top of page

Mis códigos

Por aquí algunas de ideas que he empezado a explorar con los lenguajes de programación. Si usas el código en tus trabajos académicos puedes citarlo de esta forma:

Barreto, A. (fecha del código). Nombre del código [Notebook de Google Colab]. Google Colab. https://alexgbarreto.wixsite.com/vitae/projects-6

Transcripción Total con Whisper  (22 de octubre 2025)

Este código en python utilizando google Colab, permite que descargues o cargues archivos y luego los transcribas utilizando modelos de IA.

# ============================================================

# 🎧 DESCARGA O CARGA + TRANSCRIPCIÓN AUTOMÁTICA CON WHISPER

# ============================================================

 

!pip install -q yt-dlp openai-whisper

 

from google.colab import drive, files

import yt_dlp

import os

import re

import time

import shutil

import glob

import whisper

import torch

 

# ============================================================

# 🔧 CONFIGURACIÓN INICIAL

# ============================================================

 

drive.mount('/content/drive')

drive_folder = "/content/drive/My Drive/YoutubeDownloads"

os.makedirs(drive_folder, exist_ok=True)

 

 

# ============================================================

# 🧩 FUNCIONES AUXILIARES

# ============================================================

 

def cuenta_regresiva(segundos, mensaje, default):

    print(f"\n{mensaje} (esperando {segundos}s, valor por defecto: {default})")

    for i in range(segundos, 0, -1):

        print(f"{i}...", end=" ", flush=True)

        time.sleep(1)

    print("\n⏰ Tiempo agotado, seleccionando valor por defecto.")

    return default

 

 

def limpiar_nombre(nombre):

    """Reemplaza caracteres especiales por '_'."""

    return re.sub(r'[^A-Za-z0-9]', '_', nombre)

 

 

def generar_nombre_final(nombre, es_segmento=False):

    """Genera nombre corto según reglas del usuario."""

    base = os.path.splitext(os.path.basename(nombre))[0]

    base = limpiar_nombre(base)

 

    if len(base) <= 10:

        nuevo = base

    else:

        nuevo = base[:5] + "_" + base[-4:]

 

    if es_segmento:

        nuevo += "_seg"

 

    final_path = os.path.join(drive_folder, nuevo)

 

    # Evitar duplicados

    contador = 1

    while os.path.exists(final_path + os.path.splitext(nombre)[1]):

        final_path = os.path.join(drive_folder, f"{nuevo}_{contador}")

        contador += 1

 

    return final_path

 

 

def formatear_tiempo_para_nombre(tiempo):

    """Convierte tiempos como 1:23:45 o 0:45 a formato 1h23m45s."""

    partes = tiempo.split(':')

    partes = [p.zfill(2) for p in partes]

    if len(partes) == 3:

        return f"{int(partes[0])}h{int(partes[1])}m{int(partes[2])}s"

    elif len(partes) == 2:

        return f"{int(partes[0])}m{int(partes[1])}s"

    elif len(partes) == 1:

        return f"{int(partes[0])}s"

    return tiempo

 

 

def listar_resoluciones(url):

    """Lista resoluciones disponibles para un video de YouTube."""

    ydl_opts = {'quiet': True}

    with yt_dlp.YoutubeDL(ydl_opts) as ydl:

        info = ydl.extract_info(url, download=False)

 

    formatos = []

    for f in info['formats']:

        if f.get('vcodec') != 'none' and f.get('acodec') == 'none':

            res = f.get('height')

            ext = f.get('ext')

            if res:

                formatos.append((res, ext))

 

    formatos = sorted(list(set(formatos)), key=lambda x: x[0])

    print("\n📺 Resoluciones disponibles:")

    for i, (res, ext) in enumerate(formatos, start=1):

        print(f"{i}. {res}p ({ext})")

    return formatos

 

 

