Communitygithub.com

video-cut

Convierte un video largo sin editar en un primer corte compacto y visible, con decisiones editoriales humanas y precisión mecánica automatizada.

¿Qué es video-cut?

La habilidad 'video-cut' está diseñada para tomar un video largo y sin editar (ya sea una URL de YouTube o un archivo local) y producir un 'primer corte' compacto y visible. El humano (tú) toma las decisiones editoriales sobre QUÉ conservar, mientras que los scripts automatizados se encargan de la precisión mecánica, como el alineamiento de límites, la eliminación de silencios, la renderización segura en memoria y la autoverificación. Es ideal para reducir la duración del video a la mitad, eliminar partes aburridas o crear un corte preliminar. No es adecuado para microcirugía de muletillas palabra por palabra, ensamblaje multicámara o corrección de color/audio, ya que esas tareas son para una etapa de pulido posterior. Depende de la habilidad '/video-understand' como requisito previo, que debe ejecutarse primero para obtener el medio validado, la transcripción, el análisis y la línea de tiempo. El flujo de trabajo principal utiliza archivos de proyecto duraderos y scripts para transcribir, analizar, construir el plan de edición, asignar velocidad variable y generar la línea de tiempo final. La habilidad admite compatibilidad independiente con scripts heredados y entrega un archivo de video 'first_cut.mp4' junto con un informe de edición y autoverificación.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/WhiteTowerAI/cut-as-code/tree/main/skills/video-cut

Preguntar en tu IA favorita

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

Documentación

Video Cut

Convierte un video largo sin editar en un primer corte compacto y visible: decisivo, consciente del contenido y autoverificado. El humano (tú, el modelo) toma la decisión editorial de QUÉ conservar; los scripts incluidos realizan la precisión mecánica (alineación de límites, recuperación de silencios, renderizado seguro en memoria, autoverificación).

Cuándo usarlo

  • Un video sin procesar/sin editar (URL de YouTube o archivo local) necesita convertirse en un corte más ajustado.
  • La solicitud es "redúcelo a la mitad", "corta las partes aburridas", "haz un primer corte/borrador".
  • NO para: microcirugía de muletillas palabra por palabra, ensamblaje multicámara con material adicional, pulido de color/audio — esas son una pasada de pulido P1/P2 posterior. Esta habilidad es P0: validar el diagnóstico y producir un corte sólido.

Dependencias

/video-understand es un requisito previo. Ejecútalo primero y utiliza su contenido multimedia validado, transcripción, análisis y línea de tiempo en lugar de recrearlos en esta habilidad. Antes de comenzar, verifica que esté instalado. Si no es así, advierte al usuario que falta este requisito previo y detente antes de procesar el contenido.

Activa cualquier entorno que tenga estos (NO asumas un nombre específico de conda env):

  • yt-dlp (descarga), ffmpeg/ffprobe (corte/renderizado/exploración) en PATH
  • Python con faster-whisper (CPU funciona: device=cpu, compute_type=int8) Verifica primero: yt-dlp --version, ffmpeg -version, python -c "import faster_whisper".

Flujo de trabajo del protocolo del proyecto

Utiliza estos archivos de proyecto duraderos:

work/cut/edit-plan.json          # decisiones de conservar/eliminar solo escritas a mano
work/timeline.json               # rangos de precisión generados + mapeo de fuente/programa
review/01-cut/cut-summary.md
review/01-cut/timeline-map.png
review/01-cut/boundary-review.mp4
review/01-cut/full-proxy.mp4  # revisión opcional del ritmo de todo el programa

Cada decisión canónica tiene un id estable, action (keep o drop), start_s, end_s, reason y referencias de evidencia semántica/de transcripción evidence_refs. Las decisiones de conservar son cronológicas; V1 no admite clips fuente reordenados o duplicados.

Reutiliza la capa de evidencia compartida en lugar de transcribir o diagnosticar nuevamente:

python skills/video-understand/scripts/transcribe.py work/cache/audio16k.wav work/understand/transcript
python skills/video-understand/scripts/analyze.py work/understand/transcript.json work/understand/analysis.json

Los scripts de precisión existentes aceptan el plan canónico. Expande los límites seguros para las palabras, asigna opcionalmente velocidad variable lineal, luego genera la línea de tiempo compartida:

python skills/video-cut/scripts/build_edit.py work/cut/edit-plan.json work/understand/transcript.json work/cache/edit-final.json
python skills/video-cut/scripts/assign_speed.py work/cache/edit-final.json work/understand/transcript.json
python skills/video-understand/scripts/build_timeline.py work/cache/edit-final.json work/timeline.json --fps-num SOURCE_FPS_NUM --fps-den SOURCE_FPS_DEN

