CommunityProgramación y desarrollogithub.com

ethan-podcast-post

Procesa grabaciones de podcasts o locuciones propias (archivos de audio local): reduce ruido, recorta silencios iniciales y finales, ecualiza y comprime la voz, normaliza la sonoridad a aproximadamente -16 LUFS y exporta a MP3; opcionalmente añade música de introducción, cierre y segmentada (tabla de cues, con validación previa); sugiere ediciones para pausas largas y segmentos marcados para regrabación, y realiza el corte según la tabla confirmada por el usuario.

¿Qué es ethan-podcast-post?

Esta habilidad transforma grabaciones de podcasts o locuciones del usuario en archivos finales listos para publicar. Realiza reducción de ruido, recorte de silencios de inicio y fin, ecualización y compresión de la voz, normalización de sonoridad a aproximadamente -16 LUFS y exportación a MP3. También puede agregar música de introducción, cierre y segmentada, y ofrece sugerencias de edición (pausas largas que se pueden acortar, segmentos regrabados) para que el usuario las confirme antes de cortar. Está diseñada para macOS y Linux, requiere `ffmpeg` y Python 3.9 o superior instalados localmente. Todo el procesamiento se realiza en la máquina del usuario, sin subir archivos a internet. El modelo de reducción de ruido (RNNoise) se descarga automáticamente la primera vez, pero si falla, se usa el filtro `afftdn` de ffmpeg. La habilidad es ideal para quienes editan sus propios podcasts y buscan un flujo de trabajo profesional pero automatizado.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Ethanyang9512/ai-creator-studio/tree/main/skills/ethan-podcast-post

Installed? Explore more Programación y desarrollo skills: steipete/bluebubbles, steipete/eightctl, steipete/blucli · View all 6 →

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Edición y masterización de podcasts

Convierte las grabaciones de podcasts o locuciones del usuario en episodios listos para publicar: reduce ruido, recorta silencios de inicio y final, ecualiza y comprime la voz, normaliza la sonoridad a aproximadamente -16 LUFS y exporta a MP3. Cuando sea necesario, añade música de introducción, cierre y segmentada, y ofrece sugerencias de edición (qué pausas largas se pueden acortar, dónde hay segmentos regrabados) que el usuario confirma antes de cortar.

Los directorios scripts/, references/ están dentro del directorio de esta habilidad. Al ejecutar, escribe las rutas completas, por ejemplo: bash <directorio_de_la_habilidad>/scripts/edit_podcast.sh.

1. Antes de empezar, explícale al usuario

  • Debe tener ffmpeg instalado (herramienta de audio gratuita y de código abierto). Si no lo tiene, pídele que lo instale: en macOS con brew install ffmpeg, en Linux con el gestor de paquetes (p. ej., apt install ffmpeg). El script busca en este orden: variable de entorno FFMPEG → ffmpeg en el PATH del sistema → ubicaciones comunes /opt/homebrew/bin, /usr/local/bin. Probado con las versiones 6.0 y 8.1.
  • Requiere bash y Python 3.9 o superior, solo biblioteca estándar, no es necesario instalar paquetes adicionales de Python.
  • Solo compatible con macOS y Linux: probado en macOS; debería funcionar en Linux; Windows requiere WSL, pero no está probado.
  • La primera reducción de ruido descargará un modelo público de aproximadamente 300 KB (RNNoise) y lo guardará en ~/.cache/ethan-podcast-post/. Después de la descarga, se verifica con SHA-256. Si no se puede descargar o la verificación falla, el script usará automáticamente el filtro afftdn incorporado en ffmpeg. El script indicará qué método usa; debes informar al usuario. El origen del modelo se encuentra en references/third-party.md.
  • Todo el proceso se realiza en la máquina local: no se sube la grabación, no hay costos.
  • Lo que no hacemos: no generamos ni clonamos voces, no doblamos, no transcribimos (si se necesitan subtítulos, el usuario debe proporcionar un archivo SRT), no publicamos en ninguna plataforma, no proporcionamos música (la música de fondo la proporciona el usuario y debe confirmar que tiene los derechos de uso).