def descargar_video(url, tipo, resolucion=None, seccion=None):

    """Descarga contenido de YouTube con opciones personalizadas."""

    with yt_dlp.YoutubeDL({'quiet': True}) as ydl:

        info = ydl.extract_info(url, download=False)

        titulo = limpiar_nombre(info.get('title', 'video'))

 

    etiqueta_seccion = ""

    if seccion:

        inicio, fin = seccion.split('-')

        inicio_fmt = formatear_tiempo_para_nombre(inicio)

        fin_fmt = formatear_tiempo_para_nombre(fin)

        etiqueta_seccion = f"_{inicio_fmt}-{fin_fmt}"

 

    base_nombre = f"{titulo}{etiqueta_seccion}"

 

    opciones = {

        'outtmpl': f"{drive_folder}/{base_nombre}.%(ext)s",

        'noplaylist': True,

        'merge_output_format': 'mp4',

    }

 

    if tipo == "audio":

        opciones.update({

            'format': 'bestaudio/best',

            'postprocessors': [{

                'key': 'FFmpegExtractAudio',

                'preferredcodec': 'mp3',

                'preferredquality': '192',

            }],

        })

    elif tipo == "video_sin_audio":

        opciones.update({'format': f'bestvideo[height={resolucion}]'})

    elif tipo == "video_con_audio":

        opciones.update({'format': f'bestvideo[height={resolucion}]+bestaudio/best'})

    else:

        print("❌ Tipo no válido.")

        return None

 

    if seccion:

        opciones['download_sections'] = [f"*{seccion}"]

        opciones['postprocessor_args'] = ['-ss', seccion.split('-')[0], '-to', seccion.split('-')[1]]

 

    with yt_dlp.YoutubeDL(opciones) as ydl:

        ydl.download([url])

 

    # Buscar el archivo descargado

    archivos = glob.glob(os.path.join(drive_folder, f"{titulo}*"))

    if not archivos:

        print("❌ No se encontró el archivo descargado.")

        return None

 

    archivo_descargado = max(archivos, key=os.path.getctime)

 

    # Renombrar final según reglas

    es_segmento = bool(seccion)

    base_path = generar_nombre_final(archivo_descargado, es_segmento)

    nuevo_nombre = base_path + os.path.splitext(archivo_descargado)[1]

    shutil.move(archivo_descargado, nuevo_nombre)

 

    print(f"\n✅ Archivo final: {nuevo_nombre}")

    return nuevo_nombre

 

 

# ============================================================

# 🚀 INTERFAZ INTERACTIVA

# ============================================================

 

print("¿Deseas descargar un video de YouTube o cargar un archivo desde tu dispositivo?")

print("1. 🔽 Descargar de YouTube")

print("2. 📂 Cargar archivo manualmente")

modo = input("👉 Opción (1/2): ").strip()

 

archivo_final = None

 

if modo == "1":

    url = input("🔗 Ingresa la URL del video de YouTube: ").strip()

 

    print("\nElige el tipo de descarga:")

    print("1. 🎵 Solo audio (mp3)")

    print("2. 🎬 Solo video (sin audio)")

    print("3. 📀 Video con audio")

    opcion = input("👉 Opción (1/2/3): ").strip() or cuenta_regresiva(10, "Seleccionando tipo de descarga...", "1")

 

    print("\n¿Deseas descargar todo el video o solo una parte?")

    print("1. ⏯️ Todo el video")

    print("2. ✂️ Solo una parte (indica tiempo de inicio y fin)")

    parte = input("👉 Opción (1/2): ").strip() or cuenta_regresiva(10, "Seleccionando opción...", "1")

 

    seccion = None

    if parte == "2":

        print("\nFormato de tiempo: 0:30 o 1:02:15 o 01:02:15")

        inicio = input("⏱️ Desde (inicio): ").strip()

        fin = input("🏁 Hasta (fin): ").strip()

        seccion = f"{inicio}-{fin}"

 

    tipo = "audio"

    if opcion == "2" or opcion == "3":

        resoluciones = listar_resoluciones(url)

        if not resoluciones:

            print("❌ No se encontraron resoluciones disponibles.")

        else:

            indice = input("\n📌 Elige el número de la resolución: ").strip()

            if not indice:

                print("⏰ Tiempo agotado, seleccionando 720p.")

                resolucion = 720

            else:

                indice = int(indice) - 1

                resolucion = resoluciones[indice][0]

            tipo = "video_sin_audio" if opcion == "2" else "video_con_audio"

    archivo_final = descargar_video(url, tipo, resolucion if opcion != "1" else None, seccion)

 

else:

    print("\n📂 Carga tu archivo de audio o video (mp3, mp4, wav, etc.)")

    subido = files.upload()

    nombre = next(iter(subido))

    es_segmento = False

    base_path = generar_nombre_final(nombre, es_segmento)

    nuevo_nombre = base_path + os.path.splitext(nombre)[1]

    shutil.move(nombre, nuevo_nombre)

    archivo_final = nuevo_nombre

    print(f"✅ Archivo cargado y renombrado: {archivo_final}")

 

 

# ============================================================

# 🧠 TRANSCRIPCIÓN CON WHISPER

# ============================================================

 

if archivo_final:

    modelo = input("\n🤖 Modelo de Whisper (tiny, base, small, medium, large): ").strip().lower()

    if not modelo:

        modelo = cuenta_regresiva(10, "Esperando modelo de Whisper...", "small")

 

    device = "cuda" if torch.cuda.is_available() else "cpu"

    print(f"\nCargando modelo Whisper '{modelo}' en {device}...")

    model = whisper.load_model(modelo, device=device)

 

    print("Transcribiendo...")

    result = model.transcribe(archivo_final)

    texto = result["text"]

 

    base_txt = os.path.splitext(archivo_final)[0] + ".txt"

    with open(base_txt, "w", encoding="utf-8") as f:

        f.write(texto)

 

    print("\n--- TRANSCRIPCIÓN ---\n")

    print(texto)

    print(f"\n✅ Transcripción guardada en: {base_txt}")

else:

    print("❌ No se encontró archivo para transcribir.")

Descarga Video YT (12 de marzo de 2025)

Este código en python utilizando google Colab, permite que descargues un video de YT según tus necesidades para la investigación

# ============================================================

# DESCARGA INTERACTIVA DE VIDEOS DE YOUTUBE EN GOOGLE COLAB

# ============================================================

 

!pip install -q yt-dlp

 

from google.colab import drive

import os

import yt_dlp

import re

 

# Montar Google Drive

drive.mount('/content/drive')

 

# Carpeta donde se guardarán las descargas

drive_folder = "/content/drive/My Drive/YoutubeDownloads"

os.makedirs(drive_folder, exist_ok=True)

 

 

def limpiar_nombre(nombre):

    """Conserva solo los primeros 8 caracteres del título, reemplazando caracteres especiales."""

    nombre_limpio = re.sub(r'[^A-Za-z0-9]', '_', nombre)  # Reemplaza todo lo no alfanumérico

    return nombre_limpio[:8] or "video"  # Si queda vacío, usa "video"

 

 

def formatear_tiempo_para_nombre(tiempo):

    """Convierte tiempos como 1:23:45 o 0:45 a formato 1h23m45s."""

    partes = tiempo.split(':')

    partes = [p.zfill(2) for p in partes]

    if len(partes) == 3:

        return f"{int(partes[0])}h{int(partes[1])}m{int(partes[2])}s"

    elif len(partes) == 2:

        return f"{int(partes[0])}m{int(partes[1])}s"

    elif len(partes) == 1:

        return f"{int(partes[0])}s"

    return tiempo

 

 

def listar_resoluciones(url):

    """Lista las resoluciones de video disponibles para una URL de YouTube."""

    ydl_opts = {'quiet': True}

    with yt_dlp.YoutubeDL(ydl_opts) as ydl:

        info = ydl.extract_info(url, download=False)

 

    formatos = []

    for f in info['formats']:

        if f.get('vcodec') != 'none' and f.get('acodec') == 'none':

            res = f.get('height')

            ext = f.get('ext')

            if res:

                formatos.append((res, ext))

 

    formatos = sorted(list(set(formatos)), key=lambda x: x[0])

    print("\n📺 Resoluciones disponibles:")

    for i, (res, ext) in enumerate(formatos, start=1):

        print(f"{i}. {res}p ({ext})")

 

    return formatos

 

 

