Taste Application
La segunda mitad del pipeline. taste-distillation mide las referencias en un pack de estilo; esto genera contra ese pack y corta el resultado.
Contrato de Ejecución y Entrega
La implementación original se incluye aquí en scripts/; no se necesita un checkout separado de ito-video. Instala scripts/requirements.txt para procesamiento local. Instala scripts/requirements-live.txt solo para ejecución en un proveedor. Las cargas, envíos y descargas en vivo requieren TASTE_FORGE_ALLOW_LIVE=1 además de las credenciales; actívalo solo para la ejecución autorizada del usuario. --dry-run sigue siendo libre de credenciales y produce marcadores etiquetados. Un tiempo de espera ambiguo del proveedor no se reintenta como un nuevo trabajo pago. Inspecciona la solicitud al proveedor antes de decidir si merece otro envío.
Usa tomas completadas existentes sin llamadas al proveedor:
python scripts/pipeline.py --genre ejemplo --root stylepacks \
--takes media/take-a.mp4 media/take-b.mp4 --duration 12 --fps 30 \
--out out/review-v1.mp4
--duration es un objetivo de cadencia de mejor esfuerzo, no un tiempo de ejecución exacto. Los planos completos pueden producir una edición más corta o más larga; el ensamblador no duplica clips ni añade relleno para alcanzar el objetivo. El manifiesto de salida conserva la duration real y añade duration_contract con los segundos solicitados y reales, déficit, exceso y la política cadence_target. Las diferencias de al menos un fotograma de salida se advierten explícitamente. No se proporciona un modo de duración exacta; cuando se requiere un tiempo de ejecución exacto, inspecciona el recibo y revisa o rechaza el corte antes de la entrega.
El pipeline conserva los archivos de plano graduados de cada ejecución porque el FCPXML y EDL editables los referencian. Rechaza colisiones de salida e informa fallos de exportación de la línea de tiempo. Un render completado no es un proyecto de editor guardado ni una aprobación creativa. Conserva los activos fuente y los puntos de control del proyecto versionados antes y después de las ediciones en vivo; registra la ruta guardada y el resumen por separado del recibo de la línea de tiempo en memoria.
Los grafos de Fal listos para clonar y su compilador de entrada fuera de línea están documentados en workflows/README.md. Compila el resumen y la dirección de estilo antes del envío; no asumas que un campo de esquema desconectado afecta a un prompt de modelo. Valida los campos de endpoint actuales contra el proveedor real antes de una ejecución paga.
Para Blender, usa el GLB texturizado fuente completo; la retopología es un derivado con nombre separado y nunca reemplaza esa fuente. blender_prop.py soporta --width 1920 --height 1080 --fps 30 --receipt receipt.json explícitos y conserva la iluminación de borde y las texturas de material derivadas del pack. Guardar una escena es distinto de renderizarla; inspecciona el estado del recibo y las imágenes empaquetadas.
Para superposiciones de Resolve, usa taste.resolve.apply_placements con objetos inyectados de un objetivo versionado seleccionado explícitamente. Establece source_end_mode en la convención verificada en ese host. No asumas un final de fuente inclusivo entre versiones de Resolve. El adaptador asigna efectos superpuestos sobre pistas preservadas y verifica cada colocación inmediatamente y de nuevo después de todas las inserciones. Los números enteros compuestos deben coincidir con la API instalada; para el host verificado Studio 21, Screen es 5, no el incorrecto 22 del constructor histórico. El recibo prueba solo la colocación en memoria. Guarda el proyecto, verifica su punto de control, luego inspecciona la salida renderizada exacta antes de informar la entrega.
Cuándo Activar
- "haz un vídeo en este estilo" / "aplica el pack" / "complementa este metraje"
- Ensamblar clips generados en algo con un ritmo de edición real
- Acuñar props 3D a partir de un look y devolverlos al vídeo
- Verificar que una pieza terminada realmente coincide con su referencia
División del Trabajo
El modelo proporciona contenido, movimiento, encuadre y estructura de iluminación. El pack proporciona color y ritmo. Esto se mide, no es una preferencia estilística — ver taste-distillation para los números. Consecuencias prácticas:
- El prompt de generación contiene cero lenguaje de color. Añade "Color: ninguno. Render neutro. La gradación se aplica después."
- Mantén dos banderas separadas:
--brief(lo que OCURRE: sujeto, acción, lugar) y--style-steer(cómo SE VE). Fusionarlas filtra palabras de estilo en la escena ("azul verdoso" se convierte en un objeto azul verdoso) y palabras de sujeto en la gradación. - El modelo responde mucho mejor a reglas locales y comprobables que a globales. "Fondos negro puro y sin luz; los sujetos tendiendo al blanco" funciona; "contraste extremo" no funciona.
Generar TOMAS, No Planos
La lectura obvia de "coincidir con la cadencia" es una generación por plano. Es económicamente absurdo. Una referencia que promedia 0.78s/plano contra un endpoint con un suelo de 4 segundos convierte una pieza de 10s en 12 llamadas, 48 segundos generados por 10 usados (21% de eficiencia), y doce clips no relacionados unidos en lo que debería leerse como continuo.
Los editores ruedan una toma más larga y cortan dentro de ella. Agrupar planos en tomas de ~5s: 3 llamadas, 13 segundos generados, 77% de eficiencia, y planos consecutivos que realmente pertenecen entre sí porque vinieron de la misma generación.
Dile al modelo qué forma quieres, o renderiza un lento push bloqueado y seis cortes dentro de él se leen como un tartamudeo:
"Filmado como UNA toma continua sin cortes duros dentro de ella. Se cortará en 6 piezas de aproximadamente 0.8s en la edición, por lo que el encuadre, el sujeto y la luz deben seguir cambiando a lo largo — cualquier ventana de 0.8s tiene que valerse por sí misma como su propio plano."
Reglas de Corte
- Recodifica, nunca copies en streaming. La copia en streaming solo corta en keyframes, que a 0.78s significa que la longitud del plano redondea cada límite al GOP más cercano — destruyendo lo exacto que el pipeline existe para preservar.
- Al complementar metraje existente, usa sus propios límites de plano. Dividir un vídeo base en piezas contiguas y reproducirlas en orden simplemente reensambla el original: cada "corte" cae a medio plano y es invisible. Medido, un ensamblaje de 20 planos registró solo 12 cortes detectados. Detecta límites reales y toma cada N para que las selecciones consecutivas estén garantizadas como discontinuas. Eso movió una medición de corte de 1.29s a 0.83s contra un objetivo de 0.78s.
- Muestrea las longitudes de plano de la distribución de la referencia, no de su media, para que el corte herede la varianza del ritmo en lugar de aplanarse a clips uniformes.
Reglas de Gradación
- La medición directa supera a un LUT horneado cuando tienes el clip: mídela, empareja su CDF L*, aplica croma por zona.
grade_clip_directalcanzó MAE 1.58 y contraste 34.0 contra 34.7. - Ancla, no uses CDF-match, cuando el histograma del clip no se parezca al de la referencia. Forzar un clip generado con 68% de negro sobre un histograma de referencia ocupado levantó todo el fondo del negro: la preservación del fondo cayó al 26.0% (CDF) frente al 69.0% (ancla), mientras que MAE y contraste seguían viéndose excelentes. Por defecto, usa tono anclado.
- El tamaño del lote importa. Graduar 48 fotogramas a la vez mató el proceso por falta de memoria; 6 es seguro.
Comportamiento Recuperado de la Plataforma fal
Estas observaciones y ejemplos de endpoint provienen del flujo de trabajo recuperado. Vuelve a verificar los metadatos del endpoint actual; no son garantías sobre cada versión futura del proveedor. Las plantillas de grafo incluidas registran las entradas de flujo de trabajo verificadas por separado, incluido el control explícito de audio generado.
Esto cuesta tiempo real de descubrimiento. Compruébalos antes de diseñar un grafo.
| Límite | Detalle |
|---|---|
| No hay ningún renderizador 3D | fal tiene image-to-3d, text-to-3d, 3d-to-3d y nada más. Cada endpoint 3d-to-3d emite otra malla. No hay una categoría 3d-to-image/3d-to-video, por lo que un GLB acuñado no puede volver a entrar en un grafo de vídeo de fal. Renderiza localmente, luego usa fal-ai/ffmpeg-api/images-to-video. |
| compose no puede superponer | fal-ai/ffmpeg-api/compose rechaza una segunda pista con "No se admiten múltiples pistas de vídeo" — y cuenta una pista de image como una pista de vídeo. Solo secuencia una pista de vídeo. Compón localmente con ffmpeg. |
| compose keyframes están en milisegundos | Nada en la respuesta lo dice. Una ejecución enviada en segundos se acepta y devuelve un vídeo que es 1000x demasiado corto. |
| extract-frame ofrece solo primero/medio/último | Sin marca de tiempo arbitraria. Usa los tres como tres imágenes de acondicionamiento distintas. |
| Sin bucles, sin concatenación de cadenas en el DAG | El fan-out por plano tiene que ser creado nodo por nodo, o mantenerse local. |
| Kling 3.0 no tiene referencia-a-vídeo | La línea v3 es solo texto/imagen/control de movimiento; referencia-a-vídeo vive en la línea o3: fal-ai/kling-video/o3/pro/reference-to-video. |
| Los prefijos no son uniformes | bytedance/*, tripo3d/*, meshy/*, minimax/*, openai/* no llevan el prefijo fal-ai/. kling-video, veo3.1, flux-*, hunyuan-3d, ffmpeg-api sí lo llevan. |
Selecciones de endpoint
| Espacio | Mejor | Alternativa de valor |
|---|---|---|
| referencia→vídeo | bytedance/seedance-2.5/reference-to-video (~$0.473/s @720p) | fal-ai/kling-video/o3/pro/reference-to-video (~$0.112/s) |
| imagen→3D | fal-ai/hunyuan-3d/v3.1/pro/image-to-3d ($0.375, hasta 8 vistas) | tripo3d/h3.1/image-to-3d ($0.20) |
| texto→3D | fal-ai/hunyuan-3d/v3.1/pro/text-to-3d | tripo3d/h3.1/text-to-3d |
| retopología | fal-ai/hunyuan-3d/v3.1/smart-topology ($0.75) | tripo3d/tripo/remesh (~75x más barato) |
| división de partes | fal-ai/hunyuan-3d/v3.1/part (solo FBX) | tripo3d/tripo/segment |
| texto→imagen | fal-ai/nano-banana-pro ($0.15 fijo) | fal-ai/flux-2-pro ($0.03/MP) |
Seedance es ~4x el precio de Kling o3 por los mismos 5 segundos. Lo gana en fidelidad de múltiples referencias (hasta 50 refs mixtos de imagen/vídeo/audio) y no lo gana cuando se condiciona sobre una sola imagen fija.
Los IDs de modelo y los precios cambian. Verifícalos contra fal.ai/models antes de prometer cualquiera de ellos.
La Rama 3D
python mint3d.py --genre <nombre> --from-stills 4 --retopo --render
python mint3d.py --genre <nombre> --prompt "un visor de cromo agrietado" --render
- Genera una placa limpia primero; no tomes de imágenes de referencia. El requisito de entrada declarado del endpoint es fondo simple, objeto único, objeto >50% del fotograma. Los carretes de referencia son lo contrario de eso — collages, planos generales, varios sujetos, gráficos quemados — y producen ruido esculpido. Texto → placa de objeto único → malla cuesta ~$0.15 extra y es la diferencia entre una malla utilizable y una descartada.
- La vista múltiple se nombra por campos por ángulo, no una lista.
input_image_url(frontal, obligatorio), luegoback_image_url,left_image_url,right_image_url,left_front_image_url,right_front_image_url,top_image_url,bottom_image_url. No hayinput_image_urlsni un flagmulti_view— inventarlos degrada cada acuñación a una sola vista mientras parece funcionar. Una etiqueta de ángulo incorrecta es peor que omitir la vista, porque el modelo confía en ella. - Accede al GLB por clave, no por posición. La respuesta lleva un PNG
thumbnaily un bloquemodel_urlsjunto amodel_glb; tomar la primera URL funciona solo hasta que las claves se reordenan, y un PNG de vista previa se descarga bien — nada falla hasta que Blender se niega a abrirlo. - Solicita mapas PBR. Sin ellos, la malla se ilumina como cartón pintado.
- Retopologiza si alguien va a editar o riguear la malla. Las mallas generadas son densas y caóticas.
- Renderiza localmente para cerrar el bucle. Una vez que un plato giratorio son fotogramas, es metraje, y cada etapa posterior ya maneja metraje — gradúalo, córtalo, utilízalo como elemento o súbelo como referencia de acondicionamiento. Usa Blender cuando haya un binario en PATH; mantén un rasterizador de software ligero como valor predeterminado, porque un contexto GL sin cabeza es lo más común que falta en un contenedor y un renderizador que solo funciona en una estación de trabajo no es parte de un pipeline.
Verifica, Luego Cree
Cada otra etapa afirma un resultado. Compruébalo, y comprueba la forma de la distribución, no solo los momentos:
background— proporción del fotograma por debajo de L*10 contra la cifra del pack. Compáralo con la referencia, no con el clip fuente: una fuente generada al 68% de negro es más negra que cualquier referencia en una banda de 24–55%, por lo que "preservar los negros de la fuente" exige lo incorrecto e igualmente excusa una gradación levantada.chroma_mae— error a*/b* por zona, usando la mediana (coincidiendo con cómo se midieron los objetivos del pack; una media aquí compara una estadística sensible a la asimetría con una robusta e informa un desajuste de definición como un error).contrast/black_point/white_pointbanding— bins vacíos del histograma L* entre bins ocupados. Contar bins vacíos totales no funciona: un clip legítimamente oscuro tiene bins vacíos de altas luces.cadence— longitud media de plano detectada frente a la de la referencia.
Cuidado con la trampa de unidades: OpenCV cambia la convención de Lab con el dtype. En float32, L* es 0–100 y a*/b* están firmados; en uint8, L* es 0–255 y a*/b* tienen sesgo +128. Mezclarlos informa errores de croma en los cientos.
Cadena Completa
python pipeline.py --genre <nombre> --refs a.mov b.mov \
--brief "lo que sucede" --duration 12 \
--base-video existente.mp4 --out out/FINAL.mp4
acuñar → destilar → (mint3d) → aplicar → forjar → verificar. Las etapas 1–3 están cacheadas, por lo que iterar sobre briefs nunca vuelve a medir nada. --dry-run simula cada llamada de red: el plan, los prompts, la disposición de pistas y el manifiesto aún se ejecutan.
Anti-patrones
| No hacer | Por qué |
|---|---|
| Una generación por plano | 21% de eficiencia, 12 clips no relacionados |
| Poner color en el prompt | Medido que no funciona; aleja de la base neutra que el LUT quiere |
| Copiar en streaming los cortes | Los límites solo en keyframes destruyen el ritmo sub-segundo |
| Cortar un vídeo base de forma contigua | Reensambla el original; cada corte invisible |
| Confiar en compose para superponer | No puede; rechaza la segunda pista |
| Enviar segundos a compose | Silenciosamente 1000x demasiado corto |
| Entregar solo con MAE | Añade la comprobación de proporción de fondo |
El Metraje Prestado Lleva la UI de la App de Captura
El peor defecto único encontrado en un corte entregado: el vídeo finalizado enviaba el botón de me gusta, el contador de vistas y la burbuja de comentarios de otra persona, porque el base...