2. Seguridad de los archivos (obligatorio)

  1. La grabación original es de solo lectura: el script solo la lee, no la modifica, no la mueve, no la elimina.
  2. Todo el resultado se escribe en un directorio nuevo: se crea un directorio junto a la grabación (p. ej., Episodio3_edicion/), sin mezclarse con la grabación o la música de fondo. El script se detiene si descubre que el directorio de salida está en el mismo directorio que el archivo de entrada.
  3. No sobrescribir sin permiso: si en el directorio de salida ya existen archivos como episodio_final.mp3, audio_raw.wav, voice_master.wav, el script se detiene para no sobrescribirlos. Para sobrescribir, primero dile al usuario qué archivos se sobrescribirán y que los archivos antiguos no se pueden recuperar; solo después de que el usuario acepte, ejecuta de nuevo con OVERWRITE=1. Lo mismo aplica para las sugerencias de edición, el corte y los scripts de procesamiento de voz: se detienen si ya existe un archivo de salida con el mismo nombre; el usuario debe aceptar antes de usar --overwrite.
  4. Confirmar antes de eliminar: cualquier eliminación (incluyendo la limpieza de archivos grandes como audio_raw.wav) debe comunicarse al usuario (qué archivo y por qué) y obtener su consentimiento antes de eliminar. Los archivos intermedios del script se colocan en un subdirectorio temporal específico de la ejecución dentro del directorio de salida; al final, solo se limpia ese subdirectorio.
  5. Lo que se corta lo decide el usuario: las sugerencias de edición son solo una lista de candidatos; no se corta nada hasta que el usuario lo confirme.

3. Flujo de procesamiento

Primero, ejecuta una comprobación del entorno e informa al usuario:

bash <directorio_de_la_habilidad>/scripts/edit_podcast.sh --check

Esto mostrará la ubicación de ffmpeg, su versión, si la ecualización dinámica de 250 Hz está habilitada (ver sección 6) y si el modelo de reducción de ruido está listo. Si no encuentra ffmpeg, indicará cómo instalarlo; primero hay que instalarlo y luego continuar.

Paso 1: Primer procesamiento, genera la master de voz y la versión de prueba

KEEP_MASTER=1 bash <directorio_de_la_habilidad>/scripts/edit_podcast.sh <archivo_de_grabación> <directorio_de_salida>/pass1 <nombre>
  • La grabación puede ser wav, m4a, mp3, mp4 o cualquier formato que ffmpeg pueda leer. Para conversaciones de dos o más personas, añade INTERVIEW_MODE=1 (compresión más fuerte y nivelación automática del volumen entre personas).
  • Orden de procesamiento: extraer a 48 kHz WAV → control de calidad → recortar silencios de inicio y final (las pausas intermedias no se tocan) → eliminar chasquidos de labios y dientes → filtro paso alto de 80 Hz → reducción de ruido → ecualización dinámica de 250 Hz → desesibilización → compresión → realce de 5 kHz → ganancia lineal a -16 LUFS → limitador → exportar a MP3 → remedición de sonoridad.
  • Resultados:
    • <nombre>_final.mp3: episodio sin música (también sirve como versión de prueba);
    • voice_master.wav: master de voz (ya recortada al inicio y final); las transcripciones, sugerencias de edición y cortes posteriores se basarán en este archivo;
    • audio_raw.wav: copia WAV de la grabación original (se escribe en el directorio de salida solo después de que todo el procesamiento haya tenido éxito); puede ser útil para rehacer, pero ocupa espacio.
  • Revisa estos elementos de la salida e informa al usuario:
    • Volumen al final por debajo de -80 dB: la grabación podría haberse interrumpido; primero confírmalo con el usuario;
    • Método de reducción de ruido: RNNoise o afftdn;
    • La sonoridad del episodio final debe estar entre -16 LUFS ±1, y el pico verdadero no debe superar -1.5 dBTP. Si se excede, el script lo indicará; díselo al usuario tal cual.
  • Si la grabación es demasiado baja o está vacía, el script generará un error y se detendrá, sin producir un episodio vacío. En el error se dará un valor sugerido basado en el pico de la grabación: primero confirma con el usuario que la grabación contiene voz; luego, ejecuta de nuevo añadiendo INPUT_GAIN=<valor_sugerido> (en dB, ya incluye el INPUT_GAIN actual) para elevar todo el segmento a un nivel normal; cuando se produce el error, no quedan archivos en el directorio de salida, por lo que se puede volver a ejecutar usando el mismo directorio. Al mismo tiempo, sugiere al usuario que en el futuro aumente el volumen de entrada al grabar.

Paso 2: Sugerencias de edición (solo lista de candidatos, no se modifica el audio)

La transcripción debe hacerse a partir del voice_master.wav del paso 1 (o del MP3 del episodio sin música del paso 1, ya que ambos tienen la misma línea de tiempo). No uses la transcripción de la grabación original: la original no tiene los silencios de inicio y final recortados, por lo que los tiempos no coincidirán y las ubicaciones encontradas serán incorrectas.

Para encontrar pausas largas que se puedan acortar:

