Documentation
¶
Overview ¶
Package transcode wraps ffmpeg and ffprobe for local audio files.
Callers pass file paths; the package resolves the ffmpeg/ffprobe binaries, limits concurrent processes when configured, captures bounded stderr for diagnostics, and terminates the process, or its process group where supported, when a context is canceled.
A Command is just an argument list, so command construction can be tested without starting ffmpeg. A Spec selects the target Codec, optional bitrate, and pre-encode audio filters. Loudness normalization and cuts are passed in as filters so they can run in the same encode as the format conversion.
Processing uses seekable files, not pipes, because several muxers need seeks while writing. Outputs are staged next to the destination path and renamed into place only after ffmpeg exits successfully. CodecCopy is the no-encode mode; FLAC, ALAC, and WAV decode and encode with lossless codecs.
Index ¶
- type Codec
- type Command
- type ProbeFormat
- type ProbeResult
- type ProbeStream
- type Result
- type RunError
- type RunResult
- type Runner
- func (r *Runner) FFmpegPath() string
- func (r *Runner) FFprobePath() string
- func (r *Runner) Probe(ctx context.Context, input string) (ProbeResult, error)
- func (r *Runner) ProbeURL(ctx context.Context, url string, headers http.Header) (ProbeResult, error)
- func (r *Runner) Run(ctx context.Context, cmd Command) (RunResult, error)
- func (r *Runner) Transcode(ctx context.Context, input, output string, spec Spec) (Result, error)
- type RunnerConfig
- type Spec
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Codec ¶
type Codec uint8
Codec identifies an output audio encoding. CodecCopy stream-copies the source audio into a container. The lossless codecs (FLAC, ALAC, WAV) still decode and encode; they are not stream copies.
const ( CodecCopy Codec = iota // stream copy / remux (the only no-re-encode path) CodecFLAC // lossless re-encode (.flac) CodecALAC // lossless re-encode (Apple Lossless in .m4a) CodecWAV // lossless PCM (.wav) CodecMP3 // libmp3lame (V0 by default, CBR when a bitrate is set) CodecAAC // native AAC in .m4a CodecOpus // libopus (.opus) CodecVorbis // libvorbis (.ogg) )
func (Codec) Extension ¶
Extension returns the canonical file extension (without a dot) for c, or "" for CodecCopy (whose container follows the source).
func (Codec) IsLossless ¶
IsLossless reports whether c uses a stream copy or a lossless encoder. For CodecWAV, Transcode probes the source and picks the PCM encoder with wavEncoder; sources that do not report a usable depth use the 16-bit fallback.
type Command ¶
type Command struct {
Args []string
}
Command is a built ffmpeg invocation. Args excludes the binary name.
type ProbeFormat ¶
ProbeFormat describes the container.
type ProbeResult ¶
type ProbeResult struct {
Format ProbeFormat
Streams []ProbeStream
}
ProbeResult is the parsed subset of ffprobe's -show_format -show_streams JSON: container metadata plus per-stream codec details.
func (ProbeResult) AudioStream ¶
func (p ProbeResult) AudioStream() (ProbeStream, bool)
AudioStream returns the first audio stream and true, or a zero stream and false when the result carries no audio. Probe rejects no-audio inputs with waxerr.ErrUnsupportedInput, so a result obtained from Probe always has one; this accessor is for inspecting a ProbeResult directly.
type ProbeStream ¶
type ProbeStream struct {
Index int
CodecType string // "audio", "video", ...
CodecName string // e.g. "opus", "aac", "flac"
SampleRate int // Hz (audio)
Channels int
BitRate int
Duration time.Duration
// SampleFmt is ffprobe's sample_fmt (for example "s16", "s32", or "fltp").
// BitsPerSample is the coded PCM depth. BitsPerRawSample is the source depth
// reported by some lossless codecs, such as a 24-bit FLAC. A zero value means
// ffprobe did not report the field.
SampleFmt string
BitsPerSample int
BitsPerRawSample int
}
ProbeStream describes one media stream.
type Result ¶
type Result struct {
Output string // final output path
Size int64 // output size in bytes (0 if it could not be stat'd)
Codec Codec // codec the output was encoded with
}
Result reports a completed transcode.
type RunError ¶
RunError reports a non-zero ffmpeg/ffprobe exit and includes a bounded stderr tail for diagnosis.
type Runner ¶
type Runner struct {
// contains filtered or unexported fields
}
Runner executes ffmpeg and ffprobe. It resolves the binaries once, bounds the number of concurrent processes, captures a bounded tail of stderr for diagnostics, and terminates the process on context cancellation. On Unix it uses a process group so helper children are signaled with the ffmpeg process. Runner is safe for concurrent use.
func NewRunner ¶
func NewRunner(cfg RunnerConfig) (*Runner, error)
NewRunner resolves the ffmpeg and ffprobe binaries and returns a Runner. It returns a wrapped waxerr.ErrFFmpegNotFound if either binary cannot be located.
func (*Runner) FFmpegPath ¶
FFmpegPath returns the resolved ffmpeg binary path.
func (*Runner) FFprobePath ¶
FFprobePath returns the resolved ffprobe binary path.
func (*Runner) Probe ¶
Probe runs ffprobe on a local input and returns the parsed result. ffprobe failures, malformed JSON, and media with no audio stream are reported as waxerr.ErrUnsupportedInput.
func (*Runner) ProbeURL ¶
func (r *Runner) ProbeURL(ctx context.Context, url string, headers http.Header) (ProbeResult, error)
ProbeURL probes a remote input with the supplied HTTP headers. This is used for signed media URLs whose User-Agent or token headers must match the resolver. Empty headers behave like Probe. ProbeURL can block on the network, so callers should pass a bounded context.
func (*Runner) Run ¶
Run executes ffmpeg with cmd's arguments. A non-zero exit becomes a *RunError carrying the stderr tail; a canceled context returns ctx.Err() after the child process has been stopped.
func (*Runner) Transcode ¶
Transcode reads input, applies spec.Filters, encodes per spec, and writes the result to output. The output is staged in a temp file in output's directory and atomically renamed into place on success; on failure or cancellation the temp is removed and any existing file at output is left untouched.
Input must be a seekable local file. A stream copy (CodecCopy) combined with filters is rejected with waxerr.ErrIncompatibleSpec before any process starts.
type RunnerConfig ¶
type RunnerConfig struct {
// FFmpegPath and FFprobePath override the binaries; empty looks them up in
// PATH by name.
FFmpegPath string
FFprobePath string
// ShutdownGrace is how long a canceled process is given to exit after SIGTERM
// before it is force-killed (default 5s).
ShutdownGrace time.Duration
// MaxProcs bounds concurrent ffmpeg/ffprobe processes (0 = unlimited). It
// guards local CPU independently from network parallelism.
MaxProcs int
// Logger receives debug logs. Nil discards them.
Logger *slog.Logger
}
RunnerConfig configures a Runner. The binary paths are looked up in PATH when left empty.
type Spec ¶
type Spec struct {
Codec Codec
Bitrate int
// Filters is a comma-joined -af chain for linear audio filters such as
// loudnorm. It is mutually exclusive with FilterComplex.
Filters []string
// FilterComplex is a complete -filter_complex graph. The graph must read the
// source audio from [0:a:0] and write the final audio to [out]; buildCommand
// maps [out] as the only output stream. Use it for labeled or multi-input
// graphs such as concat/acrossfade. It is mutually exclusive with Filters and
// cannot be used with CodecCopy.
FilterComplex string
}
Spec describes a transcode. Codec selects the output codec, Bitrate overrides lossy preset defaults in bits/sec, and the optional filter fields run before encoding. The zero value is a stream copy with no filters.