mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-27 11:37:02 -06:00
Render Queue: Output To an .mp4 file keeps an HEVC or AV1 module (#179)
apply_output switched the format whenever the Output To extension mapped to a different format, and `.mp4` maps to H.264 only, so renderQueue.setOutput with an .mp4 path (even the item's own default name) turned an HEVC or AV1 module into H.264 and the render wrote an H.264 stream. The extension now changes the format only when the current format doesn't write it (OutputFormat::extension): HEVC, AV1 and H.264 all write .mp4, so they stay; `.mov` on H.264 still picks ProRes and `.mp4` on ProRes still picks H.264. Test: output_to_keeps_a_format_that_writes_the_extension. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
5d2083b64c
commit
247187872d
@@ -360,7 +360,8 @@ fn apply_output(om: &mut OutputModule, templates: &RenderTemplates, roi: Option<
|
||||
}
|
||||
if let Some(o) = str_p(p, "output").or(str_p(p, "path")) {
|
||||
om.output = o.to_string();
|
||||
if let Some(f) = OutputFormat::from_path(o).filter(|f| *f != om.format && !o.contains("[fileExtension]")) {
|
||||
// Only an extension the format doesn't write changes it: `.mp4` is H.264's, HEVC's and AV1's.
|
||||
if let Some(f) = OutputFormat::from_path(o).filter(|f| f.extension() != om.format.extension() && !o.contains("[fileExtension]")) {
|
||||
if p.get("format").is_some() {
|
||||
// An explicit format wins and the extension follows it, as choosing a format in
|
||||
// the Output Module renames Output To (#154: `--format hevc --out x.mp4`).
|
||||
|
||||
@@ -83,6 +83,33 @@ fn an_explicit_format_wins_over_the_output_extension() {
|
||||
assert_eq!((om.format, om.output.as_str()), (OutputFormat::PngSequence, "/out/still.png"));
|
||||
}
|
||||
|
||||
/// Output To only changes the format when the format can't write the new extension: HEVC and AV1
|
||||
/// write `.mp4` too, so they stay (#179). Other extensions still pick a file type.
|
||||
#[test]
|
||||
fn output_to_keeps_a_format_that_writes_the_extension() {
|
||||
let mut s = session();
|
||||
let cases = [
|
||||
("hevc", "/out/x.mp4", OutputFormat::Hevc, "/out/x.mp4"),
|
||||
("av1", "/out/x.mp4", OutputFormat::Av1, "/out/x.mp4"),
|
||||
("h264", "/out/x.mov", OutputFormat::ProRes, "/out/x.mov"),
|
||||
("prores", "/out/x.mp4", OutputFormat::H264, "/out/x.mp4"),
|
||||
("h264", "/out/x.mp4", OutputFormat::H264, "/out/x.mp4"),
|
||||
];
|
||||
for (format, out, want, path) in cases {
|
||||
let a = s.execute("renderQueue.add", json!({"format": format})).unwrap();
|
||||
let r = s.execute("renderQueue.setOutput", json!({"item": a["item"], "path": out})).unwrap();
|
||||
let om = &s.project.render_queue.last().unwrap().output;
|
||||
assert_eq!((om.format, om.output.as_str()), (want, path), "{format} → {out}");
|
||||
if OutputFormat::from_name(format) == Some(want) {
|
||||
assert_eq!(r["outputModuleSummary"], a["outputModuleSummary"], "{format} → {out}: the module is unchanged");
|
||||
}
|
||||
}
|
||||
// The module's own default name (HEVC resolves to `Main.mp4`) changes nothing either.
|
||||
let a = s.execute("renderQueue.add", json!({"format": "hevc"})).unwrap();
|
||||
let r = s.execute("renderQueue.setOutput", json!({"item": a["item"], "path": a["outputPath"]})).unwrap();
|
||||
assert_eq!((&r["output"]["format"], &r["outputModuleSummary"]), (&json!("Hevc"), &a["outputModuleSummary"]), "{r}");
|
||||
}
|
||||
|
||||
/// A `comp` that names no composition says so, rather than "no active composition" (#155).
|
||||
#[test]
|
||||
fn an_unknown_comp_is_named_in_the_error() {
|
||||
|
||||
Reference in New Issue
Block a user