std.video — Video-Metadaten
Das std.video-Paket liest Video-Container-Metadaten (Auflösung, Dauer, FPS, Codec) aus AVI- und MP4/ISOBMFF-Dateien. AVI-Dateien mit MJPEG-Codec unterstützen zusätzlich Frame-Extraktion und Dekodierung.
Es gibt kein vollständiges Videodecoding (keine Softdecoder für H.264/H.265/AV1) — die Units sind auf Metadaten-Extraktion und MJPEG-Einzelbilder ausgelegt.
→ Units-Übersicht · Lyx-Sprache
Units
| Unit | Code | Beschreibung |
|---|---|---|
std.video.core | VID-00 | VidMeta-Struct, Format- und Codec-Konstanten, Container-Erkennung |
std.video.avi | VID-01 | AVI-Reader: Metadaten, Frame-Zählung, MJPEG-Frame-Extraktion |
std.video.mp4 | VID-02 | MP4/ISOBMFF-Reader: Box-Traversierung, Video-Track-Metadaten, Codec-Erkennung |
VidMeta-Struct
VidMeta ist ein 64-Byte-Puffer im Heap. Alle Felder sind int64 (8 Bytes). Die Funktionen AviMeta, AviMetaFile, Mp4Meta und Mp4MetaFile schreiben direkt in diesen Puffer:
| Konstante | Offset | Inhalt |
|---|---|---|
VID_OFF_WIDTH | 0 | Videobreite in Pixeln |
VID_OFF_HEIGHT | 8 | Videohöhe in Pixeln |
VID_OFF_DURATION_MS | 16 | Gesamtdauer in Millisekunden |
VID_OFF_FPS_NUM | 24 | FPS-Zähler (Frames per Second, Zähler) |
VID_OFF_FPS_DEN | 32 | FPS-Nenner |
VID_OFF_FRAME_COUNT | 40 | Gesamtzahl der Frames |
VID_OFF_FORMAT | 48 | Container-Format (VID_FMT_*) |
VID_OFF_CODEC | 56 | Codec (VID_CODEC_*) |
VID_SIZE | 64 | Gesamtgröße des Structs |
FPS wird als Bruch dargestellt: FPS = VID_OFF_FPS_NUM / VID_OFF_FPS_DEN. Bei MP4 sind beide Felder nicht aus dem moov-Box ableitbar und werden auf 0/1 gesetzt.
Konstanten
Container-Formate
| Konstante | Wert | Format | Erkennungsmerkmal |
|---|---|---|---|
VID_FMT_UNKNOWN | 0 | Unbekannt | — |
VID_FMT_AVI | 1 | AVI | RIFF + AVI ab Offset 8 |
VID_FMT_MP4 | 2 | MP4/ISOBMFF | ftyp ab Offset 4 |
Codecs
| Konstante | Wert | Codec | Typische Verwendung |
|---|---|---|---|
VID_CODEC_UNKNOWN | 0 | Unbekannt | — |
VID_CODEC_MJPEG | 1 | Motion JPEG | Überwachungskameras, Screencasts |
VID_CODEC_H264 | 2 | H.264 / AVC | Standard-Web- und Kameravideo |
VID_CODEC_H265 | 3 | H.265 / HEVC | 4K, effizientere Kompression |
VID_CODEC_AV1 | 4 | AV1 | Streaming, lizenzfrei |
VID_CODEC_MP4V | 5 | MPEG-4 Part 2 | Ältere Kameras, DivX/Xvid |
VID_CODEC_VP8 | 6 | VP8 | WebM, ältere Browser |
VID_CODEC_VP9 | 7 | VP9 | YouTube, Chrome |
Quickstart
import std.video.core;
import std.video.mp4;
import std.alloc;
import std.io;
fn main(): int64 {
var vid: int64 := alloc(VID_SIZE);
var ok: int64 := Mp4MetaFile("film.mp4"c as int64, 0, vid);
if (ok == 0) { PrintLn("Fehler"); return 1; }
var w: int64 := peek64(vid + VID_OFF_WIDTH);
var h: int64 := peek64(vid + VID_OFF_HEIGHT);
var dur: int64 := peek64(vid + VID_OFF_DURATION_MS);
var cod: int64 := peek64(vid + VID_OFF_CODEC);
PrintLn(IntToStr(w) + "x" + IntToStr(h) + " " + IntToStr(dur / 1000) + "s");
if (cod == VID_CODEC_H264) { PrintLn("Codec: H.264"); }
if (cod == VID_CODEC_H265) { PrintLn("Codec: H.265"); }
if (cod == VID_CODEC_AV1) { PrintLn("Codec: AV1"); }
free(vid, VID_SIZE);
return 0;
}
std.video.core — Container-Erkennung
// Mindestens 12 Bytes erforderlich.
// Gibt VID_FMT_* zurück.
var fmt: int64 := VidDetectFormat(buf, len);
if (fmt == VID_FMT_AVI) { AviMeta(buf, len, vid); }
if (fmt == VID_FMT_MP4) { Mp4Meta(buf, len, vid); }
std.video.avi — AVI-Reader
Metadaten
import std.video.avi;
// Aus Speicher-Puffer
var ok: int64 := AviMeta(buf, len, vid); // 1 = Erfolg, 0 = Fehler
// Aus Datei (liest automatisch in Puffer)
// plen: Zeiger auf int64 → erhält Dateigröße; oder 0
var ok: int64 := AviMetaFile("clip.avi"c as int64, 0, vid);
AVI liefert alle Felder einschließlich FPS (aus strh.dwRate/dwScale) und Frame-Zählung (aus avih.dwTotalFrames).
Frame-Extraktion
// Anzahl '00dc'-Chunks (Video-Stream 0) in der movi-Liste
var count: int64 := AviGetFrameCount(buf, len);
// Zeiger auf Frame-Daten (innerhalb von buf), Größe in pFrameLen
// frameIdx: 0-basiert
var pFrameLen: int64 := alloc(8);
var framePtr: int64 := AviGetFrameOffset(buf, len, 0, pFrameLen);
var frameLen: int64 := peek64(pFrameLen);
MJPEG-Frame dekodieren
AviExtractMjpegFrame kombiniert Frame-Suche und JPEG-Dekodierung in einem Schritt. Nur bei VID_CODEC_MJPEG sinnvoll:
import std.video.avi;
import std.image.core;
fn ExtractFrame(buf: int64, len: int64, frameIdx: int64): int64 {
var img: int64 := GrfImageAlloc(0, 0); // Größe wird vom Decoder gesetzt
var ok: int64 := AviExtractMjpegFrame(buf, len, frameIdx, img);
if (ok == 0) { GrfImageFree(img); return 0; }
return img; // GrfImage mit RGBA-Pixeln; Aufrufer muss GrfImageFree aufrufen
}
std.video.mp4 — MP4/ISOBMFF-Reader
import std.video.mp4;
// Aus Speicher-Puffer (erfordert 'ftyp'-Box ab Offset 4)
var ok: int64 := Mp4Meta(buf, len, vid);
// Aus Datei
var ok: int64 := Mp4MetaFile("film.mp4"c as int64, 0, vid);
Der Reader traversiert moov → mvhd (Dauer, Timescale), moov → trak → tkhd (Auflösung), mdia → hdlr ('vide'-Track), minf → stbl → stsd (Codec-Erkennung).
Einschränkungen MP4: FPS und Frame-Zählung sind aus dem moov-Box allein nicht zuverlässig ermittelbar und werden auf VID_OFF_FPS_NUM=0, VID_OFF_FPS_DEN=1, VID_OFF_FRAME_COUNT=0 gesetzt. Dauer und Auflösung sind immer verfügbar.
Codec-Erkennung (MP4)
Aus der stsd-Box (minf → stbl → stsd):
| 4CC | Codec |
|---|---|
avc1, avc3 | H.264 |
hvc1, hev1 | H.265 |
av01 | AV1 |
mp4v | MPEG-4 Part 2 |
vp08 | VP8 |
vp09 | VP9 |
Codec-Erkennung (AVI)
Aus dem strh.fccHandler-Feld des Video-Streams:
| FCC | Codec |
|---|---|
MJPG, mjpg | MJPEG |
H264, avc1, X264 | H.264 |
MP4V, XVID, DIVX, DIV3 | MPEG-4 Part 2 |
hvc1, HVC1 | H.265 |
Quelldateien
| Datei | Inhalt |
|---|---|
std/video/core.lyx | VID-00: VidMeta-Struct-Offsets, Format- und Codec-Konstanten, VidDetectFormat |
std/video/avi.lyx | VID-01: RIFF/AVI-Parser, avih/strh-Auswertung, Frame-Extraktion, MJPEG-Dekodierung |
std/video/mp4.lyx | VID-02: ISOBMFF-Box-Traversierung, mvhd/tkhd/hdlr/stsd-Auswertung |
Letzte Aktualisierung: 2026-06-15