Usa el FPS racional exacto de work/understand/media.json; nunca redondees 30000/1001 a 30/1. Revisa timeline-map.png y el breve boundary-review.mp4. Genera full-proxy.mp4 solo cuando sea necesario revisar el ritmo de todo el programa. Escribe el resultado en cut-summary.md y apunta el informe de verificación de la operación a ese archivo.

Registra la contribución de la línea de tiempo con su entrada fuente requerida, actualiza el entero de operación revision y establece based_on en la revisión exacta de comprensión consumida:

"render": {
  "kind": "timeline-transform",
  "input": "../input/original-video.mp4",
  "plan": "timeline.json"
}

El renderizador de entrega compartido codifica la secuencia activa después de que pasen todas las comprobaciones de revisión.

Flujo de trabajo de compatibilidad independiente

Los archivos y comandos heredados a continuación siguen siendo compatibles durante la migración. build_edit.py acepta tanto edit_coarse.json como decisions[] canónicos; cut_render.py acepta tanto edit_final.json como timeline.json; el transcribe.py de esta habilidad es un envoltorio de compatibilidad alrededor de ../video-understand/scripts/transcribe.py.

Mantén todos los archivos intermedios bajo work/, entrega en la raíz del proyecto:

work/source.mp4            # original descargado
work/audio16k.wav          # audio mono de 16k para whisper
work/transcript.json/.srt  # marcas de tiempo a nivel de palabra
work/analysis.json         # diagnóstico (silencios/muletillas/racha)
work/edit_coarse.json      # *** TU decisión editorial (escrita a mano) ***
work/edit_final.json       # segmentos de renderizado ajustados expandidos (generados; lleva velocidad por segmento)
work/selfcheck/            # retranscripción del corte + fotogramas de unión
first_cut.mp4              # EL ENTREGABLE
first_cut_report.md        # informe de edición + autoverificación

El pipeline (6 pasos)

1. Descarga

La más alta calidad accesible + audio. El cliente reproductor predeterminado a menudo falla (no disponible/DRM/inicio de sesión). La alternativa confiable es el cliente de android:

yt-dlp --extractor-args "youtube:player_client=android" \
       -o work/source.mp4 "<URL>"

Si solo se puede acceder a un muxed 360p (formato 18) sin inicio de sesión, acéptalo y documenta la limitación — HD DASH a menudo está bloqueado por DRM/inicio de sesión. Luego extrae el audio:

ffmpeg -y -i work/source.mp4 -ac 1 -ar 16000 work/audio16k.wav

2. Transcripción (a nivel de palabra)

python scripts/transcribe.py work/audio16k.wav work/transcript [base.en]

Produce work/transcript.json (segmentos + inicio/fin por palabra) y .srt. faster-whisper, CPU/int8, VAD activado, word_timestamps=True. No inglés: pasa un modelo multilingüe + --lang, p.ej. python scripts/transcribe.py work/audio16k.wav work/transcript medium --lang zh (los modelos .en son solo inglés). Verifica el idioma en una muestra corta primero. Nota: Whisper elimina la mayoría de los "em/eh" vocalizados — NO son medibles por transcripción, por lo que la detección de muletillas debe combinar la búsqueda de palabras léxicas a continuación con el análisis de brechas de silencio, no confiar solo en el texto de la transcripción.

3. Diagnosticar ("ver" + "leer")

python scripts/analyze.py work/transcript.json work/analysis.json

Superficies: silencio inicial/final, silencios entre palabras ≥0.8s (con la palabra que siguen), recuento de muletillas, ppm, ratio_de_habla, repeticiones casi duplicadas, rachas de monólogo >40s (candidatos a divagación).

Para ver la imagen, muestrea un fotograma cada ~2s en una hoja de contactos y léela tú mismo; confirma la estructura de la escena / busca fotogramas negros o basura:

ffmpeg -y -i work/source.mp4 -vf "fps=1/2,scale=240:-1,tile=10x10" -frames:v 1 work/contact.png
ffmpeg -i work/source.mp4 -vf "blackdetect=d=0.1:pic_th=0.98" -an -f null -

Para una sola toma de cabeza parlante estática no hay cortes de escena — espera esto y ten en cuenta que los cortes de salto posteriores son normales, no fallos.

4. Decide el corte — escribe edit_coarse.json A MANO

