You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Found by research after #637 shipped (PR #644). #644's behaviour is correct for the default case and arguably wrong for an explicit request; the blocker is that rdlp cannot tell them apart.
What upstream actually does
Verified from source, not paraphrase:
FFmpegVideoConvertorPP._options calls stream_copy_opts(False) — -c copy is never emitted. yt-dlp's recode verb has no copy mode at all; it always re-encodes when the extension differs.
FFmpegVideoRemuxerPP._options is stream_copy_opts() (copy=True) with no compatibility check; when ffmpeg rejects the copy, real_run_ffmpeg raises FFmpegPostProcessorError with ffmpeg's own last stderr line. The README is explicit: "If the target container does not support the video/audio codec, remuxing will fail."
ffmpeg never auto-falls back from -c copy to encoding.
So the two verbs are deliberately separated: copy-or-fail lives under remux, always-re-encode lives under recode, with no cross-contamination. Neither tool has a "copy, and quietly substitute an encoder if that doesn't work" mode — which is what rdlp does today.
RecodeAudioMode::Copy is #[default] (crates/rdlp-types/src/recode_audio_mode.rs) and PostProcess::recode_audio is a non-optionalRecodeAudioMode (postprocess.rs:174). By the time RecodeStage sees it, these are the same value:
the user typed --recode-audio=copy — an explicit demand
the user typed nothing — rdlp's own optimisation ("copy the audio if you can")
The information exists at the CLI boundary (Args::recode_audio is Option<String>) and is discarded during merge.
Consequence: for a container that provably cannot carry the codec (webm/mpg/ogg + aac), #644 re-encodes to the container's default and warns. Right for the default; wrong for the explicit request, where yt-dlp's contract says fail.
Hard-failing unconditionally is not the fix — it would break the default configuration, since --recode-video=webm with no audio flag would start erroring on any AAC source.
Found by research after #637 shipped (PR #644). #644's behaviour is correct for the default case and arguably wrong for an explicit request; the blocker is that rdlp cannot tell them apart.
What upstream actually does
Verified from source, not paraphrase:
FFmpegVideoConvertorPP._optionscallsstream_copy_opts(False)—-c copyis never emitted. yt-dlp's recode verb has no copy mode at all; it always re-encodes when the extension differs.FFmpegVideoRemuxerPP._optionsisstream_copy_opts()(copy=True) with no compatibility check; when ffmpeg rejects the copy,real_run_ffmpegraisesFFmpegPostProcessorErrorwith ffmpeg's own last stderr line. The README is explicit: "If the target container does not support the video/audio codec, remuxing will fail."-c copyto encoding.So the two verbs are deliberately separated: copy-or-fail lives under remux, always-re-encode lives under recode, with no cross-contamination. Neither tool has a "copy, and quietly substitute an encoder if that doesn't work" mode — which is what rdlp does today.
Source: https://github.com/yt-dlp/yt-dlp/blob/master/yt_dlp/postprocessor/ffmpeg.py, https://github.com/yt-dlp/yt-dlp/blob/master/README.md
The problem
RecodeAudioMode::Copyis#[default](crates/rdlp-types/src/recode_audio_mode.rs) andPostProcess::recode_audiois a non-optionalRecodeAudioMode(postprocess.rs:174). By the timeRecodeStagesees it, these are the same value:--recode-audio=copy— an explicit demandThe information exists at the CLI boundary (
Args::recode_audioisOption<String>) and is discarded during merge.Consequence: for a container that provably cannot carry the codec (webm/mpg/ogg + aac), #644 re-encodes to the container's default and warns. Right for the default; wrong for the explicit request, where yt-dlp's contract says fail.
Hard-failing unconditionally is not the fix — it would break the default configuration, since
--recode-video=webmwith no audio flag would start erroring on any AAC source.Proposed
Preserve the distinction, then branch on it:
PostProcess::recode_audio: Option<RecodeAudioMode>—None= "not specified", matching theOption-as-inherit convention the desktop overlay already uses (see Desktop: should settings.json materialise defaults and be authoritative over config.toml? #610's verdict; do NOT materialise the default into settings.json).warn!(today's behaviour, matches yt-dlp recode).copy+ copy impossible → refuse, naming the container/codec pair and suggesting--recode-audio=autoor a different container.Touches CLI merge, the desktop IPC contract, and
config.tomlparity (#540/#583 are the precedent for that kind of change).Acceptance
--recode-audio=copyinto a container that cannot carry the source codec refuses, naming both.RecodeAudioMode::Copy.config.toml/ IPC round-trip unchanged for an unspecified value.Refs #637, #644