El motor dual Zig y libav del daemon y el plan de reproducción composicional que decide qué hace cada uno.
Implementado.
track/media-engineestá en curso youtcome/playback-core(el planificador completo) todavía no ha empezado como outcome: lo que existe es el planificador de@styx/playback-policyque usaplayback-svc. El estado de cada gate está en el roadmap.
El daemon hace demux, remux y empaquetado fMP4-CMAF/HLS con motor propio en Zig y, de forma
configurable, con libav (FFmpeg 8) enlazado como librería (dec-0110). Los dos implementan el
mismo contrato MediaEngine (en native/zig/media-core/engine/):
probe: hechos del contenedor y de las pistas, con la misma estructura en ambos motores;openDemuxer: paquetes comunes (pista, pts/dts con base de tiempo racional, marca de
fotograma clave, datos con dueño explícito);openRemuxer: escribe paquetes y devuelve fragmentos;EngineError): ningún
código AVERROR sale del puente.La generación de listas HLS/CMAF y la segmentación por tiempo son código común a los dos motores
(native/zig/transmux). Cada motor sólo aporta demux y mux de fragmentos, de modo que comparar
uno con otro aísla lo que de verdad difiere.
| Crate | Contenido |
|---|---|
media-core/container/ | Parsers ISOBMFF y Matroska en Zig y los hechos de contenedor |
media-core/engine/ | El contrato MediaEngine y la base de tiempo |
transmux/ | Muxer fMP4-CMAF, empaquetador HLS común y registro de selección de motor |
libav-bridge/ | El único sitio con @cImport de FFmpeg; sólo se compila con -Dlibav=true |
transmux nunca importa libav-bridge. Sin la opción, el puente compila una versión desactivada.
La regla es doble: FFmpeg sólo entra como librería, y ningún motor abre ficheros ni URLs por su
cuenta. libav recibe un contexto de E/S propio cuyos callbacks leen de la fuente del daemon con el
propósito correcto (probe, playback, seek). La guarda check:no-media-spawn falla si algún
fichero de producto lanza ffmpeg o ffprobe. FFmpeg se compila como LGPL.
Como el código C de libav tiene historial de CVEs, el motor libav se trata como código no
memory-safe: los parsers de entrada no confiable en Zig son seguros por construcción (ReleaseSafe,
lectores acotados, fuzz), y el aislamiento de libav en un proceso trabajador es un invariante de
diseño de dec-0117 (I6).
El control plane decide, el daemon valida y ejecuta:
media.engine = zig | libav | auto, y un fallback opcional hacia
libav sólo con auto.auto usa el motor Zig si declara la capacidad para
(contenedor, códec, destino) y si no, libav.media.engine).Un conjunto de pruebas diferenciales corre el mismo corpus (fijado por hash) por los dos motores y compara hechos, paquetes y fragmentos. Cada discrepancia se clasifica: fallo del motor Zig, laxitud de libav o diferencia legítima. Un canario con un oráculo desplazado debe producir discrepancias, para demostrar que la prueba discrimina.
playback-svc convierte una intención (qué asset, qué cliente, qué preferencias) en un
PlaybackPlan composicional y explicable, con las reglas puras de @styx/playback-policy:
PlaybackIntent + capacidades del cliente + capacidades de la fuente
│
▼ planPlayback (sin E/S)
PlaybackPlan { source, container, video, audio, subtitles, delivery, reasons, estimatedCost, mode }copy, remux, package), vídeo
(copy, transcode, con filtros), audio (copy, transcode) y subtítulos (none,
passthrough, convert, burn). Una sesión real puede necesitar un remux, un transcode de audio y una conversión de
subtítulos a la vez.mode (direct, adapted, video-transcode) es una clasificación derivada para la
interfaz y la telemetría, nunca una entrada.reasons explica cada decisión por pista, incluida la del motor de medios y su sustitución.@styx/api-contracts; la lógica vive en
@styx/playback-policy, que depende de los contratos y no al revés.Hoy @styx/capability-model describe las capacidades de códec, contenedor, audio y subtítulos
como enumeraciones TypeScript fijas (VIDEO_CODECS, AUDIO_CODECS…) y el emparejamiento entre
cliente y fuente (matching.ts). Objetivo, sin código todavía (r23):
CanonicalCodecPolicy v1): AV2 como frontera preferida, AV1
como respaldo de producción y HEVC Main10 por compatibilidad. Ningún paquete la implementa, y
AV2 no está en VIDEO_CODECS.