Edición de video vertical de presentador (talking head) con素材 real (Windows + Codex + Jianying)
Escenario aplicable: Solo se dispone de素材 grabados por otros (presentador + B-roll), hay que editarlos en un video vertical de 30–50 segundos, 1080×1920, y que el editor final lo termine en Jianying o lo exporte directamente.
Reglas estrictas (no violables) en references/AGENTS_rules.md, colócalo en AGENTS.md del proyecto antes de empezar. Este documento solo describe el flujo.
Entrada
- Directorio de素材 (solo lectura, nunca modificar el original; primero copiar una copia al directorio de trabajo).
- Hábitos de estilo del editor (si los hay). Los hábitos que el editor haya mencionado personalmente son el estándar estricto; los videos de referencia solo son un banco de técnicas, se aprenden las técnicas pero no los parámetros; en caso de conflicto, se sigue al editor.
- Opcional: videos de referencia, ubicación de la marca, texto CTA al final (no se deben escribir números de teléfono/direcciones no verificados).
Salida
spec.json(storyboard, única base para la edición), video preliminar o final mp4,.srt, collage de QC por segundo, informe de QC.- Ruta A entrega adicional: borrador de Jianying; Ruta B entrega adicional: capa superpuesta transparente ProRes 4444
.mov.
Paso 0: Autoverificación del entorno (no empezar si falla)
Ejecutar la autoverificación según references/windows_env.md: ffmpeg versión completa (con zscale, tonemap, prores_ks), Python 3.10/3.11, faster-whisper + whisperX, Playwright + Chromium + fuente china objetivo, opcional demucs / RVM; el directorio de borradores de Jianying ya está configurado y añadido a writable_roots. El sandbox de Codex está desconectado por defecto, los modelos y dependencias deben instalarse con antelación. Si falla algo, primero informar qué falta, no ejecutar a ciegas. Los comandos específicos de cada paso están en references/windows_commands.md.
Paso 1: Inventario de素材
- ffprobe cada archivo: resolución, framerate (¿variable?), rotación, duración, transferencia de color (HLG/PQ = HDR). Escribirlo en
inventory.csv. - No exportar archivos intermedios SDR: cada vez que se lea un frame, convertir en la cadena de filtros. Añadir
fps=30a todos los素材; la cadena de filtros para leer frames de素材 HDR debe comenzar con la conversión HDR a SDR, de lo contrario la imagen se ve apagada, también para los frames de miniatura (comandos en la sección 2 dewindows_commands.md). - Extraer miniaturas de cada素材 y etiquetarlas (contenido, personas, tramos utilizables, obstrucciones/escena negra/inicio oscuro, si es otra marca). Marcar los no utilizables y sus tramos.
- Verificar: cada素材 tiene etiqueta; los素材 con transferencia de característica arib-std-b67 o smpte2084, la cadena de filtros de lectura de frames comienza con conversión HDR.
Paso 2: Transcripción y corrección
- Transcripción inicial con faster-whisper: modelo
medium,device='cpu',compute_type='int8',language='zh',vad_filter=True,word_timestamps=True,initial_promptcon vocabulario del sector. VAD puede omitir frases, ejecutar otra ronda sin VAD, esta ronda concondition_on_previous_text=False. - Primero, corrección manual del texto completo contra el audio: términos técnicos, números, homófonos mal escritos; Whisper también puede inventar frases que no se dijeron, hay que eliminarlas. Las palabras que no se oyen claramente se cortan directamente del audio, no se adivinan.
- Antes de transcribir, extraer primero un WAV mono de 16 kHz con ffmpeg y luego pasarlo a whisper. Luego pasar el texto corregido a whisperX para alineación forzada (el resultado se escribe en el campo
aligndespec), obtener los inicios palabra por palabra (error de 0–3 frames). Los finales de palabra de whisperX no son fiables, los puntos de salida se determinan con detección de energía.
- Verificar: no hay términos técnicos ni números sin corregir en la transcripción; cada oración tiene inicio por palabra.
Paso 3: Reorganización narrativa (primero definir la narrativa, luego los efectos)
- El primer segundo debe ser un gancho: «contraste + resultado», usando las palabras originales. No poner B-roll ni logo al inicio.
- El gancho puede combinar dos frases originales no adyacentes, pero cada mitad debe tener
src_t, y al combinar no se puede cambiar el significado original. - Dos opciones de audio, escribir en
spec: la primera frase comienza normalmente, con letras grandes superpuestas; o elevar la frase de resultado (≤3 segundos) al inicio como cold open, y luego volver al orden normal.
- El gancho puede combinar dos frases originales no adyacentes, pero cada mitad debe tener
- Eliminar las frases que no avanzan la historia (lemas, relleno, afirmaciones repetitivas), objetivo 30–50 segundos.
- Marcar 3–4 puntos de inflexión narrativa (gancho inicial / cambio de escena / clímax resultado / frase de cierre), los impactos solo se colocan en estas posiciones; la intensidad del clímax es la mayor, seguida del inicio. Dos impactos deben estar separados al menos 6 segundos; para videos de ~30 segundos poner 3, para ~50 segundos poner 4.
- Verificar: cada texto en pantalla se puede encontrar en la transcripción con su timestamp y contexto (la misma palabra puede tener diferente significado en distintas oraciones).
Paso 4: Escribir el storyboard spec.json, solicitar confirmación al usuario
Especificaciones de campos en references/spec_schema.md, ejemplos de categorías de palabras clave en references/kw_class.example.json (las palabras del ejemplo son de un proyecto específico, al cambiar de proyecto hay que reescribirlas). Cada segmento debe incluir:素材 de origen y puntos de entrada/salida, formato, subtítulos, kw_class, preset de efectos, B-roll, efectos de sonido, sección musical, src_t (timestamp de las palabras originales). Enviar el storyboard al usuario para confirmación antes de renderizar.
Paso 5: Edición
- Puntos de entrada/salida con detección de energía RMS de 10 ms (no usar finales de palabra de Whisper). Cortar los espacios de respiración: sin dejar inhalaciones ni palabras de relleno.
- Método práctico comprobado: cortar primero por energía, umbral máximo (percentil 10 + 14 dB, −48 dBFS), 3 ventanas consecutivas de 10 ms para considerar que hay voz, dejar 0.10 s antes y 0.14 s después, luego ajustar manualmente; verificar que la longitud continua por debajo de −42 dBFS a cada lado del corte sume ≤90 ms.
- Objetivo del hábito del editor: dejar solo 1–2 frames (≤67 ms) antes del inicio de cada palabra, aún no probado con este estándar (pendiente de verificación). Método de verificación: después de separar la voz con demucs, medir desde el punto de corte hasta el inicio de 3 ventanas consecutivas de 10 ms superiores a −42 dBFS; cada punto de corte ≤67 ms, las consonantes iniciales no se cortan, y el segmento cortado debe pasar un nuevo ASR sin palabras truncadas. Si pasa, se convierte en predeterminado.
- Se puede generar otra versión con 2–3 frames entre oraciones para que el editor elija.
- Exportar cada segmento con precisión de frame:
-ssantes de-i,-vfincluyefps=30, usar-frames:v nfpara longitud fija (nf = round((salida − entrada) × 30)),libx264 -preset veryfast -crf 12, con las tres marcas de color BT.709; audio unido por muestras, cada segmento con fade in de 8 ms / fade out de 15 ms para evitar picos. - Cortes de salto en la misma cámara: añadir zoom de 1.08x; transiciones de entrada/salida de B-roll con whip pan + desenfoque horizontal.
- B-roll solo se inserta donde las palabras originales mencionan ese contenido, no forzar ritmo.
Paso 6: Efectos de subtítulos (dos niveles)
Nivel normal: uno cada 1.5–2 segundos, intervalo máximo ≤3 segundos, moderado.
- Subtítulos inferiores: texto blanco con borde negro, una línea ≤12 caracteres, aparecen en frase completa (si colorear palabras clave se convierte en parámetro, lo decide el editor).
- Énfasis en letras doradas grandes en la capa media (palabras clave 1.75×, números 2×), entrada letra por letra 115%→100%, 6–8 frames; se puede añadir subrayado/círculo a mano, textura de papel, sombra suave.
- Técnicas opcionales: números que ruedan, pegatinas de objetos reales con sonido correspondiente, listas acumulativas (tamaño de fuente ≥ 1.2× la de subtítulos inferiores, luego agrandar al juntarse), frases doradas en vertical a pares (al aparecer ocultar el subtítulo inferior de la misma frase), etiqueta de identidad al inicio (solo usarla una vez al inicio, marcar «no son palabras originales»).
Nivel de impacto: 3–4 por video, contabilizados en la densidad total, cada uno al máximo:
- Letras grandes ocupando 75–85% del ancho del cuadro (85% es el límite, prioridad a la zona segura); zoom de 1.15–1.25 en 4 frames; pantalla vibrante 2–3 frames con desenfoque de movimiento; fondo oscurecido 6–30%, desaturación adecuada (parámetro, ajustar para que los rostros se vean claros en móvil), no modificar la capa de personas; efecto de sonido compuesto de impacto pesado premezclado (contado como 1).
- Niveles de intensidad: el más fuerte zoom 1.25, pantalla vibrante 3 frames; los demás zoom 1.15, pantalla vibrante 2 frames.
- La misma técnica solo se usa una vez en todo el video: letras detrás de la persona (con chroma key) / transición de máscara de texto / números rodantes en pantalla completa + sello rojo / frase dorada vertical que aparece + barrido de luz.
- Letras detrás de la persona: colocar letras por encima de la línea del hombro, evitar manos y objetos; la cabeza debe tapar las letras un 25–30% (si <15% no se nota en móvil); antes de delinear con blanco, borrar objetos mal recortados (como sillas) de la máscara.
- Sello rojo: único color rojo en todo el video, ancho 30–40% del ancho del cuadro, aparece en 3 frames 150%→100% + pantalla vibrante 2 frames.
- Congelación: solo se puede colocar en un silencio natural después de una oración (voz < −45 dB), elegir el frame donde la boca esté más cerca de cerrarse, ≤0.4 segundos, máximo uno en todo el video, el efecto de sonido de impacto pesado se coloca al inicio de la congelación. Esta es la única excepción a «no dejar espacios de respiración».
- Todas las animaciones de entrada comienzan 1 frame antes.
Paso 7: Sonido
- Voz: filtro paso alto 80 Hz → reducción de ruido → ecualización ligera → compresión.
- Música: cambiar por secciones (hábito del editor), crossfade de 300–600 ms; sidechain ducking cuando hay voz. Usar solo música con licencia confirmada o auto-compuesta.
- Efectos de sonido: aproximadamente 0.5 por segundo, distribuidos uniformemente, en cada ventana de 4 segundos 1–3, cualquier intervalo entre dos ≥0.25 segundos; nivel por defecto RMS del efecto de sonido 14 dB por debajo de la voz (
db=-14); priorizar sonidos realistas que coincidan con el contenido sobre pops genéricos. - Volumen: primera pasada
loudnorm=I=-14:TP=-1.5:LRA=11para medir; segunda pasada con los valores medidos añadiendolinear=true, luego fijoaresample=48000,alimiter=limit=0.7:attack=1:release=30:level=false; finalmente medir con ebur128 y compensar ganancia con g = min(−14 − I, −2.9 − Peak). Objetivo −14 LUFS, pico real ≤ −1 dBTP.
Paso 8: Renderizado y entrega (elegir una o combinar)
- Ruta A: Borrador de Jianying (predeterminado cuando el editor solo usa Jianying). Codex genera el corte preliminar, subtítulos, efectos de sonido y tiempos musicales, usa pyJianYingDraft para crear un nuevo borrador, el editor abre Jianying para empaquetar y exportar. Limitaciones y precauciones en
references/jianying_route.md, toda la ruta debe verificarse en una máquina Windows real. - Ruta B: Capas superpuestas (obligatorio para impactos). Las capas de efectos se hacen con HTML/Canvas, Playwright controla Chrome del sistema para capturar frames PNG transparentes fotograma a fotograma: viewport 1080×1920,
device_scale_factor=1, parámetros de inicio--font-render-hinting=none, esperarwindow.READYydocument.fonts.readyantes de capturar,omit_background=True; todas las animaciones son funciones puras del tiempo t. La secuencia PNG se lee con-framerate 30, se codifica a ProRes 4444 (-alpha_bits 16), luego se compone con ffmpeg overlay. Colocar la capa superpuesta como pista de video en el borrador de Jianying: no se ha probado, pendiente de verificación. ffmpeg drawtext no puede hacer entrada letra por letra ni letras detrás de la persona. - Entrega de respaldo: video preliminar + SRT + storyboard, el empaquetado lo hace el editor en Jianying.
- Antes de superponer, aplicar un ajuste de color ligero a la capa base
eq=contrast=1.04:saturation=1.07. - Codificación final:
libx264 -profile:v high -preset slow -crf 17 -maxrate 16M -bufsize 24M -g 60 -r 30 -pix_fmt yuv420p -color_primaries bt709 -color_trc bt709 -colorspace bt709, AAC 192k,-movflags +faststart.
Paso 9: Control de calidad (entregar solo si todo pasa)
Revisar ítem por ítem según references/qc_checklist.md. El informe solo debe incluir lo que se haya verificado extrayendo frames y escuchando el audio, cada ítem con número y unidad; lo que no se pueda medir, escribir «no medido», no inventar.
Miniatura
- División del trabajo: el planificador redacta el texto y los frames candidatos (escribir en el campo
coverdespec), el editor proporciona el diseño y exporta (1080×1920 y 3:4). - El título principal usa palabras originales condensadas, se puede ajustar el orden (por ejemplo, «atornillar un mes y medio»), sin añadir hechos que no estén en las palabras originales; ≤7 caracteres, máximo 2 líneas. Las etiquetas secundarias colocan el número del resultado, 2–3 pegatinas.
- El título y el rostro deben estar dentro del área central de 1080×1440 (y 240–1680), la cuadrícula de la página de inicio de Douyin se recorta a 3:4.
- Proporcionar al menos 3 frames candidatos cada vez, con timestamp y justificación, indicar «no es versión final».
- Escanear todo el tramo cada 0.5 segundos para encontrar frames de perfil o expresiones; la dirección de la mirada determina el diseño (si la persona mira arriba a la izquierda → colocarla abajo a la derecha, título arriba a la izquierda); si la ropa o el fondo tienen texto, no permitir espejo horizontal.
Criterios de éxito
- Duración de 30–50 segundos, el primer segundo es un gancho con palabras originales; el texto en pantalla es 100% trazable hasta las palabras originales.
- Intervalo máximo de efectos normales ≤3 segundos; 3–4 impactos con niveles de intensidad y técnicas no repetidas.
- Efectos de sonido ≈0.5 por segundo, sin superposiciones simultáneas; sincronización ≤2 frames; −14 LUFS ±1, pico real ≤−1 dBTP.
- Sin violaciones de la zona segura; sin frames negros o congelados inesperados; las letras no cubren rostros ni marcas.
- El usuario ha confirmado el storyboard; todos los entregables están completos.
Errores comunes → Soluciones
| Error | Solución |
|---|---|
| Material HLG se ve apagado | Convertir a SDR con zscale + tonemap=hable, gamma ≈ 1.12 |
| Los timestamps de Whisper son demasiado tempranos, el final de la palabra se extiende al silencio | Usar alineación de whisperX para el inicio, detección de energía para el final |
| VAD omite frases | Ejecutar otra ronda sin VAD |
| El texto en pantalla no son las palabras originales / error de contexto | Cada línea lleva src_t, QC verifica contra la transcripción |
| Todos los efectos tienen la misma intensidad, se ven comunes | Dividir en nivel normal y de impacto, el impacto va al máximo |
| Las letras detrás de la persona no se notan | Medir el porcentaje de oclusión, la cabeza debe tapar 25–30% |
| La silla se incluye en el recorte de la persona | Colocar letras por encima de la línea del hombro; borrar antes de delinear |
| Error al medir la sincronización | Medir desde «el primer frame visible»; la entrada comienza 1 frame antes |
| Los sibilantes se confunden con efectos de sonido | Separar la voz con demucs y medir solo en la pista de acompañamiento |
| Efectos de sonido agrupados | En cada ventana de 4 segundos 1–3, los efectos compuestos de clímax cuentan como 1 |
| Los capítulos o letras grandes entran en el área del botón de Douyin | El borde derecho debe estar ≤ x 930 |
| Congelación mientras se habla, la boca no coincide | Colocar la congelación solo en silencio, ≤0.4 segundos |
| La animación al deslizarse cruza la cara o sale del cuadro | Cambiar a fade out en la posición original + fade in ampliado en la posición objetivo |
| La herramienta de visualización almacena en caché imágenes antiguas por ruta | Cambiar el nombre del archivo cada vez que se revise |
| La ruta china o los espacios causan fallos en los comandos | Usar Python subprocess para pasar lista de argumentos; lectura/escritura explícita utf-8 |
| Alucinación de Whisper: genera frases que no se dijeron | Revisar manualmente el audio completo antes de alinear |
| Quiere cambiar a otro esquema de renderizado (como Remotion) | No verificado, no reemplazar por cuenta propia, la capa de efectos solo usa HTML/Canvas + Playwright |
| El nuevo borrador no aparece en la lista de Jianying, fuente incorrecta | Entrar/salir de un borrador existente o reiniciar; abrir el borrador dos veces |