python3 <directorio_de_la_habilidad>/scripts/edit_cuts.py suggest <directorio_de_salida>/pass1/voice_master.wav \
    [--srt subtitulos.srt] [--protect 15:00.0-15:03.0 ...]
  • Por defecto, considera como candidatas las pausas de más de 1.5 segundos y sugiere acortarlas a 1.2 segundos (dejando la mitad de la pausa a cada lado para mantener el ruido ambiental de la sala).
  • Las pausas que el usuario haya dejado intencionadamente (por ejemplo, silencio después de una frase importante) se marcan con --protect inicio-fin, dejando 0.5 segundos de margen a cada lado; no se sugerirá cortarlas.
  • Si no se encuentran pausas largas evidentes, es posible que el ruido de fondo sea alto; ajusta --noise de -45 (valor por defecto) a -40 y vuelve a ejecutar.
  • Si hay más de 15 candidatos o más de 60 segundos acumulados por cada 40 minutos de audio, el script advertirá que los parámetros son demasiado estrictos: aumenta --min-pause y no cortes todo sin criterio.

Para encontrar segmentos regrabados marcados con una palabra clave (necesita transcripción):

python3 <directorio_de_la_habilidad>/scripts/edit_cuts.py retakes <directorio_de_salida>/pass1/voice_master.wav --srt subtitulos.srt [--phrase tu_palabra_clave]
  • Convención al grabar: si te equivocas → pausa de más de 1 segundo → di la palabra clave con calma → pausa de más de 1 segundo → vuelve a decir la frase desde el principio.
  • La palabra clave por defecto es «repite repite». Para usar tu propia palabra clave, usa --phrase; si el software de transcripción suele escribir la palabra clave con homófonos, puedes usar varias veces --phrase para incluir todas las variantes. Elige una frase que no aparezca en el texto normal; decirla dos veces seguidas reduce las falsas detecciones.
  • El script busca la palabra clave en la transcripción, usa el inicio de la frase repetida para encontrar la frase incorrecta anterior y proporciona el intervalo de corte y un nivel de confianza (high / mid / low). Los de nivel «low» deben ser escuchados por el usuario para confirmar.

Ambos comandos generan voice_master_suggested_cuts.tsv y voice_master_retake_cuts.tsv respectivamente (si ya existen, no se sobrescriben; el usuario debe aceptar con --overwrite). Explica cada candidato al usuario (tiempo, contexto, cuántos segundos se ahorran). Después de que el usuario confirme qué cortes quiere, copia esas líneas en un nuevo archivo cuts.tsv (separado por tabuladores: inicio, fin, nota; el tiempo en formato MM:SS.s).

Paso 3: Corte

python3 <directorio_de_la_habilidad>/scripts/edit_cuts.py apply <directorio_de_salida>/pass1/voice_master.wav --cuts cuts.tsv [--srt subtitulos.srt]
  • Corta por muestra, con un fundido cruzado de potencia constante de 15 milisegundos en las uniones. Genera un archivo voice_master_edited.wav de 24 bits y un mapa de edición voice_master_edited.edit_map.json (que registra el origen y la posición de cada segmento conservado).
  • Si se proporciona --srt, los subtítulos completos se desplazan automáticamente; si algún subtítulo se corta por la mitad, el script se negará a ejecutarlo: elimina --srt y vuelve a ejecutar; después del corte, pide al usuario que vuelva a transcribir la master editada.
  • Después del corte, pide al usuario que escuche unos segundos alrededor de cada unión: sin chasquidos, sin dos inspiraciones, sin cambios bruscos de timbre.

Paso 4 (opcional): Cambiar la textura de la voz para citas, recuerdos, etc.

python3 <directorio_de_la_habilidad>/scripts/voice_fx.py <master_editada.wav> --fx fx.tsv
python3 <directorio_de_la_habilidad>/scripts/voice_fx.py --list     # Ver los cinco ajustes preestablecidos
  • Ajustes preestablecidos: quote (citar cartas, textos de otros), archive (periódicos antiguos, documentos antiguos), telephone (relatar una conversación telefónica), memory (recuerdos, sueños), radio (radio antigua, máximo una vez por episodio).
  • fx.tsv cada línea: ajuste, inicio, fin, fundido de entrada, fundido de salida, nota (separados por tabulador; escribe «-» para usar el valor por defecto).
  • Después del procesamiento, la duración no cambia (por muestra) y la sonoridad no cambia; el resultado es <nombre_original>_fx.wav.

Paso 5 (opcional): Música y tabla de cues

Solo se hace si el usuario proporciona música de fondo. Primero escribe la tabla de cues, luego haz una validación previa. La tabla de cues se coloca en el directorio de salida del segundo pase; el nombre del archivo debe ser <nombre>_cues.tsv.

