Documentation
¶
Overview ¶
Package encode runs ffmpeg encoders with codec-specific settings: x264, x265 and SVT-AV1 on the CPU, or NVIDIA NVENC (see Hardware).
Index ¶
- Variables
- type BurnEncoder
- type BurnSegment
- type BurnSpec
- type Chunk
- type ChunkSource
- type Codec
- func (c Codec) Args(p Params) []string
- func (c Codec) ChunkCommandLine(src ChunkSource, dst string, chunks []Chunk, p Params) string
- func (c Codec) CommandLine(src, dst string, p Params) string
- func (c Codec) InputArgs() []string
- func (c Codec) QualityOption() string
- func (c Codec) Step() float64
- func (c Codec) Supports(f Feature) bool
- type CopyPart
- type CopySegment
- type CopySpec
- type DigestPart
- type DigestSpec
- type FFmpeg
- func (f *FFmpeg) Burn(ctx context.Context, spec BurnSpec) error
- func (f *FFmpeg) CheckBurn(ctx context.Context, encoder BurnEncoder) error
- func (f *FFmpeg) Copy(ctx context.Context, spec CopySpec) error
- func (f *FFmpeg) DecodeRaw(ctx context.Context, src, dst string, withGrain bool) error
- func (f *FFmpeg) Decodes(ctx context.Context, path string) error
- func (f *FFmpeg) Digest(ctx context.Context, spec DigestSpec) error
- func (f *FFmpeg) Encode(ctx context.Context, codec Codec, src, dst string, p Params) error
- func (f *FFmpeg) EncodeChunks(ctx context.Context, codec Codec, src ChunkSource, dst string, chunks []Chunk, ...) error
- func (f *FFmpeg) EncodeRendition(ctx context.Context, codec Codec, spec RenditionSpec) error
- func (f *FFmpeg) Noise(ctx context.Context, path string, width, height, step int) (grain.Stats, error)
- type Feature
- type Hardware
- type Option
- type Params
- type RenditionSpec
- type Signal
Constants ¶
This section is empty.
Variables ¶
var ErrBurnSegment = errors.New("burn segment does not match the plan")
ErrBurnSegment is returned by Burn when a segment did not render the frames planned (a seek that landed after the segment's first frame): the segments are unusable, a single pass still is.
var ErrDecode = errors.New("decoding errors")
ErrDecode is returned by Decodes for a file ffmpeg reports errors on.
var ErrNoChunks = errors.New("chunked encode needs at least one chunk")
ErrNoChunks is returned when a chunked encode is asked for no chunk.
var ErrNoSegments = errors.New("digest needs at least one segment")
ErrNoSegments is returned when a digest is asked for no segment.
var ErrNoSubtitlesFilter = errors.New("ffmpeg has no subtitles filter (built without libass)")
ErrNoSubtitlesFilter is returned by CheckBurn when ffmpeg has no subtitles filter: it was built without libass.
var ErrStalled = errors.New("encoder stalled: its output stopped growing")
ErrStalled is returned for an encode whose output stopped growing for longer than the stall timeout (see WithStallTimeout), twice in a row.
var ErrUnknownBurnEncoder = errors.New("unknown overlay encoder")
ErrUnknownBurnEncoder is returned for an unknown burn encoder.
var ErrUnknownCodec = errors.New("unknown codec")
ErrUnknownCodec is returned for an unsupported codec name.
var ErrUnknownHardware = errors.New("unknown encoder implementation")
ErrUnknownHardware is returned for an unknown encoder implementation (Hardware).
Functions ¶
This section is empty.
Types ¶
type BurnEncoder ¶
type BurnEncoder string
BurnEncoder is the H.264 encoder of a burn (BurnSpec.Encoder).
const ( // BurnAuto encodes with VideoToolbox on macOS when it encodes a test // frame, with x264 otherwise (the zero value). NVENC is never chosen // automatically: it needs the GPU checks of an explicit request. BurnAuto BurnEncoder = "" // BurnX264 encodes with libx264 (BurnSpec.CRF and Preset). BurnX264 BurnEncoder = "x264" // BurnVideoToolbox encodes with Apple's hardware encoder // (h264_videotoolbox), at constant quality (Apple silicon). BurnVideoToolbox BurnEncoder = "videotoolbox" // BurnNVENC encodes with NVIDIA's hardware encoder (h264_nvenc), and // decodes with NVDEC. BurnNVENC BurnEncoder = "nvenc" )
Burn encoders. A burn is a debug copy: the hardware encoders write it several times faster than x264, at a quality where the overlay's text stays crisp (see docs/overlay.md).
func ParseBurnEncoder ¶
func ParseBurnEncoder( s string, ) (BurnEncoder, error)
ParseBurnEncoder reads a burn encoder: auto (or empty), x264, videotoolbox or nvenc.
func (BurnEncoder) Hardware ¶
func (e BurnEncoder) Hardware() bool
Hardware reports whether e encodes on a hardware encoder.
func (BurnEncoder) String ¶
func (e BurnEncoder) String() string
String returns the encoder name, "auto" for the zero value.
type BurnSegment ¶
type BurnSegment struct {
// From is when the segment's first frame is presented, on the source's
// container timeline; To when the frame after its last one is (0: the
// segment runs to the end).
From, To media.Duration
// Frames is the number of frames of the segment: a segment rendering
// another count fails the burn with ErrBurnSegment.
Frames int
// Subtitles, when set, is the script of the segment instead of
// BurnSpec.Subtitles: the same script, with only the events shown
// during the segment, loads and renders faster.
Subtitles string
}
BurnSegment is a run of consecutive frames of the source, rendered by its own ffmpeg (BurnSpec.Segments). Each ffmpeg keeps the source's timestamps (-copyts), seeks burnPreroll before the segment, decodes from the keyframe it lands on and keeps the frames presented from From to To: the segments hold every frame once whatever the keyframes, and the script draws on each frame what it draws in a single pass. The segments are joined without re-encoding, each one starting where the previous one's frames end, and the source's audio is added once.
type BurnSpec ¶
type BurnSpec struct {
// Source is the video; Subtitles the ASS script; Output the copy
// written (H.264, 8-bit 4:2:0).
Source, Subtitles, Output string
// Height scales the copy to that height before the script is drawn
// (0 keeps the source's): a smaller copy encodes faster, and libass
// scales the script to it.
Height int
// Encoder is the H.264 encoder (BurnAuto: VideoToolbox on macOS, x264
// elsewhere).
Encoder BurnEncoder
// CRF and Preset are the x264 settings (default 20, fast).
CRF float64
Preset string
// Segments, when there are two or more, render the copy in runs of
// consecutive frames, Workers at once, joined without re-encoding (see
// BurnSegment): one ffmpeg draws the overlay on a single thread, too
// slowly to feed a hardware encoder.
Segments []BurnSegment
// Workers is how many segments render at once (0: the encoder's
// default; 1 or less renders in a single pass, as x264 does by
// default).
Workers int
// Start is the start of the source's timeline (its container's start
// time), which ffmpeg subtracts from the timestamps its filters see in
// a single pass: segments subtract it too, so that the script is the
// same in both modes.
Start media.Duration
// AudioCodec is the codec of the source's first audio stream, "" when
// it has none: its audio is copied when the output container can hold
// it, encoded to AAC otherwise.
AudioCodec string
// FontsDir, when set, is searched for the script's fonts before the
// system's.
FontsDir string
// Progress, when set, is called with the number of frames written so
// far, about twice a second.
Progress func(frames int)
}
BurnSpec describes a burn: a copy of a video with an ASS subtitle script drawn on its frames.
type Chunk ¶
type Chunk struct {
// Start is the index of the chunk's first frame.
Start int `json:"start"`
// Frames is the number of frames of the chunk.
Frames int `json:"frames"`
CRF float64 `json:"crf"`
// Width and Height, when set, override the encode's resolution for the
// chunk: per-shot resolution changes the resolution at chunk
// boundaries (always keyframes).
Width int `json:"width,omitempty"`
Height int `json:"height,omitempty"`
}
Chunk is a run of consecutive frames encoded with its own CRF. Chunked encoding is how per-shot settings reach every encoder the same way: x264 and x265 accept zones through their private parameters, but SVT-AV1 has no per-frame quantiser control reachable from ffmpeg. Each chunk is encoded separately (it starts with a keyframe) and the chunks are joined without re-encoding; decoding the joined file gives exactly the frames of the separate chunks for x264, x265 and SVT-AV1, whose headers do not depend on the CRF. Chunks starting on the fixed GOP grid keep the keyframes of every rung aligned, as ABR segmenting requires.
type ChunkSource ¶
type ChunkSource struct {
Path string
// Rate is the frame rate of the video, which places the chunks in time.
Rate media.Rational
// Origin is the presentation time of the first frame of the video on
// the container's timeline (bitstream.Report.Start), which chunks are
// seeked on (absolute seeks): a chunk starts at Origin plus its frames'
// time. Without it, a video starting after its audio would be seeked
// from the container's start, and every chunk would start early by the
// difference. A digest starts at 0.
Origin media.Duration
}
ChunkSource is the video a chunked encode reads.
type Codec ¶
type Codec struct {
// Name is the user-facing name: h264, hevc or av1.
Name string `json:"name"`
// Encoder is the ffmpeg encoder.
Encoder string `json:"encoder"`
// Hardware is the encoder implementation: the CPU (empty) or NVENC.
Hardware Hardware `json:"hardware,omitempty"`
// DefaultPreset favours speed: the ladder is estimated from many encodes.
DefaultPreset string `json:"-"`
// MinCRF and MaxCRF bound the constant-quality scale.
MinCRF float64 `json:"-"`
MaxCRF float64 `json:"-"`
// ProbeCRFs are the constant-quality values probed per resolution, from
// high to low quality; together they span VMAF ~97 to ~40 at the right
// resolution for most content.
ProbeCRFs []float64 `json:"-"`
// CRFStep is the granularity of the constant-quality scale.
CRFStep float64 `json:"-"`
// MaxRate is the highest VBV rate the encoder accepts (bits/s, 0 for no
// limit): SVT-AV1 refuses maxrate above 100 Mb/s, which the 2× cap of a
// top rung of grainy content can exceed.
MaxRate int64 `json:"-"`
// contains filtered or unexported fields
}
Codec describes how to drive one encoder.
func LookupFor ¶
LookupFor returns the codec named name, encoded on hw. The codec is a copy the caller may change.
func (Codec) ChunkCommandLine ¶
ChunkCommandLine renders a copy-pasteable shell script encoding src chunk by chunk into dst (see EncodeChunks), then removing the chunk files.
func (Codec) CommandLine ¶
CommandLine renders a copy-pasteable ffmpeg command for p. NVENC commands also decode the source on the GPU (see InputArgs).
func (Codec) InputArgs ¶
InputArgs are the input options of the commands rendered for the codec: NVENC commands decode the source with NVDEC too (frames are downloaded before the CPU scaler, so the encoder sees exactly what the ladder measured; ffmpeg falls back to software decoding for codecs NVDEC does not decode). Encodes run by the ladder read the raw digest and need no decoder.
func (Codec) QualityOption ¶
QualityOption is the ffmpeg option of the constant-quality value: -crf, or -cq for NVENC.
type CopyPart ¶ added in v1.2.0
type CopyPart struct {
Source string
// Origin is the presentation time of the source's first frame on its
// container's timeline (see ChunkSource.Origin).
Origin media.Duration
Segments []CopySegment
}
CopyPart is the part of a copy cut from one source.
type CopySegment ¶ added in v1.2.0
CopySegment is a run of frames of a source: Frames frames from the keyframe shown at Start (a time of the video, from its first frame), which last Duration on the timeline of the source.
type CopySpec ¶ added in v1.2.0
type CopySpec struct {
// Destination receives the segments, joined; its extension picks the
// container.
Destination string
// Codec is the codec of the sources (ffprobe's name), which picks how
// the segments are carried before they are joined.
Codec string
// Rate is the frame rate of the sources.
Rate media.Rational
// Parts are the sources, in the order of the file. They must share
// their codec, geometry and frame rate.
Parts []CopyPart
// Segments is the number of segments over the parts, for Progress,
// which is called with the count copied so far.
Segments int
Progress func(done int)
}
CopySpec describes a file made of segments of videos copied as they are, without re-encoding: whole GOPs, from a keyframe on.
type DigestPart ¶ added in v1.1.0
DigestPart is the part of a digest cut from one source: its segments, times of that source's video seeked at its Origin.
type DigestSpec ¶
type DigestSpec struct {
// Source is the file the segments are cut from; Destination receives
// the digest.
Source, Destination string
Segments []media.Interval
// Rate is the source frame rate, restored on the concatenated timeline.
Rate media.Rational
// Origin is the presentation time of the source's first frame on its
// container's timeline (see ChunkSource.Origin): the segments are
// times of the video, from its first frame, and are seeked at Origin
// plus their start.
Origin media.Duration
// BitDepth is 8 or 10.
BitDepth int
// Lossless keeps the digest compact (FFV1); otherwise it is raw video in
// a NUT container, which costs nothing to decode for the many encodes
// and measurements that read it.
Lossless bool
// Parts, when set, cut the digest from several sources, one after the
// other, in place of Source, Origin and Segments: the digest of a
// program. The sources must share their geometry, frame rate and pixel
// format, which the concatenation does not convert.
Parts []DigestPart
}
DigestSpec describes a digest: segments of a source (or of several, see Parts) concatenated at the source resolution in 4:2:0.
type FFmpeg ¶
type FFmpeg struct {
// contains filtered or unexported fields
}
FFmpeg encodes with the ffmpeg binary.
func NewFFmpeg ¶
NewFFmpeg returns an FFmpeg running bin. It encodes, extracts digests, decodes and measures grain: consumers such as the ladder engine declare the narrow part they use.
func (*FFmpeg) Burn ¶
Burn writes the copy spec describes. The frames keep their timestamps (no frame is dropped or duplicated), so the script's times, taken from the source, land on the frames they describe.
func (*FFmpeg) CheckBurn ¶
func (f *FFmpeg) CheckBurn( ctx context.Context, encoder BurnEncoder, ) error
CheckBurn verifies that ffmpeg can burn subtitles with encoder: that it has the subtitles filter (libass), failing with ErrNoSubtitlesFilter otherwise, and, for a hardware encoder, that it encodes a few frames on this machine. BurnAuto is not tested: Burn falls back to x264 when the hardware fails.
func (*FFmpeg) Copy ¶ added in v1.2.0
Copy writes spec.Destination: every segment is copied from its source into a file of its own, then the files are joined, without re-encoding anything. H.264 and HEVC segments travel as MPEG-TS, which carries their parameter sets with every keyframe: sources encoded with other settings then decode once joined. The frames of the result are the sources' own.
func (*FFmpeg) DecodeRaw ¶
DecodeRaw decodes src to raw video in a NUT container at dst. withGrain false leaves AV1 film grain out (exported as side data instead of applied): the clean picture fidelity is scored against a denoised reference, since VMAF penalises synthesised grain for not matching the source's grain sample by sample.
func (*FFmpeg) Decodes ¶ added in v1.2.0
Decodes decodes every frame of the video of path and returns ErrDecode, with what ffmpeg reported, when a frame does not decode: ffmpeg is asked to stop at the first error rather than conceal it.
func (*FFmpeg) Digest ¶
func (f *FFmpeg) Digest( ctx context.Context, spec DigestSpec, ) error
Digest writes the digest spec describes.
func (*FFmpeg) EncodeChunks ¶
func (f *FFmpeg) EncodeChunks( ctx context.Context, codec Codec, src ChunkSource, dst string, chunks []Chunk, p Params, ) error
EncodeChunks encodes src chunk by chunk, each with its own CRF and the other settings of p, and joins the chunks into dst.
func (*FFmpeg) EncodeRendition ¶
EncodeRendition writes the rendition spec describes. A rendition is a long encode: it is watched for stalls like every encode, and reports its progress in frames.
func (*FFmpeg) Noise ¶
func (f *FFmpeg) Noise( ctx context.Context, path string, width, height, step int, ) (grain.Stats, error)
Noise measures the grain of path (frames of width×height), on grain.SampleFrames frames taken every step frames, decoded as they would be shown (AV1 film grain applied): ffmpeg decodes and scales, the pure estimator of package grain measures.
type Feature ¶
type Feature int
Feature is an encoder capability callers such as the ladder engine depend on: they ask the codec (Codec.Supports) instead of guessing from its hardware or encoder name.
const ( // FeatureFilmGrain is film grain synthesis (Params.FilmGrain): the // encoder denoises its input, codes the clean picture and signals grain // parameters the decoder adds back. SVT-AV1 only: av1_nvenc has none // reachable from ffmpeg. FeatureFilmGrain Feature = iota + 1 // FeatureChunkJoin is chunked encoding (FFmpeg.EncodeChunks): chunks // encoded separately and joined without re-encoding decode exactly as // the separate chunks. Verified for x264, x265 and SVT-AV1 (see Chunk). FeatureChunkJoin )
Encoder features.
type Hardware ¶
type Hardware string
Hardware selects the implementation of a codec's encoder.
const ( // HardwareCPU encodes with x264, x265 and SVT-AV1 (the zero value). HardwareCPU Hardware = "" // HardwareNVENC encodes with NVIDIA's hardware encoders (h264_nvenc, // hevc_nvenc, av1_nvenc). AV1 needs an Ada Lovelace or newer GPU. HardwareNVENC Hardware = "nvenc" )
Encoder implementations.
func ParseHardware ¶
ParseHardware reads an encoder implementation: cpu (or empty) or nvenc.
type Option ¶
type Option func(*FFmpeg)
Option configures an FFmpeg.
func WithLogger ¶
WithLogger logs to logger the fallbacks of automatic choices (a hardware encoder that does not work on this machine).
func WithStallTimeout ¶
WithStallTimeout sets how long an encode may go without its output growing before it is stopped and tried once more (default 5 minutes).
type Params ¶
type Params struct {
Width, Height int
CRF float64
Preset string
// GOP is the keyframe interval in frames (fixed, no scene-cut keyframes,
// as ABR segmenting requires). 0 lets the encoder decide.
GOP int
// MaxRate and BufSize (bits/s, bits) cap the bitrate when set.
MaxRate int64
BufSize int64
// BitDepth is 8 (default) or 10 (Main10 / 10-bit profiles).
BitDepth int
// FilmGrain is the SVT-AV1 film grain synthesis level (1–50; 0 off,
// ignored by the other encoders).
FilmGrain int
// Signal is the colour signal the encode carries (HDR sources); the
// zero value leaves it to the input frames.
Signal Signal
// contains filtered or unexported fields
}
Params are the settings of one encode.
type RenditionSpec ¶
type RenditionSpec struct {
// Source is the title; its Rate and Origin place the chunks.
Source ChunkSource
Destination string
Params Params
// Chunks, when set, are the chunks of a per-shot rendition covering
// the whole title.
Chunks []Chunk
// Progress, when set, is called with the number of frames written so
// far, about twice a second.
Progress func(frames int)
}
RenditionSpec describes a rendition of a title: the whole title encoded with Params, or chunk by chunk with the CRFs of Chunks (a per-shot rendition).
type Signal ¶
type Signal struct {
Color media.Color `json:"color"`
Mastering *media.MasteringDisplay `json:"masteringDisplay,omitempty"`
ContentLight *media.ContentLightLevel `json:"contentLightLevel,omitempty"`
}
Signal is the colour signal an encode carries: its colour description, written in the bitstream (VUI, AV1 sequence header), and for HDR10 the static metadata of SMPTE ST 2086 and CTA-861.3 (SEI, AV1 metadata OBUs). The zero value carries nothing: the encoder writes whatever its input frames say, which is how SDR ladders have always been encoded.
func SignalOf ¶
func SignalOf( v media.VideoStream, ) Signal
SignalOf is the signal of an HDR (PQ or HLG) video stream, to carry on its encodes, and the zero Signal for SDR ones. Unknown content light levels (0, 0) are left out.