Help us shape the future of Go! Take the 2026 Go Developer Survey

go-media

command module
v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 27, 2026 License: MIT Imports: 7 Imported by: 0

README

go-media

Pure-Go library for probing, duration, metadata, subtitles, embedded artwork, and keyframe thumbnails on common media files—without spawning ffmpeg or ffprobe.

Built for file browsers and indexers (e.g. FileBrowser Quantum) that need fast, deterministic answers from io.ReaderAt with minimal I/O. Unsupported inputs return typed errors so the app can fall back to ffmpeg.

import "github.com/gtsteffaniak/go-media/pkg/media"

info, err := media.Probe(r, size)
thumb, err := media.ThumbnailLarge(r, size, 10) // ~10% into the timeline

Import: github.com/gtsteffaniak/go-media/pkg/media
Demo CLI: go run . probe <file> · duration · thumb [--small|--large]

What it does today

Area Coverage
Containers MP4/MOV/M4A/M4V/3GP, MKV/WebM, WAV, FLAC, OGG (Vorbis/Opus), MP3
Probe & duration Stream layout, codecs, tags summary; duration from headers (MP3 CBR estimate where needed; WebM when Duration is present)
Tags & artwork ID3, MP4 ilst, Vorbis comments (dhowden/tag); APIC / covr / FLAC PICTURE
Subtitles Sidecar SRT/VTT/ASS → WebVTT; MKV text tracks extract; external track discovery
Thumbnails MJPEG, VP8 (WebM/MKV), H.264 intra IDR (Baseline CAVLC + Main/High CABAC, 8-bit 4:2:0); embedded cover when PreferEmbedded
H.264 decode Clean-room intra-only decoder for thumbnail keyframes (docs/H264.md)—not a general player

Capability reference (by feature, with ffmpeg equivalents where useful): docs/SUPPORTED_CAPABILITIES.md.

Not in scope: transcoding, HLS, inter-frame playback, WMV/AVI/FLV/MPEG-TS, VP9/AV1/HEVC thumbnails, or full ffmpeg parity. Use go-ffmpeg for that; go-media is the fast path in front of it.

Quality and CI

Regression safety is built into the repo, not ad hoc manual testing.

  • go test ./... with CGO_ENABLED=0 on linux/amd64 and linux/arm64, with and without the checked-in PGO profile.
  • ffmpeg 9.0.2 comparison gate (make compare-gate): generated corpus of 20 assets (phone/camera-style encodes), 162 manifest cases in test/compare/expectations.json—72 must match ffmpeg/ffprobe as supported (duration, probe, tags, artwork, lyrics, subtitles, thumbnails where applicable). 7 cases must return typed unsupported (e.g. WebM VP9 thumbnails). CI uploads the HTML report as an artifact.
  • Thumbnail timing: supported thumb paths are gated on the production build (CGO_ENABLED=0 + -pgo=default.pgo) to stay within 50% of ffmpeg 9.0.2 wall time on the same fixture (stricter 10% documented as the long-term target). Visual parity uses PSNR/SSIM vs ffmpeg -frames:v 1 on keyframe decodes.
  • Fuzzing: subtitle parsers and H.264 CABAC engine (go test -fuzz); CI runs a fuzz smoke on subtitles.

Run locally: make compare (ffmpeg on PATH) or make compare-gate (pinned ffmpeg). Report: test/compare/report_site/index.html — see test/compare/README.md.

Design

  • Pure Go — CGO_ENABLED=0, cross-compiles everywhere; no cgo, no WASM, no bundled binaries in library code.
  • Bounded scope — read headers and sync samples; decode one keyframe for previews, not whole files.
  • Typed errors — ErrUnsupported, ErrUnsupportedProfile, ErrCorrupt, ErrNotMedia for clean fallback.
  • Transparent provenance — duration/thumbnail results record source (header, estimate, etc.) for caching next to ffprobe.

More: docs/PROFILING.md, docs/SIMD.md.

Repository layout

Path Role
pkg/media Public API
internal/ Format parsers, H.264 clean-room decoder, thumbnail pipeline
cmd/gomedia-compare ffmpeg/ffprobe comparison harness
main.go Small demo CLI
default.pgo Profile for release-style builds

API sketch

import "github.com/gtsteffaniak/go-media/pkg/media"

// Presets aligned with FileBrowser (small ≈ 256px Q76, large ≈ 1280×720 Q90)
thumb, err := media.ThumbnailSmall(r, size, 10)
thumb, err := media.ThumbnailLarge(r, size, 10)

thumb, err := media.Thumbnail(r, size, media.ThumbnailOptions{
    MaxWidth: 320, MaxHeight: 240,
    Quality:  85,
    Format:   "jpeg", // jpeg | png | webp-lossless
    SeekPercent: 10,
    Filter:   media.ThumbnailFilterArea,
})

