06 — One API, many containers (AV1 + WebM + Opus)
Every tutorial so far played MPEG-1. This one plays AV1 — the royalty-free codec
— with no change to your code. video_open sniffs the file’s magic bytes and picks
the backend: pl_mpeg for an MPEG-1 .mpg, dav1d for a raw AV1 .ivf, and nestegg
+ dav1d + libopus for a WebM container carrying AV1 video alongside Opus audio.
Open, decode, borrow — the surface never names the codec.
(That clip is Emma explaining WebM — and it plays as a WebM: the demo below decodes the very thing she’s describing, AV1 video and Opus sound, through the same calls.)
The library
probe_media opens a path, decodes the whole stream, and reports what came out. It
is the MPEG-1 decode loop from tutorials 02 and 05 verbatim — video_decode for the
AV1 frames, video_enable_audio + video_decode_audio + the get_audio_data
borrow for the Opus audio. The only thing that changed is the file you hand it.
require video
require daslib/defer
require math
struct MediaProbe {
width, height : int
has_audio : bool
samplerate : int
audio_channels : int
video_frames : int
audio_batches : int
audio_peak : float
}
// Open `path` (format auto-detected), decode the whole stream, and report what came
// out — proving the WebM / AV1 / Opus path runs through the exact same surface as
// the MPEG-1 tutorials. Audio is opt-in, so enable it when the file has a track.
def public probe_media(path : string) : MediaProbe {
var p = video_open(path)
if (p == null) return MediaProbe()
defer() { video_close(p) }
var m = MediaProbe(width = video_width(p), height = video_height(p),
has_audio = video_has_audio(p))
if (m.has_audio && video_enable_audio(p)) {
m.samplerate = video_samplerate(p)
m.audio_channels = video_audio_channels(p)
}
// Decode the AV1 video frames. dav1d does the work; `get_data` would borrow the
// pixels exactly as in tutorial 02 — here we just count them.
while (video_decode(p)) {
m.video_frames++
}
// Decode the Opus audio. libopus hands back interleaved float PCM through the
// same `get_audio_data` borrow as the MP2 audio in tutorial 05.
while (video_decode_audio(p)) {
m.audio_batches++
p |> get_audio_data() $(s : array<float>#) {
for (v in s) {
m.audio_peak = max(m.audio_peak, abs(v))
}
}
}
return m
}
Two notes. Opus always decodes at 48 kHz, so video_samplerate reports 48000 for any
WebM regardless of the source rate; video_audio_channels reports the real channel
count (1 or 2). And the AV1 path is 8-bit 4:2:0 only — 10-bit / HDR / 4:2:2 / 4:4:4
fail closed with a clear message rather than decoding wrong, by design.
Self-verifying
The test decodes the bundled sample.webm (Emma’s WebM, 640×640 AV1 + stereo Opus)
and checks that both tracks came through — AV1 frames from dav1d, Opus batches from
libopus, at 48 kHz with real amplitude.
require webm_tut
[export]
def main() {
let m = probe_media("tutorials/06_webm/sample.webm")
verify(m.width == 640 && m.height == 640, "the WebM reports its 640x640 size")
verify(m.video_frames > 0, "AV1 video decodes through dav1d")
verify(m.has_audio, "the WebM carries an Opus audio track")
verify(m.samplerate == 48000, "Opus decodes at 48000 Hz")
verify(m.audio_channels == 2, "the demo's Opus audio is stereo")
verify(m.audio_batches > 0, "Opus audio decodes through libopus")
verify(m.audio_peak > 0.01, "decoded audio is real (Emma's voice, not silence)")
print("tutorial 06 ok: {m.video_frames} AV1 frames, {m.audio_batches} Opus batches at {m.samplerate}Hz\n")
}
Running it
Run it from the repo root — the test opens its sample with a repo-root-relative path:
cd <dasVideo>
daslang -load_module . tutorials/06_webm/test_webm_decode.das
prints:
tutorial 06 ok: 467 AV1 frames, 933 Opus batches at 48000Hz
The same examples/play_audio_gl.das from tutorial 05 plays this WebM on screen, with
sound, A/V-synced — point it at tutorials/06_webm/sample.webm and watch. Because the
API is format-agnostic, the windowed player needed no change to gain AV1 + WebM + Opus.
That closes the ladder. Anything not in the royalty-free set (H.264, VP9, Theora, …) you decode yourself and feed the same borrow API — dasVideo ships the codecs whose patents and licenses are both clear, and stays out of your way for the rest.