def descargar_video(url, tipo, resolucion=None, seccion=None):

    """Descarga contenido de YouTube según las opciones dadas."""

 

    # Obtener título del video para generar nombre corto

    with yt_dlp.YoutubeDL({'quiet': True}) as ydl:

        info = ydl.extract_info(url, download=False)

        titulo = limpiar_nombre(info.get('title', 'video'))

 

    etiqueta_seccion = ""

    if seccion:

        inicio, fin = seccion.split('-')

        inicio_fmt = formatear_tiempo_para_nombre(inicio)

        fin_fmt = formatear_tiempo_para_nombre(fin)

        etiqueta_seccion = f"_{inicio_fmt}-{fin_fmt}"

 

    # Base del nombre final

    base_nombre = f"{titulo}{etiqueta_seccion}"

 

    # Configuración general

    opciones = {

        'outtmpl': f"{drive_folder}/{base_nombre}.%(ext)s",

        'noplaylist': True,

        'merge_output_format': 'mp4',

    }

 

    # Opciones según tipo

    if tipo == "audio":

        opciones.update({

            'format': 'bestaudio/best',

            'postprocessors': [{

                'key': 'FFmpegExtractAudio',

                'preferredcodec': 'mp3',

                'preferredquality': '192',

            }],

        })

    elif tipo == "video_sin_audio":

        opciones.update({'format': f'bestvideo[height={resolucion}]'})

    elif tipo == "video_con_audio":

        opciones.update({'format': f'bestvideo[height={resolucion}]+bestaudio/best'})

    else:

        print("❌ Tipo no válido.")

        return

 

    # Si se solicita una parte del video

    if seccion:

        opciones['download_sections'] = [f"*{seccion}"]

        # También forzamos el corte con ffmpeg en caso de streams

        opciones['postprocessor_args'] = [

            '-ss', seccion.split('-')[0],

            '-to', seccion.split('-')[1]

        ]

 

    # Descargar

    with yt_dlp.YoutubeDL(opciones) as ydl:

        ydl.download([url])

 

    print(f"\n✅ Descarga completada y guardada en: {drive_folder}")

 

 

# ============================================================

# 🚀 INTERFAZ INTERACTIVA

# ============================================================

 

url = input("🔗 Ingresa la URL del video de YouTube: ").strip()

 

print("\nElige el tipo de descarga:")

print("1. 🎵 Solo audio (mp3)")

print("2. 🎬 Solo video (sin audio)")

print("3. 📀 Video con audio")

opcion = input("👉 Opción (1/2/3): ").strip()

 

print("\n¿Deseas descargar todo el video o solo una parte?")

print("1. ⏯️ Todo el video")

print("2. ✂️ Solo una parte (indica tiempo de inicio y fin)")

parte = input("👉 Opción (1/2): ").strip()

 

seccion = None

if parte == "2":

    print("\nFormato de tiempo: 0:30 o 1:02:15 o 01:02:15")

    inicio = input("⏱️ Desde (inicio): ").strip()

    fin = input("🏁 Hasta (fin): ").strip()

    seccion = f"{inicio}-{fin}"

 

if opcion == "1":

    descargar_video(url, "audio", seccion=seccion)

elif opcion in ["2", "3"]:

    resoluciones = listar_resoluciones(url)

    if not resoluciones:

        print("❌ No se encontraron resoluciones disponibles.")

    else:

        indice = int(input("\n📌 Elige el número de la resolución: ")) - 1

        resolucion = resoluciones[indice][0]

        tipo = "video_sin_audio" if opcion == "2" else "video_con_audio"

        descargar_video(url, tipo, resolucion, seccion)

else:

    print("❌ Opción no válida.")

Separar Demucs (versión, 8 diciembre 2025)

Este código en python utilizando Google Colab, permite separar la voz, el bajo, la percusión y el resto de la pista en archivos separados. Útil para los músicos.

#  🎧 Separador de Audio 

# ==============================================================================

# ==============================================================================

 

import os

import shutil

import subprocess

import re

import glob

from google.colab import files

from google.colab import drive

 

print("⚙️ INICIANDO REPARACIÓN DE ENTORNO...")

 

# 1. Montar Drive

if not os.path.exists('/content/drive'):

    drive.mount('/content/drive')

 

# 2. Limpieza de archivos viejos

for f in glob.glob("/content/*.mp3"):

    try: os.remove(f)

    except: pass

 

# 3. INSTALACIÓN CRÍTICA (Aquí está el arreglo del error)

# Forzamos torchaudio anterior a la versión 2.6 para que no pida 'torchcodec'

print("⬇️ Instalando versiones compatibles de Demucs y Torchaudio...")

cmd_fix = 'pip install -U "demucs" "torchaudio<2.6" "soundfile"'

subprocess.run(cmd_fix, shell=True)

 

# Instalar FFmpeg

subprocess.run("sudo apt-get install -y ffmpeg", shell=True)

 

# 4. Configurar carpetas

BASE_OUTPUT_DIR = "/content/drive/MyDrive/_Strings_Studio/Demucs/separated_audio"

os.makedirs(BASE_OUTPUT_DIR, exist_ok=True)

 

print("✅ Entorno reparado y listo.\n")

 

 

# --- FUNCIONES ---

 

