Documentation
¶
Overview ¶
Package ffdecode wraps ffmpeg subprocesses for raw audio/video decode — shared between apps/amp (audio only) and apps/vid (video, plus a separate ffmpeg process for the video's own audio track). Never a linked decoder library, on purpose: keeps the desktop binary itself free of format-specific code, matching the GUI-TUI Bridge's Xvfb — a soft runtime dependency, only needed if you actually use the feature.
Index ¶
Constants ¶
const ( SampleRate = 48000 Channels = 2 )
SampleRate/Channels match internal/audio's fixed output format — decode straight to what the shared oto.Context expects, no separate resample step.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type AudioEvent ¶
AudioEvent is how an AudioStream's feeder goroutine reports back — never by touching caller state directly (see AudioStream's doc comment for why); drain this from whatever single-threaded path owns your app state, exactly like every other background-goroutine result channel in this codebase (apps/calendar/sync.go, apps/settings/calendar_page.go).
type AudioStream ¶
type AudioStream struct {
PCM chan []int16
// contains filtered or unexported fields
}
AudioStream decodes one file's audio track to raw PCM via an ffmpeg subprocess. PCM delivers interleaved int16 samples at SampleRate/ Channels.
func DecodeAudio ¶
func DecodeAudio(path string, onChunk func([]int16), events chan<- AudioEvent) (*AudioStream, error)
DecodeAudio launches ffmpeg on path and begins feeding PCM into the returned stream's PCM channel. events receives exactly one AudioEvent when the track ends (Ended=true) or decode fails (Err set). onChunk, if non-nil, sees each chunk synchronously in the feeder goroutine, before it's sent to PCM — callers needing per-chunk work (Amp's visualizer) should keep that work cheap and do their own synchronization, since it runs on a different goroutine than whatever's reading PCM. Passed in here rather than set on the returned struct: it must be fixed before the feeder goroutine starts, not mutated after — setting it post-construction would race that goroutine's first read of it (confirmed by go test -race while writing this).
func DecodeAudioAt ¶
func DecodeAudioAt(path string, seek time.Duration, onChunk func([]int16), events chan<- AudioEvent) (*AudioStream, error)
DecodeAudioAt is DecodeAudio starting from seek into the file (0 for the beginning) — an input-side `-ss` seek, ffmpeg's fast, keyframe-ish seek rather than a precise decode-and-discard one. Vid uses this for scrubbing; Amp always seeks to zero via plain DecodeAudio.
func (*AudioStream) Stop ¶
func (s *AudioStream) Stop()
Stop kills the ffmpeg subprocess and unblocks feed if it's stuck mid-send with nothing left to drain it. Safe to call more than once, and safe to call after decode has already finished on its own.
type VideoEvent ¶
VideoEvent is how a VideoStream's feeder goroutine reports back — same drain-from-your-single-threaded-path contract as AudioEvent.
type VideoFrame ¶
VideoFrame is one decoded frame: raw RGB24 (3 bytes/pixel, no alpha), W*H*3 bytes, row-major.
func (VideoFrame) Image ¶
func (f VideoFrame) Image() image.Image
Image returns f as an image.Image — wraps Pix directly, no copy, for feeding straight into internal/gfx.EncodeHalfBlockFit.
type VideoStream ¶
type VideoStream struct {
Frames chan VideoFrame
// contains filtered or unexported fields
}
VideoStream decodes one file's video track to raw RGB24 frames via an ffmpeg subprocess, pre-scaled to w x h pixels at fps — scaling in ffmpeg rather than after decode keeps the pipe's byte volume (and the per-frame conversion cost) down to roughly what the terminal can actually show, instead of piping full source resolution just to downsample it a moment later.
func DecodeVideo ¶
func DecodeVideo(path string, w, h, fps int, events chan<- VideoEvent) (*VideoStream, error)
DecodeVideo launches ffmpeg on path and begins feeding frames into the returned stream's Frames channel. events receives exactly one VideoEvent when the video ends (Ended=true) or decode fails (Err set).
func DecodeVideoAt ¶
func DecodeVideoAt(path string, seek time.Duration, w, h, fps int, events chan<- VideoEvent) (*VideoStream, error)
DecodeVideoAt is DecodeVideo starting from seek into the file (0 for the beginning) — see DecodeAudioAt's doc comment; Vid uses this for scrubbing.
func (*VideoStream) Stop ¶
func (s *VideoStream) Stop()
Stop kills the ffmpeg subprocess and unblocks feed if it's stuck mid-send with nothing left to drain it. Safe to call more than once, and safe to call after decode has already finished on its own.