Este es el núcleo editorial. Lee la transcripción + el análisis, luego escribe un plan general de bloques a conservar y espacios a eliminar que cubran toda la línea de tiempo sin espacios/superposiciones, cada uno con in, out y una reason de una línea. Comprime el preámbulo lento a unas pocas pepitas de alto valor; conserva la sustancia como bloques grandes; elimina las tangentes/divagaciones claras. Preserva el orden cronológico; la línea de tiempo canónica V1 rechaza el reordenamiento. Apunta a reducir aproximadamente a la mitad la duración.

  • Especificación de formato + un ejemplo real trabajado: reference/edit_coarse.schema.md.
  • Alinea cada límite de bloque con un final de oración/cláusula — nunca inicies/detengas en medio de una oración o en un tartamudeo. Usa:
    python scripts/inspect_bounds.py work/edit_coarse.json work/transcript.json
    
    Acepta tanto los planes keep[] heredados como los canónicos decisions[] e imprime las palabras que se superponen en cada límite para que puedas moverlas a bordes limpios.

5. Expandir → velocidad automática → renderizar

Convierte los bloques generales en segmentos de renderizado ajustados y sin silencios, normaliza el ritmo de habla, luego renderiza:

python scripts/build_edit.py   work/edit_coarse.json work/transcript.json work/edit_final.json 1.5
python scripts/assign_speed.py work/edit_final.json   work/transcript.json   # añade velocidad por segmento
python scripts/cut_render.py    work/edit_final.json   work/source.mp4 first_cut.mp4
  • build_edit.py divide cada bloque en pausas internas > SPLIT_GAP (4to argumento, p.ej. 1.5s) y recorta cada límite DENTRO del silencio (LEAD 0.10s / TRAIL 0.30s) para que ninguna palabra se recorte y se recupere el silencio muerto. SPLIT_GAP más bajo = más ajustado pero más entrecortado; para un hablante lento y deliberado prefiere ~1.5, no 0.6 (evita microcortes nerviosos).
  • assign_speed.py (velocidad variable automática) — agrupa segmentos de renderizado por decision_ref, mide el ritmo de habla de cada decisión de conservar escrita a mano y escribe un factor de speed compartido más el out_dur resultante de cada segmento de vuelta en edit_final.json. El ritmo ya dentro de la banda cómoda permanece en 1.0; el ritmo fuera de banda se mueve solo al borde de la banda muerta más cercano. Los bloques de decisión adyacentes difieren en no más de 0.08x para evitar uniones "bombeantes". Cambia solo el ritmo, nunca qué contenido se conserva. Lee la tabla impresa antes de renderizar:
    • Métrica: palabras/min (inglés) — cambia automáticamente a caracteres/min para CJK (zh/ja/ko).
    • Los valores predeterminados son puntos de partida para la primera ejecución, no constantes validadas: banda muerta 145–185 PPM y velocidad limitada a 1.0–1.3. Esto es solo aceleración: los bloques de decisión lentos se pueden ajustar, mientras que la entrega naturalmente rápida permanece en 1.0. Los bloques de decisión cortos (<3.5s / <6 palabras) son demasiado ruidosos para medirlos y heredan el factor global.
    • La tasa se mide después de la recuperación de silencio muerto, por lo que se lee más alta que la PPM bruta y está más cerca de la tasa de articulación. La revisión de la tabla impresa es crítica: échale un vistazo y ajusta deadband al hablante antes de renderizar, no confíes en los valores predeterminados a ciegas.
    • Perillas (k=v): mode=segment|global|off (por defecto segment; global=un factor para todo el video, off=deshabilitado), deadband=lo,hi, min_speed=/max_speed=, min_seg=/min_words=, lang=auto|en|cjk. Para saltarte esta función por completo, simplemente no ejecutes este paso — cut_render.py trata un speed faltante como 1.0.
  • cut_render.py utiliza N entradas buscadas separadas + filtro concat, una sola recodificación. Esto es obligatorio: recortar N veces de UNA entrada decodificada hace que ffmpeg almacene en búfer todo el flujo decodificado (decenas de GB para un video largo). Consulta reference/pitfalls.md. Cuando los segmentos llevan un speed, vuelve a sincronizar cada entrada (setpts video / atempo audio) y normaliza fps/base de tiempo/frecuencia de muestreo por entrada antes de concat para que el A/V permanezca sincronizado; sin velocidad, vuelve al gráfico original exacto.
  • Comparación final: video-edit-compare lee la línea de tiempo canónica más la entrega final real. Proyecta los píxeles finales de vuelta al tiempo de origen, estira los clips de velocidad variable a su duración de origen y muestra los rangos eliminados como negro.

6. Autoverificación — no declares finalizado hasta que esto pase

# comprobación de regresión de precisión del protocolo (ejecutar desde la raíz del repositorio)
python skills/video-cut/scripts/check_project_protocol.py
# retranscribir el corte terminado
ffmpeg -y -i first_cut.mp4 -ac 1 -ar 16000 work/selfcheck/cut_audio16k.wav
python scripts/transcribe.py work/selfcheck/cut_audio16k.wav work/selfcheck/cut_transcript
# verificación de contenido + muletillas + límites
python scripts/verify_cut.py work/edit_final.json work/transcript.json work/selfcheck/cut_transcript.json
# verificación de fotogramas / negro / unión (los tiempos de unión usan out_dur posterior a la velocidad, por lo que siguen siendo precisos)
python scripts/selfcheck_frames.py work/edit_final.json first_cut.mp4 work/selfcheck
# sincronización A/V + sin silencio muerto residual
ffprobe -v error -select_streams v:0 -show_entries stream=duration -of csv=p=0 first_cut.mp4
ffprobe -v error -select_streams a:0 -show_entries stream=duration -of csv=p=0 first_cut.mp4
ffmpeg -i first_cut.mp4 -af silencedetect=noise=-32dB:d=1.5 -f null -

Umbrales de aprobación:

ComprobaciónCondición de aprobación
Fotogramas negrosninguno
Fotogramas de uniónlimpios — solo saltos de cabeza naturales, sin negro/congelado/roto
Sincronización A/Vduración de video vs audio dentro de ~1 fotograma (≈30ms); total ≈ final_duration_s_after_speed cuando la velocidad variable está activada
Silencio muerto ≥1.5s0 (el ratio_de_habla debería aumentar notablemente)
Segmento eliminado/duplicadoninguno — todo el contenido clave presente (difflib ~0.90 está bien; una proporción más baja suele ser ruido de transcripción de segunda pasada en habla murmullosa, no pérdida — verifica por presencia de palabras clave antes de culpar al corte)
Medias oraciones cortadasninguna — los límites caen en silencio / en finales de oración

Advertencia honesta sobre muletillas: el corte a nivel de párrafo NO logrará "casi sin muletillas". La densidad por minuto puede incluso aumentar porque la sustancia retenida es conversacional. Informa esto honestamente; la eliminación de muletillas a nivel de palabra pertenece a P1/P2 (y haría que una cabeza parlante en una sola toma se vea visiblemente entrecortada).

Finalmente

Escribe first_cut_report.md: resumen de la fuente, qué se cortó y por qué, la tabla de autoverificación y cualquier advertencia honesta (techo de calidad de fuente 360p, densidad de muletillas, etc.). Si se aplicó velocidad variable, divúlgalo: cuántos segmentos se re-sincronizaron y el rango de velocidad (de la tabla de assign_speed.py / speed_params), para que el lector sepa que el corte no es en tiempo real 1:1. Ten en cuenta también que la cifra de muletillas por minuto de verify_cut.py se lee ligeramente más alta después de la aceleración (mismas palabras, minutos más cortos) — un artefacto de informe, no muletillas añadidas.

Principios clave (los ganados con esfuerzo)

  • Tú decides el contenido; los scripts deciden los fotogramas. Escribe a mano edit_coarse.json; deja que build_edit.py haga la precisión y assign_speed.py el ritmo.
  • La velocidad toca el ritmo, nunca el contenido. La velocidad variable automática da a todos los segmentos de renderizado de un decision_ref la misma velocidad, mueve el ritmo fuera de banda solo al borde de la banda muerta más cercano, limita las decisiones adyacentes a un delta de 0.08x y sujeta la salida a 1.0–1.3. atempo conserva el tono. Revisa la tabla; mode=off u omite el paso para deshabilitar.
  • Nunca recortes una palabra. Los límites siempre caen dentro del silencio.
  • Solo renderizado seguro en memoria (N entradas buscadas + concat). Nunca recortes múltiples veces una entrada.
  • Sé decisivo. Toma decisiones razonables y continúa; no preguntes en exceso.
  • La autoverificación no es negociable. Retranscribe + verifica fotogramas antes de declarar finalizado.
  • Consulta reference/pitfalls.md para la lista completa de trampas y soluciones.

Individual skills in this repo

This repo contains 8 individual skills — each has its own dedicated page.

Skills relacionados