Tabla de cues: 7 columnas separadas por tabulador. Las líneas que comienzan con # se ignoran. Escribe - en una columna para usar el valor por defecto. time se escribe en MM:SS.s, relativo a la línea de tiempo de la master de voz. Los siguientes son ejemplos:

# type	time	src	dur	vol	fade_in	fade_out
stinger	02:00.0	-	3	-	-	-
break	12:00.0	-@20	8	0.5	2	2
bed	18:00.0	-@40	30	0.08	-	-
ending	40:00.0	-@90	-	-	-	-
TipoFuncióndurVolumen por defecto
stingerUn breve fragmento musical, superpuesto a la vozPor defecto 6 segundos0.12
bed / postMúsica de fondo que se atenúa automáticamente cuando aparece la vozObligatorio0.12
breakEn ese punto, corta la voz, inserta un fragmento de música pura, y al terminar vuelve a la voz; el episodio se alarga dur segundosObligatorio0.5
endingMúsica de cierre: se atenúa mientras se habla, sube al terminar y finalmente se desvaneceEscribe -0.22
  • src escribe - para usar la música de fondo proporcionada en esta ejecución; -@20 indica empezar desde el segundo 20 de la música de fondo; también se puede escribir la ruta completa de otro archivo de música, igualmente con @segundos (sin @ se empieza desde el principio).
  • Para stinger, si src es - sin @, por defecto toma un fragmento desde el segundo 60 de la música de fondo; para otros tipos, sin @ se empieza desde el principio.
  • Después de escribir la tabla, haz una validación previa; si hay ❌, corrígelo primero:
python3 <directorio_de_la_habilidad>/scripts/cues_lint.py <nombre>_cues.tsv --master <master_editada.wav> --bg <música_de_fondo>

Esto verificará el formato, límites, existencia de materiales, superposición de ventanas y proporción total de música (se recomienda no superar el 15%). También proporciona una tabla de conversión de tiempos «master → episodio» para usarla directamente al escribir la línea de tiempo del programa.

Paso 6: Segundo pase para generar el episodio final

MASTER_WAV=<master_editada.wav> bash <directorio_de_la_habilidad>/scripts/edit_podcast.sh - [música_de_fondo] <directorio_de_salida>/final <nombre>
  • El primer parámetro es -. Cuando existe MASTER_WAV, se salta la extracción, reducción de ruido y normalización, y directamente superpone los cues, mezcla la música y exporta.
  • Si hay música de fondo y el audio dura más de 80 segundos, se añade automáticamente música de introducción y cierre: la música de introducción suena 3 segundos antes de que entre la voz; después de que termine la voz, la música se desvanece durante unos 7 segundos; cuando aparece la voz, la música se atenúa automáticamente.
  • Si no hay cortes ni música, el episodio del paso 1 es el episodio final; no es necesario ejecutar este paso.

Paso 7: Verificación

El script ya realiza una remedición al final. Para medir de forma independiente (usa la ruta de ffmpeg que se muestra con --check):

"<ruta_de_ffmpeg>" -hide_banner -nostats -i <episodio_final.mp3> -filter_complex ebur128=peak=true -f null - 2>&1 | tail -12
  • Criterios de aprobación: Integrated entre -16 LUFS ±1, True peak no superior a -1.5 dBFS (es decir, dBTP).
  • Pide al usuario que use auriculares y verifique: la música no tapa la voz; en las pausas, la música no vuelve bruscamente; cada punto de corte es natural; el final no se corta abruptamente; las pausas intencionadas siguen ahí.
  • Al entregar, informa al usuario: ubicación del episodio final, método de reducción de ruido, valores medidos de sonoridad y pico verdadero, y qué cortes se hicieron. Si no cumple los criterios, dilo tal cual, no digas que pasa.

4. Principios de edición

  • Solo corta accidentes, no respiraciones: errores al hablar, distracciones al leer el guion, segmentos regrabados inútiles se cortan; las respiraciones, los «eh» de pensamiento, las dudas entre frases y los silencios intencionados se dejan. Si no estás seguro, déjalo.
  • Las pausas de menos de 0.8 segundos no se tocan; las pausas entre frases de 0.8–1.5 segundos se dejan todas por defecto; las pausas más largas solo se acortan si hay evidencia de tartamudeo o distracción.
  • Los cortes se hacen en puntos de respiración naturales, sin dañar el inicio de una palabra ni el final de un tono; las respiraciones se dejan enteras o se eliminan por completo.
  • La música de fondo debe estar por debajo de la voz, evitando canciones con voz y piezas con mucho contenido en frecuencias medias (1–3 kHz); la música melódica se coloca preferiblemente entre párrafos (breaks), no superpuesta a la voz; la duración total de la música no debe superar el 15% del episodio.
  • Para más detalles, consulta references/editing-style-guide.md (estilo y presentación), references/editing-essentials.md (puntos clave de ejecución y verificación) y references/audio-glossary.md (glosario de términos de audio).

