Astiav video provider
Video transcoding, thumbnail extraction, and metadata probing implemented against FFmpeg through the asticode/go-astiav cgo bindings.
Overview
The astiav provider implements media.VideoTranscoderPort and media.StreamingTranscoderPort against FFmpeg's libav* family of libraries through go-astiav. The provider asserts both ports at compile time, so it drops into piko's video service with no adapter glue beyond NewProvider and WithVideoProvider.
Transcoding accepts an io.Reader and returns an io.ReadCloser that streams the encoded output. Both ends run through custom astiav IO contexts backed by an io.Pipe, so the data never touches the disk. ExtractCapabilities reads the input metadata and reports dimensions, codec, duration, bitrate, and framerate. The codec registry handles h264, h265, and vp9, with output containers mp4, webm, and mkv.
Transcoding, thumbnail extraction, and metadata probing work today. HLS and DASH streaming output do not. TranscodeHLS is a stub that returns an unimplemented error, and the provider reports no DASH support.
An internal semaphore caps concurrency. The default limit is 10 concurrent transcodes. Override the limit through Config.MaxConcurrentTranscodes. Every operation records OpenTelemetry spans and metrics, including active transcode counts, durations, and per-codec counters.
The provider accepts the EnableHWAccel field, but the encoder and decoder paths ignore it. All encode and decode work runs in software.
Requirements
- Build tag:
//go:build ffmpeg. Build withgo build -tags ffmpeg ./.... - System libraries: FFmpeg with the
libav*development headers (apt install libavcodec-dev libavformat-dev libavutil-dev libswscale-dev,brew install ffmpeg, or the equivalent for your distribution). - A working C toolchain (cgo enabled).
Configuration
import (
"piko.sh/piko/wdk/media"
"piko.sh/piko/wdk/media/video_provider_astiav"
)
provider, err := video_provider_astiav.NewProvider(video_provider_astiav.Config{
VideoServiceConfig: media.VideoServiceConfig{}, // optional; input and output limits
MaxConcurrentTranscodes: 10, // optional; default 10
EnableHWAccel: false, // optional; accepted but ignored
})
if err != nil {
return err
}
The constructor returns (*Provider, error). There is no FFmpegPath field. The astiav bindings link FFmpeg as a library, not as a subprocess.
VideoServiceConfig carries the limits that gate which inputs the service accepts. Leave the embedded struct zero to take the defaults. Those defaults are 3840 by 2160 pixels (4K), 8,294,400 total pixels, 500 MB input size, a 5 minute transcode timeout, 20 Mbps bitrate, and 60 frames per second. Set any field to a positive value to override that one limit. The struct holds no codec allow-list. The codec registry fixes the supported codecs.
Bootstrap
piko.New and the video options live in package piko at the module root.
import "piko.sh/piko"
ssr := piko.New(
piko.WithVideoProvider("astiav", provider),
piko.WithDefaultVideoProvider("astiav"),
)
WithVideoProvider takes the provider as a media.VideoTranscoderPort, the interface this provider satisfies. The first provider registered becomes the default unless WithDefaultVideoProvider names another. Register no video provider and the video service stays nil. Components like piko:video then degrade to basic HTML output without transcoding.
Run mode
The ffmpeg build tag and the cgo dependency tie this provider to compiled builds. The interpreted dev mode (dev-i) cannot load cgo packages, so a video provider behind the build tag does not register there. Build with the tag and a C toolchain, or piko:video degrades as described above.
See also
Other media providers:
- vips, image transformer for thumbnails generated outside the video pipeline.
- imaging, pure-Go image transformer for development and tests.
Framework docs:
- Media API reference, every type and method on the image and video services, including
VideoTranscoderPortandStreamingTranscoderPort.
External:
- FFmpeg, the underlying media framework.
- asticode/go-astiav, the Go bindings used by this provider.