# FFmpeg `deft/ffmpeg` brings video and audio playback to TUI panels: a worker thread decodes through a runtime FFI binding to the system libav* libraries, frames land in a stable pixel buffer, and the panel draws them with `draw/image`. It is a nested package inside stdext and mounts as its own top-level package.
import "deft/ffmpeg" as ffmpeg
This is the Deft half of the Video app — see FFI for the binding layer and Graphics for the draw pipeline. ## Requirements The host must be built with `-Dffi=true` and have a supported system FFmpeg installed (libavutil 58/59/60 — FFmpeg 6.1 / 7.1 / 8.1). Audio additionally needs swresample (7/8; FFmpeg 6 is video-only). The package manifest marks `ffmpeg` as an `:optional` capability, and `available?` reports whether the host can play. ## API | Def | Signature | Description | |---|---|---| | `available?` | `{||}` | FFI compiled in and libav* loads | | `probe` | `{| path |}` | `%{ w h fps duration }` or `%Err` | | `play` | `{| path opts |}` | Start a player (player ref or `%Err`); opts `:max-width :max-height` | | `pause` / `resume` / `stop` | `{| p |}` | Transport control | | `seek` | `{| p sec |}` | Seek to a position | | `position` | `{| p |}` | Seconds of the last shown frame | | `playing?` / `error` | `{| p |}` | State accessors | | `dims` | `{| p |}` | Native `%{ w h }` | | `draw` | `{| ctx p col row w h |}` | Draw the current frame; returns a bool |
set p [ffmpeg/play "/path/clip.mp4" %{ :max-width 800 :max-height 450 }]

defimpl VideoApp Panel {
    draw {| ctx |
        [ffmpeg/draw $ctx $p 0 0 $w $h] } }
## How It Plays - Worker — decode runs in a `defworker` child runtime (`deft/ffmpeg/worker`); bursts of ~0.5 s of content are yielded to the player, paced by ring backpressure. Sequential bursts continue the parked decoder; seeks restart from the nearest keyframe. - Pacing — a 16 ms poller shows frames when their presentation timestamp is due against a wall-clock origin; audio (S16, 44.1 kHz, stereo) is pushed to `audio/stream-*` on SDL hosts. Pause freezes the clock; EOF loops to 0 after the queued tail plays; a 5 s stall watchdog surfaces an error. - Binding — `deft/ffmpeg/lib` dlopens the libraries, probes the FFmpeg major, and reads structs through per-version offset tables, so no build-time linking is required. ## See Also - Video app help — the panel UI - FFI — foreign-function bindings - Graphics — pixel buffers and `draw/image` - defworker — the worker runtime model