5. Variables de entorno (todas opcionales)

VariableValor por defectoFunción
FFMPEGBúsqueda automáticaEspecifica la ruta de ffmpeg
DENOISErnnoisernnoise / afftdn / off
RNNOISE_MODEL~/.cache/ethan-podcast-post/bd.rnnnUbicación del modelo de reducción de ruido; si ya tienes el modelo, puedes apuntar directamente a él
RNNOISE_URLModelo público en GitHubSi la red no funciona, puedes cambiarlo por una URL espejo (la descarga aún se verifica con SHA-256)
INPUT_GAIN0Aumenta (o reduce) el volumen general de la grabación antes del procesamiento en dB; si la grabación es demasiado baja, usa el valor sugerido en el error
TRIM_THRESHOLD-50Umbral para recortar silencios de inicio y final (dB); si se corta un susurro al inicio o final, bájalo, p. ej., a -60
INTERVIEW_MODE01 = conversación de dos o más personas
KEEP_MASTER01 = conservar la master de voz voice_master.wav
MASTER_WAVVacíoMaster de voz para el segundo pase
MUSIC_VOLUME0.12Proporción de volumen de la música de fondo
INTRO_DURATION40Ventana en segundos para la música de introducción y cierre; si el audio es más corto que el doble de este valor, no se añade
PREROLL / TAIL3 / 7Segundos de música de introducción antes de la voz / segundos de música después de que termine la voz
OUTRO_SEEKVacíoDesde qué segundo de la canción se toma la música de cierre
MP3_BITRATE160kTasa de bits del episodio final
OVERWRITE01 = permitir sobrescribir archivos finales existentes (primero obtener el consentimiento del usuario)

6. Preguntas frecuentes

  • No encuentra ffmpeg: pide al usuario que lo instale (macOS brew install ffmpeg, Linux con el gestor de paquetes), o especifica la ruta con FFMPEG=/ruta_completa/ffmpeg.
  • Versión de ffmpeg: el script lee el número de versión. El significado de los parámetros en el nivel de ecualización dinámica de 250 Hz cambió entre ffmpeg 6 y 8; ambas versiones se han calibrado con señales sinusoidales y el efecto es consistente; con versiones no verificadas como 7.x, se omitirá este nivel y se mostrará un aviso; el resto del procesamiento continúa con normalidad. Los parámetros para recortar silencios de inicio y final también se han ajustado para el comportamiento de las versiones nuevas; 6.x y 8.x cortan de la misma manera.
  • Error «Después de recortar silencios de inicio y final, no queda casi nada» o «No se puede medir la sonoridad después del procesamiento»: la grabación es demasiado baja o está vacía. Después de confirmar que hay voz, ejecuta de nuevo con el valor sugerido de INPUT_GAIN del error (si la sonoridad está por debajo de -70 LUFS, no se puede medir; solo ajustar el umbral de recorte no es suficiente); si realmente no hay sonido en la grabación, el error se repetirá y no se generará un episodio vacío.
  • La reducción de ruido usó afftdn: significa que el modelo no se descargó correctamente. Puedes configurar RNNOISE_URL para usar un espejo, o usar RNNOISE_MODEL para apuntar a un archivo de modelo existente, y luego volver a ejecutar (pregunta al usuario antes de sobrescribir archivos finales existentes).
  • Volumen al final por debajo de -80 dB: la grabación probablemente se interrumpió; primero confírmalo con el usuario, no lo trates como un problema de edición.
  • No se encontró ningún segmento regrabado: confirma que la transcripción se hizo a partir de voice_master.wav, y luego revisa cómo se escribió la palabra clave en la transcripción; añade esa variante con --phrase.
  • Quiero ver el comando de cada paso: bash -x <directorio_de_la_habilidad>/scripts/edit_podcast.sh ....
  • Al escribir parámetros de filtros de ffmpeg en zsh: cuando una variable va seguida inmediatamente de dos puntos, escríbela como ${VAR}:...; de lo contrario, zsh interpretará $VAR:a, $VAR:r como modificadores y los parámetros se modificarán silenciosamente.

Licencia: código MIT, documentación CC BY 4.0.

Skills relacionados