Fix reel concat: force -f mp4 for the .tmp output path
The concat stage wrote to <key>.mp4.tmp (for an atomic publish-rename), but ffmpeg infers the muxer from the output extension and can't map .tmp to a format — "Unable to choose an output format". Force the mp4 muxer explicitly so the temp extension is irrelevant. Segment render, NVENC, TTS, and scripting were already working end-to-end; this was the only failure, at the final join. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+14
-3
@@ -159,7 +159,9 @@ pub fn build_segment_args(
|
|||||||
|
|
||||||
/// Build the concat-demuxer args that join rendered segments losslessly.
|
/// Build the concat-demuxer args that join rendered segments losslessly.
|
||||||
/// `+faststart` moves the moov atom up front so the reel streams immediately
|
/// `+faststart` moves the moov atom up front so the reel streams immediately
|
||||||
/// on the mobile client.
|
/// on the mobile client. The output muxer is forced with `-f mp4` because we
|
||||||
|
/// write to a `.tmp` path (atomic publish) whose extension ffmpeg can't map to
|
||||||
|
/// a format on its own.
|
||||||
pub fn build_concat_args(list_path: &str, out_path: &str) -> Vec<String> {
|
pub fn build_concat_args(list_path: &str, out_path: &str) -> Vec<String> {
|
||||||
[
|
[
|
||||||
"-y",
|
"-y",
|
||||||
@@ -173,6 +175,8 @@ pub fn build_concat_args(list_path: &str, out_path: &str) -> Vec<String> {
|
|||||||
"copy",
|
"copy",
|
||||||
"-movflags",
|
"-movflags",
|
||||||
"+faststart",
|
"+faststart",
|
||||||
|
"-f",
|
||||||
|
"mp4",
|
||||||
out_path,
|
out_path,
|
||||||
]
|
]
|
||||||
.iter()
|
.iter()
|
||||||
@@ -317,12 +321,19 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn concat_args_stream_copy_with_faststart() {
|
fn concat_args_stream_copy_with_faststart_and_forced_muxer() {
|
||||||
let args = build_concat_args("/tmp/list.txt", "/out.mp4");
|
// Output goes to a .tmp path, so the muxer must be forced — ffmpeg
|
||||||
|
// can't infer mp4 from the extension (the bug this guards against).
|
||||||
|
let args = build_concat_args("/tmp/list.txt", "/out.mp4.tmp");
|
||||||
let joined = args.join(" ");
|
let joined = args.join(" ");
|
||||||
assert!(joined.contains("-f concat -safe 0 -i /tmp/list.txt"));
|
assert!(joined.contains("-f concat -safe 0 -i /tmp/list.txt"));
|
||||||
assert!(joined.contains("-c copy"));
|
assert!(joined.contains("-c copy"));
|
||||||
assert!(joined.contains("+faststart"));
|
assert!(joined.contains("+faststart"));
|
||||||
|
assert!(joined.contains("-f mp4"));
|
||||||
|
// The forced muxer must come before the output path.
|
||||||
|
let f_mp4 = args.windows(2).position(|w| w == ["-f", "mp4"]).unwrap();
|
||||||
|
let out = args.iter().position(|a| a == "/out.mp4.tmp").unwrap();
|
||||||
|
assert!(f_mp4 < out);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user