← Back to list

The Missing Piece in Go Media Processing

Most Go media libraries eventually run into the same problem.

Dnchg · 2026-06-02 18:54 · 0 claps · 2.3 min read
#golang #ffmpeg #videos #encoder-decoder
Open on Medium ↗

The Missing Piece in Go Media Processing

Most Go media libraries eventually run into the same problem.

They don’t actually ship with a decoder.

Instead, they depend on a system-installed FFmpeg package, shared libraries, platform-specific DLLs, or external binaries that must exist on the target machine.

Everything works during development. Then deployment begins.

Suddenly you’re debugging missing DLLs on Windows, mismatched FFmpeg versions on Linux, Homebrew differences on macOS, container images that don’t contain the required libraries, or production machines where upgrading a package unexpectedly breaks media processing.

So there is a real need in something different.

The Goal

I wanted a decoder that:

  • Works from pure Go code
  • Produces a single distributable binary
  • Requires no FFmpeg installation
  • Requires no runtime shared libraries
  • Supports modern codecs such as AV1, H.264, H.265, VP8, VP9, Opus, AAC, MP3, and others
  • Can read from files, memory buffers, HTTP streams, pipes, SSH streams, and any Go reader

The result is **gopeg**.

Instead of relying on whatever media stack happens to be installed on a machine, the required FFmpeg components and dav1d decoder are statically linked into the application during build time.

When the binary is produced, everything needed for decoding is already inside it.

Why This Matters

A surprising amount of engineering time is spent solving deployment problems rather than application problems.

A typical workflow often looks like this:

  • Install FFmpeg
  • Install matching shared libraries
  • Package them correctly
  • Ensure production machines have compatible versions
  • Hope future operating system updates don’t break anything

The application becomes dependent on external state.

With static linking, the deployment story becomes much simpler.

go build

Ship the binary. And that’s it.

No external codec packages. No DLL distribution. No runtime library discovery. No “works on my machine.”

Streaming Support

Another design goal was flexibility.

The decoder does not need direct file access.

It can operate on arbitrary streams:

resp, _ := http.Get(url)
dec, err := gopeg.NewDecoder(resp.Body)

Or:

dec, err := gopeg.NewDecoder(os.Stdin)

Or even data arriving through an SSH connection or custom transport.

For seekable sources, additional metadata such as duration can be extracted more accurately.

For non-seekable streams, decoding still works normally and media can be processed as data arrives.

Modern Codec Support

The decoder currently supports common video and audio formats through FFmpeg and dav1d integration.

Examples include:

  • AV1
  • H.264
  • H.265 / HEVC
  • VP8
  • VP9
  • AAC
  • Opus
  • MP3
  • FLAC

For AV1 specifically, dav1d is used because it remains one of the fastest and most widely respected AV1 software decoders available.

Simplicity Over Abstraction

One thing I wanted to avoid was building an enormous framework.

The API is intentionally straightforward.

Open a source:

dec, err := gopeg.NewDecoder(file)

Read metadata:

meta := dec.Meta()

Decode frames:

for {
    frame, err := dec.DecodeFrame()
    if err != nil {
        panic(err)
    }
    if frame == nil {
        break
    }
    // process frame
}

No background workers. No hidden processes. No external binaries. Just decoding.

Final Thoughts

FFmpeg is an incredible piece of software, but depending on a system FFmpeg installation creates operational complexity that many applications don’t actually need.

For my use cases, a statically linked approach made more sense.

The result is a media decoder that is easy to embed, easy to deploy, and predictable across environments.

Build once.

Ship one binary.

Decode media anywhere.

If that sounds useful, check out the gopeg project and let me know what formats or features you’d like to see next.


메타데이터
post_id
bc1908875a7c
slug
how-i-built-a-runtime-dependency-free-video-decoding-library-in-go-bc1908875a7c
url
https://medium.com/@d1nch8g_91775/how-i-built-a-runtime-dependency-free-video-decoding-library-in-go-bc1908875a7c
canonical_url
https://medium.com/@d1nch8g_91775/how-i-built-a-runtime-dependency-free-video-decoding-library-in-go-bc1908875a7c
author_url
https://medium.com/@d1nch8g_91775
status
ok
fetched_at
2026-06-09 15:37:30