def generar_id_carpeta(nombre_original):

    """Genera el ID: 5 letras + _ + 2 letras + indice"""

    base = os.path.splitext(os.path.basename(nombre_original))[0]

    limpio = re.sub(r'[^a-zA-Z0-9]', '', base).lower()

 

    if len(limpio) < 7:

        nombre_base = limpio

    else:

        nombre_base = f"{limpio[:5]}_{limpio[-2:]}"

 

    contador = 0

    candidato = nombre_base

    while os.path.exists(os.path.join(BASE_OUTPUT_DIR, candidato)):

        contador += 1

        candidato = f"{nombre_base}{contador}"

    

    return candidato

 

def procesar_audio(audio_path_original):

    if not os.path.exists(audio_path_original):

        print("❌ Error: Archivo no encontrado.")

        return

 

    # 1. Preparar ID

    song_id = generar_id_carpeta(audio_path_original)

    output_folder = os.path.join(BASE_OUTPUT_DIR, song_id)

    os.makedirs(output_folder, exist_ok=True)

 

    print(f"──────────────────────────────────────────")

    print(f"🎵 Procesando:    {os.path.basename(audio_path_original)}")

    print(f"🆔 ID Generado:   {song_id}")

    print(f"📂 Guardando en:  {output_folder}")

    print(f"──────────────────────────────────────────")

 

    # 2. Renombrar input temporalmente (input seguro)

    temp_input = "/content/temp_input.mp3"

    shutil.move(audio_path_original, temp_input)

 

    # 3. Ejecutar Demucs

    print("\n⏳ Ejecutando Demucs (Separando pistas)...")

    temp_demucs_out = "/content/temp_demucs_out"

    

    # Ejecutamos Demucs estándar. 

    # NOTA: Demucs guardará los archivos como 'vocals.wav', 'drums.wav' etc.

    # No estamos forzando nombres aquí para evitar errores internos.

    cmd = f'python3 -m demucs -n htdemucs -o "{temp_demucs_out}" "{temp_input}"'

    

    # Capturamos salida para ver errores si ocurren

    resultado = subprocess.run(cmd, shell=True, capture_output=True, text=True)

 

    if resultado.returncode != 0:

        print("\n❌ DEMUCS FALLÓ OTRA VEZ. Reporte:")

        print(resultado.stderr)

        return

 

    # 4. Renombrar y Mover (AQUÍ es donde aplicamos tu lógica de nombres)

    # Buscamos dónde guardó Demucs los archivos

    path_resultados = os.path.join(temp_demucs_out, "htdemucs", "temp_input")

    

    if not os.path.exists(path_resultados):

        print("❌ Error: No se generó la carpeta de salida.")

        return

 

    print("\n📦 Renombrando y organizando...")

    pistas = os.listdir(path_resultados)

    

    for pista in pistas:

        # pista es 'vocals.wav', 'drums.wav', etc.

        origen = os.path.join(path_resultados, pista)

        

        # Aquí creamos 'milho_on_vocals.wav'

        nuevo_nombre = f"{song_id}_{pista}"

        destino = os.path.join(output_folder, nuevo_nombre)

        

        shutil.move(origen, destino)

        print(f"   ✅ {nuevo_nombre}")

 

    # 5. Limpieza

    if os.path.exists(temp_demucs_out): shutil.rmtree(temp_demucs_out)

    if os.path.exists(temp_input): os.remove(temp_input)

    

    print(f"\n✨ ¡ÉXITO! Todo guardado en carpeta: {song_id}")

 

 

# --- MENÚ ---

print("🎛️ OPCIONES:")

print("1️⃣ Descargar YouTube")

print("2️⃣ Subir Archivo")

opcion = input("👉 Opción: ").strip()

 

archivo_final = None

 

if opcion == "1":

    url = input("🔗 URL: ").strip()

    if url:

        print("\n⬇️ Descargando...")

        cmd = f'yt-dlp -x --audio-format mp3 -o "/content/%(title)s.%(ext)s" --restrict-filenames "{url}"'

        subprocess.run(cmd, shell=True)

        

        lista_mp3 = glob.glob("/content/*.mp3")

        if lista_mp3:

            archivo_final = max(lista_mp3, key=os.path.getctime)

        else:

            print("❌ Error descargando.")

 

elif opcion == "2":

    print("⬆️ Sube archivo:")

    uploaded = files.upload()

    if uploaded:

        archivo_final = list(uploaded.keys())[0]

        archivo_final = os.path.abspath(archivo_final)

 

if archivo_final:

    procesar_audio(archivo_final)

bottom of page