gates de calidad de video con ffmpeg
Juzga mediante mediciones. Mirar un video y decir "parece estar bien" es como permitir que un congelamiento de 4 segundos llegue a producción.
| Script | Mide | Fallo cuando |
|---|---|---|
scripts/qa_video.py | presencia de pista de audio; tamaño; duración (+-tol o máximo); tramo casi estático más largo (en una copia de 10 fps para que un fondo con movimiento lento no oculte una parada); silencio (-50 dB, >=0.3 s); sonoridad integrada (por defecto -14 LUFS +-1.5); pico verdadero (<= -1 dBFS) | cualquier límite superado |
scripts/opening_density.py | fracción de celdas de cuadrícula 8x8 "planas" (desviación estándar de brillo < 5) en los primeros segundos, mediana y máximo | la apertura es mayormente fondo vacío; menos de N cuadros utilizables (= no medido) |
scripts/subtitle_lint.py | líneas por cuadro de subtítulo, caracteres por línea, tiempo mínimo de visualización, caracteres/segundo, solapamientos | cualquier violación; cero cuadros analizados = no medido |
python3 scripts/qa_video.py out.mp4 --expect-size 1080x1920 --max-duration 30
python3 scripts/opening_density.py out.mp4 --seconds 3
python3 scripts/subtitle_lint.py out.vtt --max-chars 20
bash tests/run.sh # genera clips sintéticos con ffmpeg y verifica que cada defecto sea detectado por la razón correcta
Notas de diseño (por qué está construido así)
- El código de salida 3 significa "no se pudo medir". La falta de ffmpeg, un archivo ilegible o menos de N cuadros utilizables nunca debe considerarse aprobación.
- Se mide sobre una copia de 10 fps para detectar congelamientos. Los rayos de luz giratorios o el brillo de fondo pueden hacer que una escena congelada parezca "viva" a máxima precisión; la copia barata elimina ese ruido. El límite es
--max-freeze(por defecto 4 s); un congelamiento que llega hasta el final del clip también cuenta. - Los cuadros de flash/oscurecimiento se omiten en la densidad (luminancia media <8 o >247): no dicen nada sobre la escena.
- Calibra los umbrales con tus propios ejemplos buenos y malos, y documéntalos. Mide algunas aperturas que consideres buenas y algunas que consideres planas, y establece los límites entre ellas. Los valores por defecto son puntos de partida; tus números serán diferentes.
- La entrada de prueba puede estar mal, no el gate. Un patrón
testsrc2son grandes bloques de color y se mide como "vacío"; un video de ruido fue el control honesto. Cuando un gate y su entrada de prueba no coinciden, averigua cuál está mal. - Estos son aproximaciones de "se siente como un video corto real". Aprobar no garantiza que sea divertido o atractivo; la queja de un humano ("parece una presentación de diapositivas", "el subtítulo duplica el texto en pantalla") debe convertirse en un nuevo gate medible.
Combínalo con
cold-read-comprehension-reviewpara "¿lo entiende un espectador?" (lo que los números no pueden medir).llm-adaptation-fidelity-checkcuando el guion se adapta de un texto fuente.llm-verdict-gate+ci-gate-forgery-testpara el proceso circundante.
Gates adicionales que vale la pena agregar (no implementados aquí)
Auditoría de pantalla (cada cuadro de texto en pantalla: solapamientos, áreas seguras de la interfaz de la plataforma, intrusión de la banda de subtítulos); lista blanca de cadenas en pantalla (antifalsificación); altura mínima del texto como porcentaje del ancho del fotograma; ritmo de corte (longitud media/máxima de los cortes); tasa de error de caracteres entre subtítulos y voz mediante STT (<= 0.08); prohibición de emojis en el DOM renderizado; relación de duplicación entre subtítulos y texto en pantalla. Estos necesitan el DOM/línea de tiempo de tu renderizador, por lo que no pueden ser genéricos.
Dependencia de ejecución: instala requirements.txt con python3 -m pip install -r requirements.txt. Pillow debe ser al menos 12.3.0; las dependencias de modelos opcionales mencionadas anteriormente son independientes.