Communitygithub.com

0xSero/video-edit

Limpia una grabación en bruto de pantalla/OBS/charla y la convierte en un video profesional listo para subir: cortes basados en transcripción, eliminación de silencios y estática visual, protección de momentos personales, redacción de filtraciones en pantalla, mejora de audio, apertura impactante, renderizado verificado, y luego capítulos/título/etiquetas/descripción/subtítulos/miniatura, entregado en ~/Descargas y abierto. Úsalo cuando el usuario diga "edita el video que grabé", "quita los silencios", "elimina las partes embarazosas", "asegúrate de que no se filtre nada", "déjalo listo para YouTube". No es para crear videos promocionales o de motion graphics a partir de diapositivas; las miniaturas solas van a youtube-pack.

¿Qué es video-edit?

Esta skill está diseñada para agentes de IA como Claude Code o Cursor que necesitan procesar grabaciones de pantalla, OBS o charlas, transformándolas en videos profesionales listos para plataformas como YouTube. El flujo de trabajo es altamente automatizado pero con pasos explícitos y verificables: desde la transcripción (mlx_whisper), análisis de estática visual (detección de cambios de fotogramas), eliminación de filtraciones (OCR en fotogramas clave y en el video final), mejora de audio (DeepFilterNet3), hasta la generación de metadatos (capítulos, títulos, etiquetas, subtítulos) y miniaturas. La skill soporta macOS (Apple Vision para detección de manos, pyobjc) y requiere ffmpeg, Python3 y varias librerías. El resultado final es un archivo MP4 verificado, sin filtraciones, con dos pistas de audio (mejorada y original), subtítulos y metadatos, entregado en ~/Descargas y abierto automáticamente. La skill se compone de scripts en scripts/ (prep.sh, transcript_txt.py, ocr_scan.py, cam_flags.py, df_enhance.py, build_edl.py, render.py, verify_output.py, chapters.py, overview.py, job.example.json, selftest.sh) que se ejecutan desde una copia en el directorio de trabajo.

Compatible con~Claude Code~Codex CLI✓Cursor
npx skills add https://github.com/0xSero/video-edit/tree/HEAD

Preguntar en tu IA favorita

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

Documentación

Edición de video (grabación de pantalla / OBS / charla)

Kit de scripts: scripts/ en esta skill (prep.sh, transcript_txt.py, ocr_scan.py, cam_flags.py, df_enhance.py, build_edl.py, render.py, verify_output.py, chapters.py, overview.py, job.example.json, selftest.sh). Ejecútalos desde una copia en <workdir>/scripts/ para que un trabajo nunca dependa del directorio de la skill. scripts/selftest.sh demuestra una instalación completa en un par de minutos.

