AudioSnipLine es un side project engineering-first construido para convertir videos de YouTube a MP3 (con recorte opcional por ventana temporal) y generar un JSON de metadata por corrida, orientado a trazabilidad y linaje (data lineage) en flujos de trabajo de datos.
El proyecto está diseñado como un mini-pipeline: una UI en Streamlit (app.py) y un motor desacoplado (core.py) que orquesta yt-dlp + ffmpeg en un workspace efímero. El servidor no persiste artefactos en un directorio “final”: el MP3/JSON se generan temporalmente, se cargan a memoria y se entregan al usuario vía descargas.
- Engineering-first: separación UI / lógica de negocio, validaciones explícitas, naming determinista.
- Outputs portables: MP3 + JSON; el JSON es un “compañero” natural del audio para auditoría.
- Sin persistencia final en servidor: los artefactos se generan en un directorio temporal por ejecución y se devuelven como bytes para descarga.
- Calidad “best effort”: el pipeline intenta la mejor fuente de audio disponible y cae a alternativas cuando es necesario.
- ✅ Descarga de audio desde YouTube usando
yt-dlpcon estrategia de fallback:bestaudio[ext=m4a] / bestaudio / best[ext=mp4] / best
- ✅ Recorte opcional de audio durante el proceso (sin pasos manuales posteriores):
STARTyENDen formatomm:ssohh:mm:ss- Validación: END > START (cuando ambos están presentes)
- ✅ Extracción a MP3 vía FFmpeg (
FFmpegExtractAudio) con calidad alta por defecto (V0). - ✅ Saneamiento de nombres de archivo (para evitar caracteres problemáticos y lograr determinismo).
- ✅ Descargas desde la UI:
- ZIP (MP3 + JSON)
- MP3 individual
- JSON individual
- ✅ JSON de metadata por audio (limpio, sin duplicados innecesarios).
1) UI (Streamlit) — app.py
- Captura inputs: URL, nombre opcional, ventana temporal (START/END).
- Dispara el procesamiento.
- Renderiza resultados en el orden:
- Resultado
- Tamaños (MP3/JSON/ZIP)
- Descargas
- Metadata
2) Motor — core.py
- Normaliza y valida tiempos (
mm:ss→hh:mm:ss; END > START). - Resuelve naming seguro (y cachea
download=Falsepara rapidez en reruns). - Ejecuta
yt-dlp+ffmpegen unTemporaryDirectory. - Retorna:
metadata(dict)mp3_bytesjson_bytes
3) Entrega
- El servidor no guarda archivos “finales”.
- La UI construye un ZIP en memoria y habilita descargas.
.
├── app.py # UI Streamlit
├── core.py # Motor: yt-dlp + ffmpeg + metadata
├── requirements.txt
├── LICENSE
└── README.md
- Python: recomendado 3.11+ (debería funcionar en 3.10+, pero 3.11+ es la base sugerida).
- FFmpeg: instalado y disponible en
PATH. - Dependencias Python:
streamlityt-dlp
Verificación rápida
python --version
ffmpeg -versiongit clone https://github.com/<TU_USUARIO>/audiosnipline.git
cd audiosniplinepython -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
pip install -r requirements.txtpython -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
pip install -r requirements.txtbrew install ffmpeg
ffmpeg -versionsudo apt-get update
sudo apt-get install -y ffmpeg
ffmpeg -versionWinget
winget install Gyan.FFmpeg
ffmpeg -versionChocolatey
choco install ffmpeg
ffmpeg -versionSi
ffmpeg -versionno funciona, el problema casi siempre es PATH.
streamlit run app.pyAbre el navegador en la URL que Streamlit muestre en consola (típicamente http://localhost:8501).
- URL de YouTube: obligatorio
- Nombre del archivo de salida (opcional):
- Si lo dejas vacío, se usa el título original del video (sanitizado).
- Si lo defines, se genera
CUSTOM_NAME.mp3yCUSTOM_NAME.json.
- START / END (opcional):
- Formatos soportados:
mm:ssohh:mm:ss - Ejemplos:
04:34,00:04:34,10:27 - Si defines ambos, se valida END > START.
- Formatos soportados:
Cuando el proceso finaliza, la UI ofrece:
- ZIP:
{basename}.zipcontiene:{basename}.mp3{basename}.json
- Descargas individuales:
- MP3
- JSON
Importante: el servidor no persiste un directorio de salida “final”.
Los artefactos existen temporalmente durante la ejecución y luego se entregan como bytes.
Ejemplo típico:
{
"url": "https://www.youtube.com/watch?v=...",
"execution_ts": "20251230235528",
"video_id": "obyArPUIffg",
"original_video_title": "Ultimo video",
"mp3_filename": "Mi_Audio.mp3",
"json_filename": "Mi_Audio.json",
"used_custom_filename": true,
"used_trim": true,
"start_input": "04:34",
"end_input": "10:27",
"speakers_count": null,
"language": null,
"language_code": null,
"success": true,
"error": null,
"mp3_size_bytes": 7609846
}Notas:
speakers_countes opcional: si no se especifica, queda ennull.languageylanguage_codeson opcionales: si no se seleccionan, quedan ennull.languagese guarda en inglés (por ejemplo:Spanish,English,Korean).language_codese guarda como acrónimo común (por ejemplo:es,en,ko).
original_video_titlemantiene el título original para trazabilidad (aunque uses nombre custom).start_input/end_inputguardan exactamente lo que el usuario escribió.success/errorpermiten auditoría y debugging rápido.
- Asegura que FFmpeg está instalado y en el
PATH:ffmpeg -version
YouTube cambia con frecuencia. Si tienes fallos intermitentes:
- Actualiza
yt-dlp:pip install -U yt-dlp
- Verifica si el video requiere autenticación/edad/región.
- Prueba con otra URL para descartar restricciones del contenido.
- Revisa formato de
START/END(mm:ss o hh:mm:ss). - Si
END <= START, la app debe fallar con validación.
AudioSnipLine es una herramienta técnica. Asegúrate de respetar derechos de autor, licencias y los términos aplicables del contenido que proceses.
Alejandro Henao Ruiz
- GitHub: https://github.com/ahenaor
- LinkedIn: https://www.linkedin.com/in/ahenaor/