Skip to content

MediaEncoder

Output / mux: compose an output from one or more stream views, choosing per stream whether to re-encode or stream-copy, then write it to disk.

A MediaEncoder holds only references to the streams you map (which keep their Media alive) — no long-lived native memory. save() is stateless and re-runnable: it builds the output context, transcodes, and tears everything down within the call, so the same encoder can be saved to several paths.

addVideo(VideoStream $stream, VideoCodec $codec, ?int $crf = null, ?string $preset = null, ?int $bitrate = null): static

Section titled “addVideo(VideoStream $stream, VideoCodec $codec, ?int $crf = null, ?string $preset = null, ?int $bitrate = null): static”

Map a video stream into the output. $codec is a VideoCodec — e.g. VideoCodec::H264 to re-encode, or VideoCodec::Copy to remux without re-encoding. Chainable.

Optional quality controls (all ignored when $codec is Copy):

ArgumentTypeMeaning
$crf?intConstant Rate Factor — quality, lower = better. Encoder-specific range (e.g. 0–51 for H.264/H.265). With crf set and no bitrate, encoding is pure constant-quality.
$preset?stringEncoder speed/quality trade-off, e.g. "ultrafast""veryslow" for x264/x265.
$bitrate?intTarget video bitrate in bits/sec.

Throws EncodingException if the chosen encoder doesn’t support a given option (e.g. an unknown preset, or crf on an encoder without it).

addAudio(AudioStream $stream, AudioCodec $codec, ?int $bitrate = null): static

Section titled “addAudio(AudioStream $stream, AudioCodec $codec, ?int $bitrate = null): static”

Map an audio stream into the output. $codec is an AudioCodec. Optional $bitrate sets the target audio bitrate in bits/sec (ignored for Copy). Chainable.

Write the configured output to $path; the container is inferred from the extension.

  • Requires at least one mapping — video-only and audio-only are both valid.
  • Throws EncoderNotFoundException if a chosen encoder isn’t built into this FFmpeg.
  • Throws EncodingException on any other failure, carrying ->operation + ->avError.
use FFmpeg\{Media, MediaEncoder};
use FFmpeg\Codec\{VideoCodec, AudioCodec};
$media = Media::open('input.mov');
(new MediaEncoder())
->addVideo($media->videoStream(), VideoCodec::H264)
->addAudio($media->audioStream(), AudioCodec::Copy)
->save('output.mp4');

Remux only (no re-encode) into a different container

Section titled “Remux only (no re-encode) into a different container”
(new MediaEncoder())
->addVideo($media->videoStream(), VideoCodec::Copy)
->addAudio($media->audioStream(), AudioCodec::Copy)
->save('output.mkv');
(new MediaEncoder())
->addAudio($media->audioStream(), AudioCodec::AAC)
->save('audio.m4a');
use FFmpeg\Codec\{VideoCodec, AudioCodec};
(new MediaEncoder())
// near-visually-lossless H.264, fast encode
->addVideo($media->videoStream(), VideoCodec::H264, crf: 18, preset: 'veryfast')
// 128 kbps AAC
->addAudio($media->audioStream(), AudioCodec::AAC, bitrate: 128_000)
->save('output.mp4');
  • Output stream order is stable: video first, then audio.
  • Re-encoding picks a pixel/sample format the chosen encoder accepts and resamples / rescales as needed (sws for video, swr + a sample FIFO for audio).
  • Copy requires the target container to accept the source codec; otherwise re-encode.

Media · VideoCodec · AudioCodec

An Artisan Build project.

Built on FFmpeg — an independent binding, not affiliated with or endorsed by the FFmpeg project.

Proudly sponsored by Tighten.