Entradas

  • <src>: la grabación, normalmente el más reciente ~/Desktop/*.mov (nomenclatura de OBS YYYY-MM-DD HH-MM-SS.mov). Si hay varias grabaciones recientes, confirma cuál ANTES de iniciar el largo pipeline; editar el video equivocado desperdicia una hora.
  • <target_minutes>: pregunta si no se proporciona; normalmente 20-30 a partir de una fuente de 45-90 min.
  • <workdir>: directorio temporal nuevo, ej. /tmp/<session>/edit.
  • Cadena de herramientas: ffmpeg 6+, python3, mlx_whisper, DeepFilterNet3, Pillow/numpy/soundfile, Apple Vision (pyobjc-framework-Vision/-Quartz).

Pasos

  1. Reconocimiento, nunca tocar la fuente. ffprobe <src> (resolución, fps, audio). Trabaja solo con copias/extracciones en <workdir>.
  2. Preparación. prep.sh "<src>" $W: orig48.wav, mono16.wav, frames/ (1 cada 2 s), camall/ (recorte de webcam a 1 fps, geometría derivada automáticamente de la resolución), sheet_overview.jpg, silences_raw.txt (solo diagnóstico), y transcript.json (mlx_whisper large-v3-turbo, marcas de tiempo por palabra, ~4 min). Whisper sigue ejecutándose en segundo plano después de que prep regresa; inicia df_enhance.py orig48.wav df_enhanced.wav (DeepFilterNet3, ~6 min CPU) AHORA, es independiente.
  3. Lee toda la transcripción (3 fragmentos mediante transcript_txt.py ... --from/--to). Escribe los rangos a conservar (segundos de la fuente) en job.json -> keep. El recorte de silencios es menor (~2 de 47 min); los minutos reales provienen de decisiones de contenido. Whisper se informa a sí mismo: una frase repetida 10+ veces o segmentos vacíos = tiempo muerto, córtalo.
  4. Paso de estática visual. "No pasa nada" a menudo es estático visual, NO silencio. Diferencia de fotogramas en los frames a 0.5 fps: <1% de píxeles cambiados en una ventana de ~10 s = inactivo; fusiona ejecuciones separadas por destellos <=1 s; requiere >=4 s para cortar; 0.5 s de manejo. Cursores parpadeantes/spinners simulan actividad: enmascara o eleva el umbral; verifica fotogramas intermedios en busca de ráfagas de cambio-y-reversión. La escritura es ruido, no silencio: las compuertas usan RMS en la pista mejorada (pause.loud_db), nunca silencedetect en bruto.
  5. Apertura. Corta todo antes del primer contenido real. Si el inicio es lento/aburrido, comienza con la demo más interesante; opcionalmente abre con 1-2 clips emocionantes y luego acelera la introducción. Nunca abras con fondo de pantalla/negro: unos primeros 30 s entrecortados se leen como basura.
  6. Escaneo de filtraciones (se ejecuta mientras lees). ocr_scan.py scan después de run en frames/: IPv4/v6, *.ts.net, correos electrónicos, claves API, material SSH. Pase denso a 2 fps en cada rango de terminal/configuración densa (ocr_scan.py dense src.mov dense 600:60 ...). Texto estático -> boxes (relleno sólido); salida de terminal con desplazamiento -> desenfoca todo el panel (blur ventana + blur_regions, en píxeles de origen) para la ventana; las cajas por línea pierden texto entre muestras. 127.0.0.1/localhost están bien. Registra cada ventana en job.json.
  7. Cortes de privacidad (webcam). cam_flags.py (mano cerca de la boca mediante Vision) + cam_flags.py --sheet S:DUR hojas ampliadas a 2 fps de cada grupo marcado. Corta los momentos que el usuario no publicaría: mano en la cara durante una pausa, salir del escritorio, otra persona en el encuadre, segmentos de rostro a pantalla completa. Las poses de pensamiento normales y los gestos pequeños están bien. NUNCA cortes a mitad de una frase por un gesto; salta al límite de oración más cercano y anota lo que se perdió.
  8. Los cortes basados en marcas de tiempo del usuario son literales. "corta 0000 - 01:12" -> ponlo en job.cuts (o keep), aplícalo exactamente, luego vuelve a verificar el ritmo alrededor de la unión.
  9. Maestría de audio. Sanidad: correlación mejorado-vs-original > 0.95 (df_enhance.py lo imprime). La audio_chain predeterminada es paso alto 75, cortes/refuerzos alrededor de 220 Hz / 3.2 kHz / 9 kHz, de-esser, compresor 3:1; elimina cualquier tono de ventilador persistente añadiendo un término equalizer; render.py hace la normalización de dos pasos loudnorm a -16 LUFS / -1.5 dBTP. El micrófono sin procesar se mantiene como pista de audio 2.
  10. EDL + renderizado. build_edl.py -> segments.json (pausas >0.7 s dentro de los keep acortadas a 0.4 s; ajustadas a la velocidad de fotogramas probada; <0.3 s eliminadas). render.py: codificaciones h264_videotoolbox paralelas agrupadas, concat -c copy, multiplexa ambas pistas. Es reiniciable por grupo: si un grupo falla, arréglalo y vuelve a ejecutar, los grupos no modificados se saltan. Entrega 1080p a menos que se pida otra cosa (4K duplica el tiempo de renderizado para nada).
  11. Verificar antes de entregar. verify_output.py sale con código distinto de cero a menos que el recuento de fotogramas coincida con el EDL, ambas pistas de audio coincidan con la duración del video, y el OCR de la salida a 4 fps en cada ventana de redacción encuentre cero filtraciones. También extrae fotogramas de salida en cada corte de privacidad y en 0:00-1:00 y MÍRALOS. Usa --full para un barrido completo de filtraciones cuando el material sea sensible.
  12. Vuelve a transcribir el nuevo corte. La transcripción, los subtítulos y los capítulos deben coincidir con la línea de tiempo de SALIDA, no con la fuente: vuelve a ejecutar whisper en el corte (o chapters.py, que reasigna a través del EDL) antes de escribir SRT/capítulos. Nunca envíes tiempos de SRT tomados de la transcripción fuente.
  13. Metadatos + entrega. Sin que te lo pidan dos veces: marcas de tiempo de capítulos (chapters.py, >=3, primero en 0:00), 2-3 opciones de título, ~30 etiquetas con menos de 500 caracteres (+2 variantes de etiqueta/descripción si se solicita), descripción, SRT por idioma (~42 caracteres/línea; multilingüe si se solicita), todo como texto plano. Miniatura mediante youtube-pack: lee las últimas 10 miniaturas del usuario para conocer el estilo; fondo blanco/crema por defecto + texto negro, sin rostro a menos que se solicite, logotipos/texto grandes y sin saturar. Luego mueve <output>.mp4 (y SRTs/metadatos) a ~/Descargas y open el archivo / abre la carpeta en la aplicación predeterminada.

Salidas

  • <Topic> - YYYY-MM-DD - edit.mp4 (1080p, 2 pistas de audio) en ~/Descargas, abierto en la aplicación predeterminada.
  • <workdir>: job.json, segments.json, group_bounds.json, vf_<n>.txt, registros de redacción/privacidad.
  • ~/Descargas: SRTs, metadata.txt (títulos, descripción, etiquetas, capítulos).
  • Opcional si se solicita: subvideos temáticos divididos de la misma fuente, cada uno con sus propios capítulos.

Se compone con

whisper/DFN3 (en kit) -> video-edit (mp4 verificado en ~/Descargas) -> youtube-pack (thumbnail.png) -> subida al navegador a YouTube Studio configurado como los otros videos del usuario.

Reglas

  • Nunca modifiques la grabación fuente.
  • La duración objetivo es un objetivo; si el contenido no se reduce sin desvirtuar la charla, entrega ligeramente por encima y nombra los dos siguientes cortes.
  • Corta digresiones completas antes de recortar más pausas; mantén la charla técnica, las demos en vivo, las salvedades honestas, el resumen.
  • Termina siempre con: mover a ~/Descargas + abrir.
  • Informa fielmente: no puedes oír el resultado, dilo y señala la pista 2.
  • El audio grabado por separado (Discord/Craig) normalmente no existe; revisa Escritorio/Descargas/iCloud/Notas de Voz, si no está, usa el micrófono de OBS y dilo.
  • Cuando te pidan liberar espacio: elimina borradores/variantes antiguos no aceptados, conserva la fuente y el final.
  • Podcasts con varias personas: encuentra las pistas de audio CORRECTAS (normalmente 2 de muchas), asigna el audio al orador correcto, alterna el video con la persona que habla, transiciones limpias.
  • Nunca afirmes que la edición está completa porque el renderizado terminó; solo verify_output.py + fotogramas revisados visualmente lo confirman.

Verificación

  • verify_output.py imprime PASS (recuento de fotogramas, dos pistas de audio, sin filtraciones en ventanas) y sale con 0.
  • Fotogramas revisados visualmente en 0:00-1:00 y en cada corte de privacidad (verify_output.py --sheet 0:60).
  • Verificación puntual de la re-transcripción SRT contra el corte.
  • ffprobe del archivo entregado: duración, resolución, fps, 2 flujos de audio.

Fallos conocidos

  • Video equivocado editado -> confirma que el más reciente/tema coincida antes del pipeline.
  • Subtítulos/capítulos en la línea de tiempo fuente -> vuelve a transcribir después del corte (paso 12).
  • Nombre de host visible en la salida -> texto desplazándose entre muestras de OCR; desenfoca todo el panel, amplía la ventana, luego OCR del lado de la salida.
  • Silencedetect corta la escritura/reproducción de video -> compuerta basada en RMS de audio mejorado (pause.loud_db), no solo silencio.
  • Apertura negra entrecortada -> verifica fotogramas de salida 0:00-1:00, abre con contenido real.
  • cp -i solicita sobrescritura / el sandbox TCC bloquea ~/Descargas -> usa /bin/cp con sandbox desactivado.
  • El filtro ffmpeg muere ("Cannot allocate memory") pasadas ~100 cláusulas between() -> menos render_groups.
  • El cursor parpadeante cuenta como actividad en la diferencia de fotogramas -> enmascara/ajusta el umbral, verifica fotogramas intermedios.
  • render.py desajuste de fotogramas -> se niega a concatenar; lee render_<n>.log (-ss antes de un keyframe, decodificador roto).
  • Whisper aún se ejecuta cuando lees transcript.json -> transcript_txt.py reporta segmentos vacíos; espera a que whisper.log termine.

Ejemplos

  • Charla del 2026-09-02, 47 min -> 26 min: 32 rangos keep, 2 cortes de privacidad (9:52-9:58, 26:08-26:14), 2 ventanas blur + 1 box para un nombre de host *.ts.net, renderizado ~2 h de reloj, filtración detectada solo por OCR del lado de la salida.
  • Sesión de enseñanza OBS del 2026-09-24: el usuario rechazó el primer corte ("ruido de fondo, escritura, comienzo muy aburrido") -> se eliminó el ruido de escritura, se eligió una mejor apertura, se rehicieron las transcripciones, luego corte literal de cabeza 0:00-1:12, escaneo de filtraciones, miniatura blanca/crema con logotipos más grandes, 2 variantes de metadatos, se movió a Descargas.
  • Podcast (2026-09-18): 1h40m de video + 5 archivos de audio candidatos -> se identificaron las 2 pistas correctas por orador, se mapeó la voz al video, 1080p, recorte de cabeza, SRT + traducciones ES/AR/HI, marcas de tiempo de capítulos, miniatura con ambos oradores, texto en la parte superior, sin fondo negro.

Skills relacionados