Flujo de trabajo de edición de video
Siga estos pasos cada vez que el usuario envíe un video raw. Raíz de la herramienta: /home/user/video-workflow
(VW=/home/user/video-workflow). Use un directorio de trabajo fresco por video en el bloc de notas, p. ej. $SCRATCH/<nombre>/work.
Lea STYLE_GUIDE.md (el estilo), EFFECTS.md (la biblioteca de 17 efectos - use varios en CADA video) y
templates/STORYBOARD_REFERENCE.md (sintaxis) antes del paso 4.
0. Configuración (una vez por contenedor)
$VW/vw.sh setup. Si advierte que huggingface.co está bloqueado, dígale al usuario que la transcripción no puede ejecutarse hasta que permita
huggingface.co (y *.hf.co) en la configuración de red del entorno; no invente una transcripción.
1. Preparar + transcribir + proponer cortes
$VW/vw.sh prep RAW.mp4 WORK [--language ro|en] [--model small|medium]
- El metraje SDR "lavado" (iPhone HDR re-codificado por una app compresora sin mapeo de tonos: negros lechosos, blancos apagados - p. ej. *_compressed.mp4) se detecta (punto negro por encima de Y45, o punto blanco por debajo de Y203 - blancos apagados junto a clips .mov con mapeo de tonos del mismo conjunto) y sus niveles se restauran en prepare.py (estiramiento de luminancia a Y34..~215, croma x1.08), coincidiendo con el aspecto natural aprobado del HDR con mapeo de tonos (Mindri-Box-v3).
- LOOK DE COLOR APROBADO en cada clip (regla del usuario - "el filtro del que hablamos"): después de normalizar, prepare.py
ejecuta
look_matchensource.mov: mide el 60% superior del fotograma (fondo + persona) y aplica una curva de tono + saturación para que cada clip coincida con el look aprobado (Mindri-Box-v3 / Comanda-Ionut-v2/v4: negros profundos, naranja vibrante, camiseta blanca limpia; targets p5 38, p25 52, p50 76, p95 226, saturación 59). Solo oscurece sombras/medios, levanta blancos apagados y añade color (máx. 35 niveles por punto, saturación máx. x1.3); los clips que ya están en el look se dejan intactos. Los videos de varios clips así coinciden entre sí. Lagradepermanecenaturalencima. - El metraje HDR de teléfono (iPhone: HLG/PQ, BT.2020, 10 bits, Dolby Vision) se mapea a SDR BT.709 automáticamente (zscale + hable, 100 nits); sin ello todo se ve pálido y lechoso. La salida se etiqueta como BT.709.
- Normaliza a 30 fps CFR, 1080x1920 (recorte de cubierta), detecta el rostro (MediaPipe de rango completo) y mide el
brillo de la zona del título →
layout.json(zonas seguras; las zonas brillantes hacen que los títulos tengan cuadro y el texto de vidrio teñido). - Transcribe con marcas de tiempo de palabras (mantiene "um"/reinicios visibles) →
transcript.json. - Marca automáticamente palabras de relleno, tartamudeos, palabras cortadas y reinicios →
edit.json+review.txt. - Use
--model mediumpara rumano o audio ruidoso; detección automática de idioma en caso contrario. - Si la fuente era horizontal (advertencia impresa), dígale al usuario que se recortó centrado.
1b. Varios clips raw (una historia)
Cuando el usuario envíe varios clips, transcriba cada uno primero y determine el orden a partir de lo que se dice
(generalmente el orden de grabación). Ejecute los pasos 1-2 y cut por clip (WORK_k), luego únalos:
python3 $VW/scripts/merge_clips.py WORK WORK_1 WORK_2 … → una línea de tiempo; layout.json mantiene el encuadre de cada clip
(clips[]), y el renderizador y los efectos usan el encuadre del clip que esté en pantalla. Arregle el texto de los subtítulos
en el words.json fusionado, luego continúe en el paso 4 en WORK. Ponga una transición (zoom_through, flash,
glitch) en cada límite de clip.
2. Revisar la edición (paso de juicio - no lo omita)
Lea WORK/review.txt de principio a fin como un editor y arregle WORK/edit.json:
- Elimine: tomas fallidas / reinicios que el detector no haya visto (mantenga la ÚLTIMA toma buena), frases mal dichas, "espera, déjame repetir eso", digresiones fuera de tema, introducción muerta ("hola chicos", "entonces, um, hoy…") - el video debe comenzar en la línea de enganche.
- Mantenga (
"keep": [idx…]): palabras que el detector eliminó incorrectamente (repetición deliberada, "muy muy", listas). - Palabras de baja confianza
(?): verifique el contexto; una palabra mal escuchada es un problema de subtítulos (arregle el texto entranscript.json, mantenga la sincronización), no un corte. - Parámetros de ritmo:
max_gap0.20 s (ajustado, estilo guía); aumentepad_aftera 0.14 si los finales de palabras suenan recortados. Luego:
$VW/vw.sh cut WORK
Debe imprimir Sync check: … OK. Si HAY DESAJUSTE → deténgase e investigue (nunca envíe). Los puntos de corte se ajustan a fotogramas y
se colocan en silencio, por lo que la sincronía labial es exacta. Vuelva a leer WORK/words.json (nueva línea de tiempo) - todas las sincronizaciones posteriores lo usan.
3. Arreglar el texto de los subtítulos
En words.json corrija errores ortográficos, nombres de marca, números ("diez" → "10" si se lee mejor), y mantenga el
idioma del usuario y las diacríticas (ă â î ș ț). No cambie las sincronizaciones.
4. Storyboard (paso de juicio)
Escriba WORK/storyboard.json (sintaxis: templates/STORYBOARD_REFERENCE.md, ejemplo: templates/storyboard.example.json).
Primero escriba un plan corto como tabla (tiempo · qué se dice · visual · transición · SFX) y muéstrelo al usuario al
final de la respuesta. Reglas de la guía de estilo:
Gancho (0-3 s) - la afirmación más fuerte como elementos title gigantes, uno por frase, 3+ cambios visuales en 3 s
(cambio de título / cambio de fuente / flash / zoom de impacto). Mezcle fuentes de título (serif → heavy → itálica dorada). Sin introducción.
Cuerpo - algo cambia en pantalla cada ~1-3 s:
- Ilustre lo que se dice, sincronizado a la palabra exacta que lo menciona (el
startdel elemento = elstartde esa palabra): herramientas/apps →strike(cuando se rechazan) ocard; instrucciones/prompts →prompt(escribiendo); números →counter/stat; pasos → insigniasstep; enumeraciones →list; una frase clave →title; una captura de pantalla/logo que el usuario haya proporcionado →image/card. - Una palabra clave heroica por oración en
captions.keywords(la palabra que lleva el significado, no relleno). - Zoom de acercamiento (
zooms, escala 1.06-1.12, nunca más) en líneas de énfasis, alternando con 1.0 - esto mantiene al orador en un encuadre normal mientras oculta los cortes bruscos. - Transiciones estilizadas solo en cambios de sección / remate, máximo una cada 5-10 s:
flash,glitch,leak,whoosh,impact. - Cada 10-15 s cambie de modo (p. ej., una serie de tarjetas UI, luego un momento de título grande, luego una estadística).
El orador siempre visible: los gráficos van en pos: "top" (sobre la cabeza, ajustados automáticamente a la zona libre de
layout.json) o "lower" (área del pecho, sobre los subtítulos). Nunca center sobre el rostro. Los títulos pueden superponerse ligeramente a la parte superior
de la cabeza (ese es el look), nunca a los ojos/boca.
Reglas de referencia "Editado" (EFFECTS.md, final) - obligatorio en cada video: siempre una grade de color
(predeterminado natural - los colores propios del metraje, sin filtro estilizado; otros looks solo a petición), seguimiento facial
track 1-3 veces por cada 30 s, photos de internet para cosas concretas que se nombran (scripts/images.py, mírelas primero, créditos en la respuesta), títulos combo para el gancho
y encabezados de sección, numcards para enumeraciones.
Biblioteca de efectos (EFFECTS.md) - obligatorio en cada video: aproximadamente un momento de efecto cada 4-6 s de video final
(30 s → 5-7, 60 s → 9-12), cada uno emparejado con lo que se dice, sin repetición en ~15 s, mezclando familias de cámara, recorte y UI.
Ponga uno en el gancho. Ejemplo con todos ellos: templates/storyboard.effects-example.json.
CTA / final (si el usuario dijo lo que quiere): tarjeta comment (CTA de palabra clave) y/o follow en los últimos 4-6 s.
Tema de marca (elección permanente del usuario) - todo en pantalla: storyboard "style": "depth", "palette": "mindricel"
→ títulos, tarjetas, pasos, mosaicos/números, gráficos, listas de verificación, notas, tarjetas orbitales, texto de vidrio y productos usan todos el
look de referencia de profundidad en la paleta mindricel.ro (naranja #FF6600 degradado, tinta #0A0A0A paneles, texto blanco, contornos finos oscuros).
Los nombres de fuentes editoriales en líneas de título se mapean automáticamente; use naranja (#FF6600/#FF8533) o blanco para
doodles. Nunca mezcle los colores editoriales verde/crema.
Subtítulos (elección permanente del usuario - referencia "lockup", copiado 1:1): "captions": {"style": "lockup", "palette": "scene"} (no se necesita lista de palabras clave; los roles son automáticos).
- Cada frase hablada (2-5 palabras) es UNA composición tipográfica: las palabras de contenido son GRANDES (Montserrat ExtraBold, ~170 px, apretado -0.045em, como se habla - mayormente minúsculas), las palabras funcionales son PEQUEÑAS (Montserrat SemiBold, 1/3 de tamaño, blanco con un contorno fino oscuro) metidas en las esquinas de las palabras grandes - antes de una palabra grande: arriba a la izquierda, después: abajo a la derecha ("over $10,000 a month"). Una palabra grande por línea, líneas apiladas apretadamente y escalonadas izquierda/derecha.
- Rellenos por palabra grande: números/dinero → degradado verde, palabras negativas (nu, fără, stop, greșeli, scump...) → degradado
rojo, otras → degradados de los colores del metraje de ESE clip (paleta
body_profile.py) o blanco; automáticamente más profundos/saturados en escenas brillantes y claros en escenas oscuras para que siempre se lea. - La posición rota cabeza / pecho / cabeza / sobre la cabeza; mientras los títulos o gráficos ocupan la parte superior, las frases permanecen en el pecho. Una frase en FRENTE nunca cubre el rostro (cabello a barbilla): se mueve al pecho o sobre la cabeza.
- PROFUNDIDAD (regla del usuario, CADA video): aproximadamente el 40% de las frases (
behind_share0.4) se colocan ligeramente DETRÁS de la cabeza (capa trasera + recorte). La búsqueda cubre alturas desde "el borde inferior roza el cabello" hasta la mitad del rostro y se desplaza hasta ±240 px lateralmente. Un lugar es válido solo si la cabeza realmente se superpone a una palabra (behind_min_overlap5%), cada palabra grande está oculta como máximo un 25% (palabras cortas ~4% por letra, p. ej., máximo 16% para 4 letras), y la parte superior de la primera/última letra permanece visible. Usa la silueta de peor caso sobre el clip (occ_max), escalada por cualquier zoom activo en ese momento. Nunca 3 detrás seguidas, nunca mientras los gráficos ocupen la parte superior. Verifique esos fotogramas en QA. - Legibilidad: cada palabra grande tiene un contorno fino (oscuro en áreas oscuras, claro en áreas brillantes) + sombra suave; las palabras
pequeñas tienen un contorno oscuro. Los colores de relleno se eligen a partir del brillo EXACTAMENTE debajo de la frase (mapa
lumde body_profile.py): tintes claros sobre áreas oscuras, tintes profundos sobre áreas brillantes - la paleta permanece la del metraje. - QA: verifique que ninguna frase frontal toque el rostro y que las frases posteriores se lean con claridad (abra fotogramas en cada una).
- Movimiento: la frase entra lateralmente con fantasmas de desenfoque de movimiento, las palabras aparecen mientras se hablan (desenfoque rápido), y sale en la dirección opuesta cuando comienza la siguiente frase (sin espacios entre frases).
- Tiempo de lectura: una frase aparece
lead0.25 s antes de que se hable (sus palabras ligeramente antes de la voz), las frases más cortas quemin_phrase1.0 s se fusionan con la siguiente/anterior (máx. 7 palabras / 34 caracteres), la última frase sostienehold1.2 s. El video mantienetail0.8 s de imagen después de la última palabra (parámetrosedit.json; si el metraje termina antes, se mantiene el último fotograma). Múltiples clips:"tail": 0en cada clip excepto el ÚLTIMO. - Fondos mixtos (p. ej., camiseta blanca sobre un fondo oscuro, dispersión de brillo > 0.17 debajo de la frase): un tono medio vívido del color propio del video con el contorno oscuro (ver "Colores de subtítulos" abajo).
- Guardia de contraste: si el color de una palabra está demasiado cerca en brillo de lo que tiene detrás (
min_contrast0.42), el mismo color obtiene su tinte de máximo contraste + el contorno fino - nunca se vuelve blanco (regla del usuario). - Temas sensibles / serios (funerales, enfermedad, pérdida, disculpas...): mantenga el look lockup pero
"motion": "fade"(fundido suave, sin latigazos),"semantic": false(sin colores de palabras verdes/rojas), sin glitch/pixel/vertigo/frame-break, sin SFX contundentes (ninguno está bien), desplazamientos lentos y seguimiento suave solo, fuerza de grade ~0.6, y sin tema naranja mindricel a menos que sea la propia marca del usuario. Dígale al usuario que el tono se adaptó y ofrezca la versión enérgica. - Estilos de subtítulos más antiguos (
cleantitulares,depth,bold,editorial) solo a petición.
Números: tiles ahora se renderizan como UNA píldora redondeada oscura con grandes dígitos limpios que cuentan hacia arriba y una unit opcional
en naranja (p. ej., {"type": "tiles", "text": "400-600", "unit": "cm³"}); los cuadros antiguos solo con "look": "classic".
Transiciones (referencia de bienes raíces): en cambios de clip / cambios de sección use flash_blur (desenfoque sobreexpuesto),
pixelate (disolución de píxeles, también buena cuando un elemento/imagen sale), zoom_through, y cortes de zoom-salto (punch
alternando 1.0 / 1.1-1.15 en cortes bruscos). Mantenga glitch raro.
Sonidos (video de referencia SFX del usuario, extraído - la ÚNICA biblioteca; el antiguo sintetizado se eliminó a petición):
10 WAVs en sfx/ (pico -3 dBFS): loading (tictac digital 0.9 s), click, air (silbido aireado corto), tap (pop suave),
marker (trazo de resaltador), tick (tic UI pequeño), blur_hit (impacto contundente + cola), swish, sub_boom (gota
sub-grave), logo_hit (golpe de revelación grande). Mapeados automáticamente (compose.py): flash_blur → blur_hit, zoom_through/leak/
whoosh/swoosh transiciones → swish, flash → air, pixelate/glitch/rewind → loading, impact → sub_boom, punch → click;
title/stat/combo → blur_hit (primer combo + sub_boom), strike/doodle/wall/accent → marker, cards/app/image/product info → tap,
products → air + swish, steps/lists/checklists/numcards → click, counters/tiles/charts → loading, glass/cover → sub_boom,
follow card → logo_hit, typing → tick. Nombres antiguos (pop, whoosh, deep_bass, ding, ...) aún funcionan mediante SFX_ALIAS.
Densidad de SFX (usuario: "usa efectos de sonido más a menudo") - predeterminado "sfx_density": "high": además de los sonidos de elementos y
transiciones, compose.py añade sonidos extra silenciosos (-15..-19 dB) en cambios de frase de subtítulos (air cuando la frase va
detrás de la cabeza, tap en números/precios, alternando swish / tick en otro caso; desde WORK/caption_events.json), en cada
corte brusco (click), cuando un gráfico superior sale (air) y en movimientos de cámara push/track. Cada sonido extra mantiene >= 0.3 s de separación
de los demás (~1 sonido por segundo). Temas tranquilos: "sfx_density": "normal" (automático cuando subtítulos motion: "fade").
MENOS SUBTÍTULOS (regla del usuario, cada video): los subtítulos en cada frase son cansados - solo ~60% de las frases reciben un subtítulo
(captions.density 0.6 = 40% menos). El renderizador mantiene las frases más significativas (palabras de contenido, números/precios,
negaciones, nombres, preguntas/exclamaciones; palabras de relleno como bă/mă/băi/deci puntúan bajo), siempre la primera y la última frase,
y nunca 4 frases seguidas sin subtítulos.
5. Renderizar
$VW/vw.sh render WORK [-v]
Salida: WORK/final.mp4. Use -v solo para inspeccionar; el video final siempre se renderiza sin mostrarse.
6. Comprobación final de calidad
- Reproduzca
WORK/final.mp4(use$VW/vw.sh preview WORKpara una ventana) y verifique:- Sin parpadeos de subtítulos.
- Las palabras clave detrás se leen bien.
- Los gráficos no cubren la boca.
- El sonido está sincronizado y los niveles son buenos.
- El color coincide entre clips.
- Si hay problemas, arregle
storyboard.jsonoedit.jsony vuelva a ejecutarrender.
7. Mensaje de respuesta al usuario
Incluya:
- Plan: la tabla de storyboard (contenido visual). Documente cada elección creativa.
- Estado: enlace al video (si está en un agente con vista previa) o confirme que se renderizó.
- Créditos: para cada foto de internet usada, enumere la fuente en una nota al pie (dominio, URL si está disponible).
- Opciones: ofrezca regenerar con un ajuste específico ("¿Quieres tono más serio?", "¿Más/menos SFX?", "¿Versión más larga/corta?") - no se limite a preguntar si está bien; los usuarios quieren opciones.