info, err := media.Probe(r, size)
d, err := media.Duration(r, size)

tags, err := media.ReadTags(r, size)
vtt, err := media.SubtitleToWebVTT("movie.en.srt")

if errors.Is(err, media.ErrUnsupported) {
    // use go-ffmpeg / ffmpeg
}

See pkg/media/doc.go and docs/SUPPORTED_CAPABILITIES.md for the full surface (ListSubtitleTracks, H264KeyframeYUV420, presets, filters, etc.).

Production build

Ship with the checked-in PGO profile (tier 2 in compare reports—best balance of speed and portability):

CGO_ENABLED=0 go build -pgo=default.pgo ./...
# or: export GOFLAGS=-pgo=$PWD/default.pgo

Optional GOEXPERIMENT=simd kernels are experimental (tier 3); not required for production. make pgo regenerates the profile after hot-path changes; CI warns if it is stale (make check-pgo).

H.264 thumbnails

The in-tree decoder is intra-only (IDR keyframes): CAVLC Baseline and CABAC Main/High for 8-bit 4:2:0, with optional fast preview (reduced deblock). Profiles that decode but fail the timing gate can be listed in gatedProfiles and rejected with ErrUnsupportedProfile so callers use ffmpeg. Implementation is clean-room MIT; ffmpeg/h264bsd are behavioral references only—no LGPL source.

Details: docs/H264.md.

Roadmap (selected)

  • Matroska tags and MKV embedded artwork; MP4 embedded subtitle boxes (tx3g / wvtt).
  • AIFF/AU duration; tighter MP3 duration without estimate.
  • Lossy WebP thumbnail output (research).

License

MIT

Documentation

Overview

Demo CLI for go-media. Library import: github.com/gtsteffaniak/go-media/pkg/media

Directories

Path Synopsis
cmd
gomedia-compare command
Command gomedia-compare fetches seed media, generates ffmpeg fixtures, runs go-media vs ffprobe/ffmpeg checks, and writes a static HTML report.
Command gomedia-compare fetches seed media, generates ffmpeg fixtures, runs go-media vs ffprobe/ffmpeg checks, and writes a static HTML report.
gomedia-thumbmode command
Command thumbmode benchmarks media.Thumbnail for one asset/preset (stdout: median write ms).
Command thumbmode benchmarks media.Thumbnail for one asset/preset (stdout: median write ms).
internal
h264
Package h264 implements intra-only H.264/AVC keyframe decode for thumbnails.
Package h264 implements intra-only H.264/AVC keyframe decode for thumbnails.
h264/cleanroom
Package cleanroom implements decode-only H.264 intra for thumbnails.
Package cleanroom implements decode-only H.264 intra for thumbnails.
h264/cleanroom/bitstream
Package bitstream — reads H.264 fields from RBSP (bytes already without emulation-prevention).
Package bitstream — reads H.264 fields from RBSP (bytes already without emulation-prevention).
h264/cleanroom/decode
Package h264 parses H.264 syntax on top of bitstream/nal.
Package h264 parses H.264 syntax on top of bitstream/nal.
h264/cleanroom/nal
Package nal — parses the H.264 NAL (Network Abstraction Layer): splitting an Annex-B bytestream into NAL units, removing emulation-prevention (EBSP→RBSP) and parsing the NAL header.
Package nal — parses the H.264 NAL (Network Abstraction Layer): splitting an Annex-B bytestream into NAL units, removing emulation-prevention (EBSP→RBSP) and parsing the NAL header.
h264/frame
Package frame implements the frame buffer for H.264/AVC decoded pictures.
Package frame implements the frame buffer for H.264/AVC decoded pictures.
jpegfast
Package jpeg implements a JPEG image decoder and encoder.
Package jpeg implements a JPEG image decoder and encoder.
kernels
Package kernels provides hot numeric paths for thumbnail decode/scale/color.
Package kernels provides hot numeric paths for thumbnail decode/scale/color.
kernels/h264
Package h264 provides SIMD-oriented H.264 decode kernels: 4×4 IDCT residual, 4×4 prediction+residual write, and future intra/8×8 helpers.
Package h264 provides SIMD-oriented H.264 decode kernels: 4×4 IDCT residual, 4×4 prediction+residual write, and future intra/8×8 helpers.
mp3
ogg
vp8decode
Package vp8decode decodes VP8 video frames (key and inter) for thumbnails.
Package vp8decode decodes VP8 video frames (key and inter) for thumbnails.
wav
pkg
media
Package media provides pure-Go fast paths for probing, metadata, subtitles, and thumbnails used by file browsing applications.
Package media provides pure-Go fast paths for probing, metadata, subtitles, and thumbnails used by file browsing applications.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL