writer

package
v1.9.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 6, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Encoder

type Encoder struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

Encoder is a standalone, muxer-agnostic collection of codec encoders keyed by caller-chosen stream ID. Unlike Writer, it never creates an AVStream or AVFormatContext, so each codec context here has no muxer-owned AVStream to free it — Encoder itself owns every context it opens and must free them in Close().

func NewEncoder

func NewEncoder(fn PacketFn) (*Encoder, error)

NewEncoder creates an empty Encoder that passes every packet it produces to fn. Use Add to register a codec for each stream ID before calling Encode.

func (*Encoder) Add

func (e *Encoder) Add(streamID int, p profile.Profile, flags ...ff.AVCodecFlag) error

Add opens a codec context for streamID from the given profile. Codec- specific options come from profile.Options(), applied the same way Writer applies Output.Opts to the format context. Any flags (e.g. AV_CODEC_FLAG_GLOBAL_HEADER, which muxers like mp4/mov require so the codec emits extradata instead of repeating headers in-band) are set on the codec context before it is opened.

func (*Encoder) Close

func (e *Encoder) Close() error

Close releases every codec context this Encoder owns.

func (*Encoder) Encode

func (e *Encoder) Encode(f frame.Frame) error

Encode sends f to the codec registered for f.Stream() and passes resulting packets to the Encoder's callback. Packets carry the codec's own timebase — rescale to a muxer's stream timebase downstream if needed.

f must be an *frame.AudioFrame or *frame.VideoFrame for a stream Added from an audio/video profile, or a *frame.SubtitleFrame for a stream Added from a subtitle profile - FFmpeg encodes subtitles via a completely separate, legacy API with no send/receive buffering.

func (*Encoder) Flush

func (e *Encoder) Flush(streamID int) error

Flush signals end-of-stream to the codec registered for streamID and passes any remaining buffered packets to the Encoder's callback. This is a no-op for a subtitle stream (subtitles use a legacy API with no buffering, so there is nothing to flush) and for a stream whose codec isn't actually an encoder (e.g. a StreamProfile fed to Add purely to copy a demuxed stream's parameters/extradata onto the muxed output for a remux - avcodec_send_frame is only valid against a real encoder context).

func (*Encoder) FrameSize

func (e *Encoder) FrameSize(streamID int) int

FrameSize returns the number of samples per frame the codec registered for streamID expects (audio only; 0 if the stream doesn't exist or the codec accepts variable frame sizes).

func (*Encoder) Par

func (e *Encoder) Par(streamID int) (*ff.AVCodecParameters, error)

Par returns codec parameters reflecting the opened codec context for streamID — unlike the profile originally passed to Add, this includes whatever the codec generated on open (e.g. OpusHead for libopus, AudioSpecificConfig for aac), which a muxer's AVStream needs. Caller must free the result with ff.AVCodec_parameters_free.

type Opt

type Opt func(o *opts) error

func WithMetadata

func WithMetadata(meta ...gomedia.Metadata) Opt

Append metadata to the output file, including artwork

func WithProfile

func WithProfile(stream int, profile profile.Profile) Opt

Append stream profile to the output file. If the stream index is 0, the next available stream index will be used.

type PacketFn

type PacketFn func(*ff.AVPacket) error

PacketFn is called for each packet an Encoder produces. Returning io.EOF stops encoding early without being treated as an error.

type Resampler

type Resampler struct {
	// contains filtered or unexported fields
}

resampler converts frames arriving for one stream into the exact format its codec was opened with, so Writer.Encode never hands Encoder.Encode a mismatched frame.

func NewResampler

func NewResampler(par *ff.AVCodecParameters, frameSize int, timebase ff.AVRational) (*Resampler, error)

NewResampler creates a resampler that converts audio or video frames into par's target format. For any other codec type (e.g. subtitle, data), it returns a passthrough Resampler. frameSize only applies to audio (see audioResampler); timebase only applies to video (see videoRescaler) - it's the fixed output timebase (typically 1/framerate) frames are counted out in, so switching source mid-stream can't hand the encoder a pts in the wrong timebase or one that jumps backwards relative to the previous source.

func (*Resampler) Close

func (r *Resampler) Close() error

func (*Resampler) Process

func (r *Resampler) Process(src frame.Frame, fn func(frame.Frame) error) error

Process converts src and calls fn for every resulting frame. Pass src==nil to flush - audio may have buffered samples still to emit; video and passthrough have nothing to flush and this is a no-op for them.

type Writer

type Writer struct {
	sync.Mutex

	*Encoder
	// contains filtered or unexported fields
}

Writer is a wrapper around an AVFormatContext that provides a higher-level interface for writing media files. It embeds an Encoder, giving it Add and FrameSize for free — one codec context per stream, opened alongside each stream's AVStream in open(). Encode and Flush are overridden (see below) to resample/rescale a frame into the exact format its stream's codec expects before handing it to the embedded Encoder.

func Create

func Create(url *url.URL, output *profile.Output, opts ...Opt) (*Writer, error)

Create a new writer with a URL and options

func NewWriter

func NewWriter(w io.Writer, output *profile.Output, opts ...Opt) (*Writer, error)

Create a new writer with an io.Writer and options

func (*Writer) Close

func (w *Writer) Close() error

Close a writer and release resources

func (*Writer) Encode

func (w *Writer) Encode(f frame.Frame) error

Encode converts f via its stream's resampler (built in open(), if the stream is audio/video) into the exact format its codec was opened with, then hands the result to the embedded Encoder. Frames for a stream with no registered resampler (subtitles) pass straight through.

func (*Writer) Flush

func (w *Writer) Flush(stream int) error

Flush drains stream's resampler (if any) of any samples not yet forming a full frame, then flushes the encoder. Resampler.Process(nil, ...) is documented as a no-op for video/passthrough, so this only does real work for audio. Safe to call more than once for the same stream - the encoder returns io.EOF for a stream already flushed, rather than an error.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL