2026-06-07 00:44:14 +03:00
2026-06-07 00:40:27 +03:00
2026-06-07 00:40:27 +03:00
2026-06-06 18:04:56 +00:00
2026-06-07 00:40:27 +03:00
2026-06-07 00:40:27 +03:00
2026-06-07 00:40:27 +03:00
2026-06-07 00:40:27 +03:00
2026-06-07 00:40:27 +03:00
2026-06-07 00:40:27 +03:00
2026-06-07 00:40:27 +03:00
2026-06-07 00:40:27 +03:00
2026-06-06 18:04:56 +00:00
2026-06-07 00:44:14 +03:00

gopeg banner

gopeg

Go video decoding library with no runtime dependencies. FFmpeg is statically linked — import the package and get a single binary, no system installs required.

Installation

go get m8sh.su/x/gopeg

Requires CGO and a C compiler:

# arch/manjaro
sudo pacman -S gcc

# debian/ubuntu
sudo apt install gcc

Platforms

Platform Arch Status
linux/amd64 x86_64 Supported
linux/arm64 AArch64 Supported
windows/amd64 x86_64 Supported
darwin/amd64 x86_64 Supported
darwin/arm64 Apple Silicon Supported
web/wasm wasm32 🚧 Coming soon

Supported formats

Codecs
Video H.264, H.265/HEVC, AV1, VP9, VP8, MPEG-4
Audio AAC, MP3, Opus, Vorbis, FLAC, PCM
Containers MP4, MKV, WebM, AVI, FLV, OGG, IVF, MPEGTS

Features

  • Decode video frames as image.NRGBA — standard Go image type, no conversion needed
  • Decode audio frames as []float32 interleaved PCM
  • Read from any io.Reader — files, in-memory buffers, HTTP streams, pipes
  • Seeking supported when the reader implements io.Seeker; works without it too
  • Zero runtime dependencies — all FFmpeg and dav1d libs statically linked
  • Single go build for all supported platforms

Quick start

package main

import (
    "fmt"
    "image/png"
    "os"

    "m8sh.su/x/gopeg"
)

func main() {
    f, _ := os.Open("video.mp4")
    defer f.Close()

    dec, err := gopeg.NewDecoder(f)
    if err != nil {
        panic(err)
    }
    defer dec.Close()

    meta := dec.Meta()
    fmt.Printf("duration: %.2fs\n", meta.Duration.Seconds())
    fmt.Printf("video: %dx%d %s @ %d/%d fps\n",
        meta.Video.Width, meta.Video.Height,
        meta.Video.CodecName,
        meta.Video.FPSNum, meta.Video.FPSDen)
    if meta.Audio != nil {
        fmt.Printf("audio: %dHz %dch %s\n",
            meta.Audio.SampleRate,
            meta.Audio.Channels,
            meta.Audio.CodecName)
    }

    for {
        frame, err := dec.DecodeFrame()
        if err != nil {
            panic(err)
        }
        if frame == nil {
            break // EOF
        }
        if frame.Video != nil {
            f, _ := os.Create("frame.png")
            png.Encode(f, frame.Video.Img)
            f.Close()
        }
        if frame.Audio != nil {
            fmt.Printf("audio pts=%v samples=%d\n",
                frame.Audio.PTS,
                len(frame.Audio.Samples)/frame.Audio.Channels)
        }
    }
}

API

// Open a decoder from any reader. If r also implements io.Seeker,
// FFmpeg will use it for random access where the format requires it.
func NewDecoder(r io.Reader) (*Decoder, error)

// Returns duration, video/audio stream info. Safe to call before decoding.
func (d *Decoder) Meta() Meta

// Decode the next video or audio frame. Returns nil, nil on EOF.
// Frame.Video and Frame.Audio are mutually exclusive per call.
func (d *Decoder) DecodeFrame() (*Frame, error)

// Release all FFmpeg resources. Safe to call multiple times.
func (d *Decoder) Close()

Types

type Meta struct {
    Duration time.Duration
    Video    *VideoMeta  // nil if no video stream
    Audio    *AudioMeta  // nil if no audio stream
}

type VideoMeta struct {
    Width, Height int
    FPSNum, FPSDen int
    CodecName string
}

type AudioMeta struct {
    SampleRate int
    Channels   int
    CodecName  string
}

type Frame struct {
    Video *VideoFrame
    Audio *AudioFrame
}

type VideoFrame struct {
    Img      *image.NRGBA
    PTS      time.Duration
    Duration time.Duration
}

type AudioFrame struct {
    Samples    []float32  // interleaved
    Channels   int
    SampleRate int
    PTS        time.Duration
}

Building from source

The vendor/ directory contains prebuilt static libraries for all supported platforms. To rebuild from scratch, delete vendor/ and use the build script:

# arch/manjaro
sudo pacman -S gcc meson ninja nasm aarch64-linux-gnu-gcc mingw-w64-gcc

# debian/ubuntu
sudo apt install gcc meson ninja-build nasm gcc-aarch64-linux-gnu gcc-mingw-w64-x86-64
go run cmd/build/main.go

Script clones necessary repositories (default dav1d mirror and FFmpeg mirror), builds them into static libraries for linking with CGO with preset of required parameters and produces a vendor directory.

License

GPLv3 - this is free software. Contributions are welcome, feel free to open an issue.

S
Description
Go video decoding solution (no runtime dependencies)
Readme GPL-3.0
75 MiB
2026-06-06 23:42:09 +00:00
Languages
Go 98.9%
C 1.1%