Pure-Go media pipelines for Go services — describe the work, see the plan, then run it.
goav is a small, composable grammar for building media workflows inside Go
applications: pick streams, declare operations, fan out, and route to
destinations. It is pure Go — no cgo, no FFmpeg, no system libraries — so a
recipe compiles into your binary and ships as one artifact. Every recipe is
inspectable data: Describe shows the exact graph and Explain the typed plan
before any resource opens, and every refusal is a structured error that names
its fix.
// Decode, downscale, re-encode, and mux. The recipe is validated before it runs.
err := bundle.Run(ctx, goav.From(goav.FileInput("in.mp4", in)).
Video().
Decode().
Resize(1280, 720).
Encode(codec.VP9(codec.Bitrate(2_000_000))).
To(goav.Write("out.webm", out)))The model reads top to bottom — inputs, stream selection, ordered operations, optional fanout, destinations, and a runnable task:
From(inputs) ─▶ .Audio()/.Video() ─▶ operations ─▶ .Branches(...) ─▶ .To(dst) ─▶ Task
input stream select decode/copy/ fanout output Run/Close
resize/encode
go get github.com/thesyncim/goavThe bundled pure-Go adapters — VP8/VP9, AV1, Opus, AAC, H.264 decode, and
Matroska/WebM/IVF containers plus MP4 (read) — live in goav/bundle.
bundle.Run and bundle.Build give you a runtime with the standard set;
build your own with goav.New(...) to register exactly the adapters you
need, per service, with no global state. The codec backends are pure-Go
ports of the reference implementations (libvpx and friends), maintained as
separate thesyncim/* modules — no cgo anywhere in the dependency graph.
| Need | Shape | Details |
|---|---|---|
| Record / remux packets | From(input).Copy().To(goav.Write(...)) |
Use cases |
| Decode to your code | From(input).Audio().Decode().To(goav.Sink(...)) |
Operations |
| Transform and encode | .Decode().Resize(...).Encode(codec) / .Decode().Resample(...).Encode(codec) |
Operations |
| Fan one stream out | .Copy().Branches(...) (packets), .Decode().Branches(...) (frames) |
Use cases |
| Own a media boundary | goav.Source(...), goav.Input(provider), goav.Sink(...), goav.Custom(...) |
Extension cookbook |
Use goav.Mux(name, destination) to feed several branches into one mux or sink
group; repeated ungrouped destination names are rejected so sharing stays explicit.
- Pure Go, one binary. No cgo, no FFmpeg, no system codecs —
go buildand ship. - Plan before you run.
Describereturns the node-for-node graph andExplaina typed report (inputs, codecs, shapes, adapters, decisions) before any resource opens — both machine-consumable as stable JSON. - Errors you can act on. Every build refusal is a
*goav.BuildErrorwith a stable family and code, the failing operation, and concrete fixes — not a string. - Live timing built in. One shared clock per task: synchronized playout, pause/seek/rate controls, and QoS lateness reports — see Flow control.
- Explicit, app-owned extension. Sources, sinks, destinations, codecs, formats, and filters plug in through exported interfaces, per runtime.
The recipes above are the v1-supported front door. Live mutation (Attach),
control sockets, converged streams (Mix/Composite/Select), and the expert
graph are governed pre-v1 — implemented and tested, but not the beginner
path. See V1 scope. goav is pre-v1: breaking changes can land
until the first tag.
| Topic | Start here |
|---|---|
| Operation rules and shape errors | Operations, Errors, Error catalog |
| Recipes, branches, live rooms, RTP, WebRTC | Use cases |
| Extension authoring | Extension cookbook, Adapter authoring, Adapters |
| Copyable examples | custom source, provider source, custom destination, custom filter, transactional writer, custom codec, custom join |
| Runtime control and observation (governed pre-v1) | Control plane, control-plane host, Components |
| Where goav fits | vs GStreamer, Architecture, Roadmap |
| Performance and trust | Performance, Releasing, Compatibility, Repository trust |