Communitygithub.com

TaherZiad/montage-crew

Recorta silencios y peso muerto (muletillas, tomas repetidas, falsos comienzos) de un video de persona hablando ANTES de construir la edición. Usa la API /auto-trim en lugar de ffmpeg manual, revisa los candidatos a peso muerto que devuelve, y haz la única tarea que solo un humano/AI puede hacer (detectar PUNTOS repetidos). Léelo cuando el briefing habilite 'Tự động cắt ngắn video' (autoCut) o el usuario se queje de que el video aún tiene peso muerto/silencios.

¿Qué es montage-crew?

Este skill, 'TaherZiad/montage-crew', está diseñado para optimizar el flujo de edición de videos de tipo 'talking head' (persona hablando a cámara) eliminando automáticamente silencios y contenido redundante o de baja calidad antes de cualquier otro paso de edición (como subtítulos, zooms o efectos de sonido). Al operar sobre el video fuente en lugar del borrador renderizado, se evita la pérdida de calidad por doble codificación y se mantiene la sincronía de todas las marcas de tiempo posteriores. La funcionalidad principal se logra mediante una arquitectura de servidor-cliente donde el servidor (endpoints `/auto-trim/analyze` y `/auto-trim/apply`) realiza las mediciones técnicas y propone candidatos, mientras que el agente (humano o AI) es responsable de revisar cada candidato y, crucialmente, identificar 'puntos repetidos' desde el punto de vista semántico, una tarea que el análisis automático no puede realizar. El skill enfatiza la revisión manual de los candidatos, especialmente en el caso de muletillas en vietnamita que a menudo se confunden con palabras reales, y proporciona un flujo de trabajo detallado con una verificación final para garantizar que no se haya eliminado contenido significativo. El sistema está diseñado para integración en plataformas como Claude Code, Cursor o Codex, y requiere una transcripción con marcas de tiempo como prerrequisito para un funcionamiento óptimo.

Compatible con~Claude Code~Codex CLI~Cursor
npx skills add https://github.com/TaherZiad/montage-crew/tree/HEAD/skills/montage-crew/references/external/AIEV

Preguntar en tu IA favorita

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

Documentación

Auto-Cut - Recorte medido de silencios y peso muerto

Principios

  1. Cortar ANTES de construir escenas/subtítulos. Cortar después desvía todas las marcas de tiempo (subtítulos, zooms, SFX). Salida de este paso: assets/<source>.cut.mp4 + assets/transcript.cut.json - cada paso posterior utiliza la versión recortada.
  2. Cortar es OBLIGATORIO cuando el briefing habilita autoCut - no es una sugerencia. Si no se puede cortar nada, debes indicar una razón concreta (el video ya estaba ajustado) en el informe.
  3. Los umbrales residen en el servidor, no en tu cabeza. NO ejecutes silencedetect tú mismo ni elijas un umbral en dB por intuición. Dos hechos comprobados acabaron con ese flujo de trabajo:
    • El umbral correcto es una propiedad del ARCHIVO, no una constante. En un archivo real, -40dB encontró 0 silencios, -30dB encontró 13, -25dB encontró 21. Un número fijo es inútil o se come el habla.
    • La sonoridad por sí sola no puede distinguir entre "pausa" y "hablar en voz baja". En el archivo fuente medido, silencedetect a -30dB informó 48.6s de "silencio" pero solo 18.2s de ellos estaban en un espacio real entre palabras; los otros 30.4s estaban dentro de palabras (pausas de sílabas, finales sordos en vietnamita c/t/p/ch). Cortar solo por nivel de sonido se traga el habla. El servidor realiza la medición (autoTrim.ts) y la generación de candidatos (deadWeight.ts). Tú haces la revisión. Esa división es el objetivo principal.
  4. Se cortan dos tipos de peso muerto: silencios (medidos por la máquina, protegidos por la transcripción) y peso muerto de contenido (muletillas, tartamudeos, tomas reformuladas - propuestas por el servidor, aprobadas por ti; además de PUNTOS repetidos, que solo tú puedes encontrar - ver Paso 3).

Paso 0 - Requisito previo: una transcripción con marcas de tiempo de palabras

Toda la protección depende de ello. El servidor busca assets/transcript.raw.json, luego assets/transcript.json. Sin una, el análisis aún se ejecuta pero devuelve guarded: false, la lista de peso muerto está vacía y los números son conjeturas en ambas direcciones (puede pasar un mal corte y fallar uno bueno). Transcribe primero - nunca recortes una cabeza parlante vietnamita sin protección.

Paso 1 - Analizar (gratuito, repetible, sin codificación)

POST http://localhost:6869/api/projects/<id>/auto-trim/analyze
body: {}                                   # o { "source": "assets/face.mp4", "level": "tight" }

level es natural | default | tight y por defecto es brief.autoCutLevel. Respuesta:

  • silence - durationSec, el thresholdDb elegido + thresholdNote (por qué ganó ese umbral), noiseFloorDb medido, los silences que se cortarán, keepRanges, removedSec, la tabla completa sweep, y wordGuard (cuántos segundos vetó la transcripción).
  • deadWeight - candidates[] con kind (filler | stutter | repeat-take | hesitation), start/end, text, confidence, reason, context; además de totalSec y byKind.
  • guarded - true solo cuando se encontró una transcripción. Si es false, arréglalo antes de cortar.

No se codifica nada, así que llámalo tantas veces como quieras (un fuente de 217s se analiza en aproximadamente un segundo).

Paso 2 - REVISAR cada candidato (tu trabajo, no el de la máquina)

La lista es determinista: misma transcripción, mismos candidatos, misma confianza. Lo que no puede hacer es entender el significado. Revísalos uno por uno y conserva solo aquellos que defenderías:

  • Confianza baja significa "lee el contexto primero", no "probablemente esté bien". Las muletillas en vietnamita casi siempre chocan con palabras reales. đó, ấy, thế, mà, là son tanto partículas de relleno como demostrativos/conjunciones reales.
  • Las frases conectoras (hoặc là, tức là, bởi vì là, với lại là) son la trampa. Medido en una transcripción real: "…có thể là ok ứng dụng nó / Hoặc là / Tham khảo để tìm cách…" es una alternativa genuina - cortarlo destruye una rama de la oración. Pero "Còn trường hợp mà mọi người có thể nghe / Hoặc là / Còn trường hợp mà người AI không ứng dụng được…" es una oración abandonada y debería eliminarse. La forma superficial es idéntica; solo el significado las separa. Es exactamente por eso que estos candidatos vuelven con una confianza base baja y una razón que dice LEE EL CONTEXTO.
  • Candidatos repeat-take: comprueba que la toma posterior realmente sea la más completa antes de aprobar.
  • Los candidatos hesitation son silencio puro entre palabras - generalmente seguros, pero verifica que no estás eliminando una pausa deliberada antes de un remate.

Rechaza libremente. Una muletilla dejada cuesta 0.4s; una palabra real cortada hace que la oración no tenga sentido y el espectador lo nota de inmediato.

Paso 3 - PUNTOS REPETIDOS (solo tú puedes encontrarlos - obligatorio)

Ningún detector captura esto, y es el peso muerto del que los usuarios se quejan más. Lee la transcripción como un discurso y analízala semánticamente:

  1. Agrupa oraciones que expresan el MISMO PUNTO - las palabras no tienen por qué coincidir, solo el contenido. Un hablante a menudo reformula un punto 2-3 veces: primero corto/titubeante, luego más completo. Considera también oraciones NO adyacentes (expone el punto A, divaga, vuelve al punto A con más detalle).
  2. Conserva exactamente UNA versión por grupo - la MÁS COMPLETA:
    • Versión corta anterior, reformulación posterior más completa -> conserva la posterior, corta la anterior.
    • La oración posterior es solo un eco corto ("đúng vậy, như tôi nói…") -> conserva la anterior, corta el eco.
    • Dos versiones equivalentes -> conserva la entrega más fluida (menos titubeos, sin muletillas).
  3. Verifica el flujo después de cortar: vuelve a leer el texto conservado de principio a fin. Si una oración conservada hace referencia hacia atrás ("như vừa nói") a una que cortaste, o conserva ambas o elige la versión sin la referencia hacia atrás.
  4. Convierte cada decisión en un rango {start, end} y envíalo con los candidatos aprobados en el Paso 4.
  5. Construye una tabla antes de cortar (inclúyela en el informe): marca de tiempo | oración cortada | razón | oración conservada - para que el usuario pueda revisar cada decisión.

Paso 4 - Aplicar (pasa por la cola de renderizado)

POST http://localhost:6869/api/projects/<id>/auto-trim/apply
body: { "cutCandidates": [{ "start": 51.81, "end": 52.25 }, …] }   # SOLO lo que aprobaste
-> 202 { job }

Envía una lista vacía si no aprobaste nada - los silencios medidos aún se cortarán. Luego consulta GET /api/jobs/<jobId> hasta que termine. El trabajo:

  1. Vuelve a analizar con la protección de la transcripción, fusiona los rangos de silencio con tus rangos aprobados (las superposiciones se fusionan, por lo que nada se cuenta dos veces).
  2. Descarta cualquier rango aprobado que se trague un punto medio de palabra - una última red de seguridad sobre tu revisión, y registra cada rango que rechaza. Los rangos rechazados en el registro significan que aprobaste algo que se encuentra sobre habla real; vuelve atrás y relee ese punto.
  3. Corta en UNA pasada de ffmpeg (trim/atrim + setpts/asetpts + concat), escribiendo assets/<stem>.cut.mp4.
  4. Reasigna cada marca de tiempo a la línea de tiempo recortada -> assets/transcript.cut.json.
  5. Verifica la SALIDA con las palabras reasignadas y escribe assets/auto-trim-report.json.

Si no hay nada que valga la pena cortar, el trabajo deliberadamente NO produce un .cut.mp4 (una copia idéntica recodificada solo pierde calidad) - output en el informe es null y sigues usando el fuente.

Paso 5 - Leer el informe (el trabajo no está terminado hasta que lo hagas)

assets/auto-trim-report.json contiene: duración antes/después, removed.silenceSec vs removed.approvedSec, el umbral elegido y por qué, candidatos rechazados y verification.

  • verdict: "pass" - el resultado cumple con el perfil para ese nivel.
  • verdict: "fail" - el trabajo aún terminó y el archivo es utilizable, pero NO cumplió con el perfil. El registro lo indica explícitamente. Aprueba más peso muerto (Paso 2/3) y ejecuta apply nuevamente, o indica en el informe final por qué lo estás aceptando. Nunca informes el corte como realizado mientras ignoras un fallo.

Los criterios de aprobación no son la vieja regla "sin silencio > 0.8s" - la medición mostró que esa regla es demasiado laxa. Un archivo real la aprobó mientras llevaba 13 silencios residuales de 0.45-0.67s totalizando 6.7s (4.2% del tiempo de ejecución), lo que suena obviamente lento. Los perfiles ahora limitan TANTO el silencio individual más largo como la relación total (default: 0.5s / 3%).

Paso 6 - Usar la versión recortada en todas partes

A partir de aquí, los subtítulos, la disposición de las teclas, la sincronización de SFX y los zooms leen assets/transcript.cut.json y el .cut.mp4. La comprobación de control de calidad dead-air vuelve a medir el video ensamblado con la transcripción y FALLA cuando brief.autoCut está activado y el silencio muerto aún supera el perfil - eso es el respaldo, no el plan.

El informe final debe incluir: la tabla de corte del Paso 3, los segundos eliminados divididos en silencio vs peso muerto aprobado, y el veredicto de verificación. Toma los números de auto-trim-report.json.

Problemas conocidos

  • Usar la transcripción ANTIGUA después de cortar -> los subtítulos se desincronizan progresivamente hacia el final. Cambia siempre a transcript.cut.json.
  • Cortar solo silencios e ignorar los puntos repetidos - lo que los usuarios llaman "peso muerto" es principalmente el Paso 3.
  • Cortar el borrador renderizado en lugar del fuente -> la calidad disminuye por una segunda codificación. Corta siempre desde el fuente (el servidor se niega a sobrescribir el fuente y omite los archivos ya nombrados *.cut.* al elegir un valor predeterminado).
  • Analizar un .cut.mp4 mientras la única transcripción es la original -> la protección está alineada con la línea de tiempo incorrecta. Empareja el archivo fuente con la transcripción que lo describe.
  • Archivos SFX/narración con su propio silencio inicial -> usa data-media-start para cortar dentro de HyperFrames (consulta "Sonoridad SFX y silencio inicial" en el skill noti-tiktok-vn), no recodifiques un archivo de audio solo por 0.3s de silencio inicial.
  • Unir segmentos cortados sin un fundido -> un clic en cada unión. Corregido en autoTrim.ts; la regla está a continuación y se aplica a cualquier código nuevo que corte o concatenate audio.

Audio: fundido de 30ms en cada borde de corte (regla estricta)

Un corte cae en medio de una forma de onda. La última muestra de un segmento y la primera muestra del siguiente no están relacionadas, por lo que la unión es un escalón vertical, y un escalón es un clic. La causa no es el codificador ni el fuente - es la unión misma, por lo que sobrevive a cualquier recodificación posterior.

La importancia depende de DÓNDE cae el corte, y la diferencia es grande. Medido sin pérdida en un video real de 278s de una persona hablando, comparando el mismo corte con y sin el fundido (el escalón muestra a muestra más grande en la unión; cualquier cosa por encima de ~0.02 es audible):

Tipo de uniónAntesDespués
Corte de silencio, 40 uniones (balanced)mediana 0.0040, peor 0.0113 - ninguno audiblemediana 0.0000
En medio del habla, 4 uniones (peso muerto / puntos repetidos)0.1195, 0.0744, 0.0232, 0.0064 - 3 de 4 audiblestodos ≤ 0.0008

A modo de escala, el escalón más fuerte en cualquier parte del habla normal en esos archivos fue de 0.06-0.13. Por lo tanto, una unión en medio del habla sin fundido puede ser un salto mayor que cualquier cosa que el contenido mismo produzca, mientras que una unión de silencio no es ni remotamente audible.

No te saltes el fundido basándote en la primera fila. El recorte de silencio simple es el caso en el que no importa; el Paso 3 (puntos repetidos) y la extracción de clips cortan directamente a través del habla, y esas son las uniones que hacen clic.

Solución: funde ambos bordes de cada segmento durante 30ms. Suficientemente largo para eliminar el escalón, demasiado corto para escucharse como un fundido. Usa audioCutFade() en apps/server/src/util.ts; no implementes el filtro manualmente.

[0:a]atrim=start=S:end=E,asetpts=PTS-STARTPTS,afade=t=in:st=0:d=0.030,afade=t=out:st=D-0.030:d=0.030[aN]

Tres cosas que hacen que funcione silenciosamente sin hacer nada:

  • Orden. afade debe ir DESPUÉS de asetpts=PTS-STARTPTS. afade lee st del reloj propio del flujo; con marcas de tiempo originales st=0 está en el pasado y el fundido de entrada nunca se activa.
  • Longitud. D es la duración del segmento, por lo que el inicio del fundido de salida es D - 0.030. Limita el fundido a D/2 o los dos fundidos se superponen en un segmento corto y lo engullen.
  • Extraer un clip, no solo unir. Un clip extraído de un video más largo tiene los mismos dos bordes en bruto aunque no se una nada - reframe.ts los funde mediante -af.

Una nota sobre cómo medir esto tú mismo: no compares dos codificaciones AAC. La recodificación perturba las muestras en todas partes, lo que enterró las 40 uniones reales entre 294 regiones de diferencia espurias y puso un desplazamiento de 54 ms entre los dos archivos. Renderiza ambas variantes directamente a pcm_s16le - entonces las dos están alineadas por muestra y las uniones se asientan exactamente en las longitudes acumulativas de los segmentos.

Individual skills in this repo

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

TaherZiad/montage-crew

Membangun motion graphic sinematik di browser (promo video, opener, intro, bumper, kinetic typography, explainer/video penjelasan bergambar 16:9 atau 9:16) memakai HTML + CSS + GSAP (+ Three.js bila perlu), dengan hasil yang bergerak seperti video sungguhan — bukan slide presentasi. Gunakan skill ini setiap kali user meminta "video promo", "opener", "intro animasi", "motion graphic", "bumper", "kinetic typography", "animasi teks sinematik", "explainer", "video penjelasan" (jurnalisme visual, kartun edukasi, kolase), atau menunjukkan referensi video promosi/explainer dan ingin dibuatkan versi web-nya — bahkan bila mereka tidak menyebut kata "motion graphic" secara eksplisit. Juga gunakan bila user mengeluh hasil animasi web "seperti PPT/presentasi" dan ingin lebih sinematik, atau ingin merender animasi web menjadi file video MP4, atau ingin explainer kartun/animasi dibangun LANGSUNG di After Effects lewat bridge/MCP Higgsfield.

TaherZiad/montage-crew

Agent 2 of the video editing pipeline. Finds and removes spoken mistakes — stutters, repeated words, false starts, and retakes (re-recorded lines) — from a talking-head recording. Use after cut-silences, when asked to cut mistakes, remove stutters / repeats / filler restarts, clean up flubs, or keep the best take. Works review-gated: it proposes every cut with context and a reason for approval, then renders only the approved cuts via ffmpeg. Requires a word-level transcript.

TaherZiad/montage-crew

Arabic short-video editor (any dialect). Edits talking-head videos and screen recordings, or builds an MG-led video from an idea with no footage - retakes and silences cut, Arabic RTL captions and hook, premium motion graphics, SFX, music, -14 LUFS master, cover - for 9:16, 16:9 or both. Delivers the MP4 plus a project for Resolve, Premiere, After Effects, CapCut or Final Cut. Asks a few questions on first use, keeps the user's brand kit, offers style cards, learns styles from videos, links and MG sites the user shows it, and learns the user's rules after each video. Use when the user asks to edit a video («منتجلي هذا الفيديو», «سوّي مونتاج», «أضف ترجمة», «قص الصمت», «بستايل …», "edit my video"), make a video from an idea («ما عندي فيديو، عندي فكرة», «فكرة فيديو عن…»), learn a style («تعلّم من هذا الفيديو», «هذا الموشن يعجبني»), save a brand («احفظ هويتي», «اقترح لي هوية») or change settings («غيّر إعداداتي»).

Skills relacionados