From 791e6bb5ebff409e5d8196db43fa87f25e836056 Mon Sep 17 00:00:00 2001 From: Kushagra Kumar Date: Mon, 19 Oct 2026 01:59:48 +0530 Subject: [PATCH 1/6] fix(engine): preserve alpha channel when saving still PNG frames Exporting still frames via comp.saveFrameAs previously flattened the rendered frame against the composition background color, stripping the alpha channel. Single still frames queued in the Render Queue also defaulted to an RGB-only PNG sequence output module. Preserve straight alpha by default in comp.saveFrameAs (while honoring transparent: false if requested), and set TemplateSlot::Still to default to 'PNG Sequence with Alpha'. Fixes #1815 --- crates/engine/src/commands/comp_more.rs | 2 +- crates/engine/src/tests_frame_export.rs | 36 +++++++++++++++++++++++++ crates/project/src/render_templates.rs | 2 +- 3 files changed, 38 insertions(+), 2 deletions(-) diff --git a/crates/engine/src/commands/comp_more.rs b/crates/engine/src/commands/comp_more.rs index d6de320ec..96aa29a9a 100644 --- a/crates/engine/src/commands/comp_more.rs +++ b/crates/engine/src/commands/comp_more.rs @@ -117,7 +117,7 @@ fn save_frame(s: &mut Session, p: &Value) -> Result { let scale = f_p(p, "scale").unwrap_or(1.0).clamp(0.01, 4.0); let bg = comp.background; let img = s.render(cid, t, effectcraft_render::RenderOpts { scale, backend: effectcraft_render::Backend::Auto, ..Default::default() }); - let rgba = img.to_rgba8_over(bg); + let rgba = if p.get("transparent").and_then(Value::as_bool) == Some(false) { img.to_rgba8_over(bg) } else { img.to_rgba8() }; let png = encode_png(&rgba, img.width, img.height).map_err(|e| EngineError::Other(format!("PNG encoding failed: {e}")))?; s.services.write_file(&path, &png).map_err(|e| EngineError::Other(format!("cannot write {path}: {e}")))?; s.toast(format!("Saved frame to {path}")); diff --git a/crates/engine/src/tests_frame_export.rs b/crates/engine/src/tests_frame_export.rs index a45c5d444..2aca8ce36 100644 --- a/crates/engine/src/tests_frame_export.rs +++ b/crates/engine/src/tests_frame_export.rs @@ -164,3 +164,39 @@ fn copy_frame_hands_the_rendered_frame_to_the_frontend() { assert!(Session::default().execute("comp.copyFrame", json!({})).is_err()); assert!(crate::menus::entries().iter().any(|(path, e)| e.command == "comp.copyFrame" && path.first().map(String::as_str) == Some("Composition"))); } + +#[test] +fn save_frame_as_png_preserves_alpha_channel() { + let mut s = Session::default(); + s.execute("comp.new", json!({"name": "AlphaComp", "width": 32, "height": 32, "frameRate": 24, "duration": 1})).unwrap(); + let red = s.execute("layer.newSolid", json!({"name": "Red", "color": "#ff0000", "width": 16, "height": 16})).unwrap()["layer"].as_u64().unwrap(); + s.execute("prop.set", json!({"layer": red, "path": "transform/position", "value": [8, 8, 0]})).unwrap(); + let dir = out_dir("frame-png-alpha"); + let path = dir.join("alpha.png").to_string_lossy().to_string(); + + s.execute("comp.saveFrameAs", json!({"path": path})).unwrap(); + let img = image::load_from_memory(&std::fs::read(&path).unwrap()).unwrap().to_rgba8(); + assert_eq!((img.width(), img.height()), (32, 32)); + let solid_px = img.get_pixel(8, 8); + assert_eq!(solid_px[3], 255, "solid region must be opaque: {solid_px:?}"); + assert_eq!(solid_px[0], 255); + let empty_px = img.get_pixel(24, 24); + assert_eq!(empty_px[3], 0, "outside solid region must have alpha 0: {empty_px:?}"); + + let flat_path = dir.join("flat.png").to_string_lossy().to_string(); + s.execute("comp.saveFrameAs", json!({"path": flat_path, "transparent": false})).unwrap(); + let flat_img = image::load_from_memory(&std::fs::read(&flat_path).unwrap()).unwrap().to_rgba8(); + let flat_empty_px = flat_img.get_pixel(24, 24); + assert_eq!(flat_empty_px[3], 255, "transparent: false must composite over background: {flat_empty_px:?}"); +} + +#[test] +fn save_frame_as_defaults_to_png_sequence_with_alpha() { + let mut s = Session::default(); + s.execute("comp.new", json!({"name": "Comp", "width": 32, "height": 32, "frameRate": 24, "duration": 1})).unwrap(); + let r = s.execute("comp.saveFrameAs", json!({"queue": true})).unwrap(); + assert_eq!(r["queued"], true); + let it = s.project.render_queue.last().unwrap(); + assert_eq!(it.output.name, "PNG Sequence with Alpha"); + assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgba); +} diff --git a/crates/project/src/render_templates.rs b/crates/project/src/render_templates.rs index cf52b000e..8de342f4c 100644 --- a/crates/project/src/render_templates.rs +++ b/crates/project/src/render_templates.rs @@ -88,7 +88,7 @@ impl Default for TemplateDefaults { ]), output_modules: s(&[ (Movie, "H.264 - Match Render Settings - 15 Mbps"), - (Still, "PNG Sequence"), + (Still, "PNG Sequence with Alpha"), (PreRender, "Lossless with Alpha"), (MovieProxy, "Lossless with Alpha"), (StillProxy, "PNG Sequence with Alpha"), From f7922a9fbaaeb43ee2729b5608a821450acc272f Mon Sep 17 00:00:00 2001 From: Kushagra Kumar Date: Mon, 19 Oct 2026 02:11:05 +0530 Subject: [PATCH 2/6] test(engine): add undo and redo assertions for queued still frame export --- crates/engine/src/tests_frame_export.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/crates/engine/src/tests_frame_export.rs b/crates/engine/src/tests_frame_export.rs index 2aca8ce36..d56c941ae 100644 --- a/crates/engine/src/tests_frame_export.rs +++ b/crates/engine/src/tests_frame_export.rs @@ -199,4 +199,10 @@ fn save_frame_as_defaults_to_png_sequence_with_alpha() { let it = s.project.render_queue.last().unwrap(); assert_eq!(it.output.name, "PNG Sequence with Alpha"); assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgba); + s.execute("edit.undo", json!({})).unwrap(); + assert!(s.project.render_queue.is_empty()); + s.execute("edit.redo", json!({})).unwrap(); + let it = s.project.render_queue.last().unwrap(); + assert_eq!(it.output.name, "PNG Sequence with Alpha"); + assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgba); } From 77e2cf05542fdafed43932481ef203cb55ad46fc Mon Sep 17 00:00:00 2001 From: Kushagra Kumar Date: Sun, 25 Oct 2026 18:44:35 +0530 Subject: [PATCH 3/6] fix(engine): expose transparent param in comp.saveFrameAs schema and test execute_checked --- crates/engine/src/commands/comp_more.rs | 2 +- crates/engine/src/tests_frame_export.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/engine/src/commands/comp_more.rs b/crates/engine/src/commands/comp_more.rs index 96aa29a9a..b47d0ebf8 100644 --- a/crates/engine/src/commands/comp_more.rs +++ b/crates/engine/src/commands/comp_more.rs @@ -235,7 +235,7 @@ pub fn specs() -> Vec { "File...", ["Composition", "Save Frame As"], Some("Cmd+Alt+S"), - "{path (.png; with queue: an output path or template), time?, scale?, queue?: bool (add a Render Queue item from the Frame Default templates instead of writing now)}", + "{path (.png; with queue: an output path or template), time?, scale?, queue?: bool (add a Render Queue item from the Frame Default templates instead of writing now), transparent?: bool (default true)}", has_comp, save_frame ), diff --git a/crates/engine/src/tests_frame_export.rs b/crates/engine/src/tests_frame_export.rs index d56c941ae..a11f7c64c 100644 --- a/crates/engine/src/tests_frame_export.rs +++ b/crates/engine/src/tests_frame_export.rs @@ -184,7 +184,7 @@ fn save_frame_as_png_preserves_alpha_channel() { assert_eq!(empty_px[3], 0, "outside solid region must have alpha 0: {empty_px:?}"); let flat_path = dir.join("flat.png").to_string_lossy().to_string(); - s.execute("comp.saveFrameAs", json!({"path": flat_path, "transparent": false})).unwrap(); + s.execute_checked("comp.saveFrameAs", json!({"path": flat_path, "transparent": false})).unwrap(); let flat_img = image::load_from_memory(&std::fs::read(&flat_path).unwrap()).unwrap().to_rgba8(); let flat_empty_px = flat_img.get_pixel(24, 24); assert_eq!(flat_empty_px[3], 255, "transparent: false must composite over background: {flat_empty_px:?}"); From 5d253465473fb58e83aea46faf9f9a41cecb906e Mon Sep 17 00:00:00 2001 From: Kushagra Kumar Date: Sun, 25 Oct 2026 19:31:46 +0530 Subject: [PATCH 4/6] fix(engine): propagate transparency setting to queued frame saves --- crates/engine/src/commands/comp_more.rs | 17 +++++++++++++---- crates/engine/src/tests_frame_export.rs | 15 ++++++++++++++- 2 files changed, 27 insertions(+), 5 deletions(-) diff --git a/crates/engine/src/commands/comp_more.rs b/crates/engine/src/commands/comp_more.rs index b47d0ebf8..1014b1992 100644 --- a/crates/engine/src/commands/comp_more.rs +++ b/crates/engine/src/commands/comp_more.rs @@ -5,7 +5,7 @@ use effectcraft_project::Marker; use effectcraft_time::Tick; use serde_json::{Value, json}; -use super::{CommandSpec, always, bad, comp_id, f_p, has_comp, has_layers, layers_p, str_p}; +use super::{CommandSpec, always, b_p, bad, comp_id, f_p, has_comp, has_layers, layers_p, str_p}; use crate::prefs::CompPreset; use crate::{EngineError, Result, Session, cmd, query}; @@ -82,7 +82,7 @@ pub(crate) fn encode_png(rgba: &[u8], w: u32, h: u32) -> std::result::Result Result { - use effectcraft_project::render_queue::{RenderQueueItem, TimeSpan}; + use effectcraft_project::render_queue::{Channels, RenderQueueItem, TimeSpan}; use effectcraft_project::render_templates::TemplateSlot; let cid = comp_id(s, p)?; let comp = s.project.comp(cid).ok_or(EngineError::NoComp)?; @@ -91,6 +91,15 @@ fn queue_frame(s: &mut Session, p: &Value) -> Result { it.settings = s.project.render_templates.default_render_settings(TemplateSlot::Still); it.settings.time_span = TimeSpan::Custom { start: t, end: t + comp.frame_duration() }; it.output = s.project.render_templates.default_output_module(TemplateSlot::Still); + if let Some(transparent) = b_p(p, "transparent") { + if !transparent { + it.output.channels = Channels::Rgb; + } else if it.output.supports_alpha() { + it.output.channels = Channels::Rgba; + } else { + return Err(bad("comp.saveFrameAs", format!("{} doesn't support an alpha channel", it.output.format.label()))); + } + } if let Some(path) = str_p(p, "path") { it.output.output = path.to_string(); } else if !it.output.format.is_sequence() { @@ -107,7 +116,7 @@ fn queue_frame(s: &mut Session, p: &Value) -> Result { } fn save_frame(s: &mut Session, p: &Value) -> Result { - if p.get("queue").and_then(Value::as_bool) == Some(true) { + if b_p(p, "queue") == Some(true) { return queue_frame(s, p); } let path = str_p(p, "path").ok_or_else(|| bad("comp.saveFrameAs", "missing `path` (.png)"))?.to_string(); @@ -117,7 +126,7 @@ fn save_frame(s: &mut Session, p: &Value) -> Result { let scale = f_p(p, "scale").unwrap_or(1.0).clamp(0.01, 4.0); let bg = comp.background; let img = s.render(cid, t, effectcraft_render::RenderOpts { scale, backend: effectcraft_render::Backend::Auto, ..Default::default() }); - let rgba = if p.get("transparent").and_then(Value::as_bool) == Some(false) { img.to_rgba8_over(bg) } else { img.to_rgba8() }; + let rgba = if b_p(p, "transparent") == Some(false) { img.to_rgba8_over(bg) } else { img.to_rgba8() }; let png = encode_png(&rgba, img.width, img.height).map_err(|e| EngineError::Other(format!("PNG encoding failed: {e}")))?; s.services.write_file(&path, &png).map_err(|e| EngineError::Other(format!("cannot write {path}: {e}")))?; s.toast(format!("Saved frame to {path}")); diff --git a/crates/engine/src/tests_frame_export.rs b/crates/engine/src/tests_frame_export.rs index a11f7c64c..c6b0847ec 100644 --- a/crates/engine/src/tests_frame_export.rs +++ b/crates/engine/src/tests_frame_export.rs @@ -194,11 +194,24 @@ fn save_frame_as_png_preserves_alpha_channel() { fn save_frame_as_defaults_to_png_sequence_with_alpha() { let mut s = Session::default(); s.execute("comp.new", json!({"name": "Comp", "width": 32, "height": 32, "frameRate": 24, "duration": 1})).unwrap(); - let r = s.execute("comp.saveFrameAs", json!({"queue": true})).unwrap(); + let r = s.execute_checked("comp.saveFrameAs", json!({"queue": true})).unwrap(); assert_eq!(r["queued"], true); let it = s.project.render_queue.last().unwrap(); assert_eq!(it.output.name, "PNG Sequence with Alpha"); assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgba); + + // Queued save with transparent: false sets Channels::Rgb (composited over background). + s.execute_checked("comp.saveFrameAs", json!({"queue": true, "transparent": false})).unwrap(); + let it = s.project.render_queue.last().unwrap(); + assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgb); + + // Queued save with transparent: true preserves Channels::Rgba. + s.execute_checked("comp.saveFrameAs", json!({"queue": true, "transparent": true})).unwrap(); + let it = s.project.render_queue.last().unwrap(); + assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgba); + + s.execute("edit.undo", json!({})).unwrap(); + s.execute("edit.undo", json!({})).unwrap(); s.execute("edit.undo", json!({})).unwrap(); assert!(s.project.render_queue.is_empty()); s.execute("edit.redo", json!({})).unwrap(); From 59b564326e60afb5d8f21c780be54e5d2d4eafcb Mon Sep 17 00:00:00 2001 From: Kushagra Kumar Date: Sun, 25 Oct 2026 19:51:06 +0530 Subject: [PATCH 5/6] fix(engine): default transparent to true in queue_frame --- crates/engine/src/commands/comp_more.rs | 15 +++++++-------- crates/engine/src/tests_frame_export.rs | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 8 deletions(-) diff --git a/crates/engine/src/commands/comp_more.rs b/crates/engine/src/commands/comp_more.rs index 1014b1992..0a1f63cb4 100644 --- a/crates/engine/src/commands/comp_more.rs +++ b/crates/engine/src/commands/comp_more.rs @@ -91,14 +91,13 @@ fn queue_frame(s: &mut Session, p: &Value) -> Result { it.settings = s.project.render_templates.default_render_settings(TemplateSlot::Still); it.settings.time_span = TimeSpan::Custom { start: t, end: t + comp.frame_duration() }; it.output = s.project.render_templates.default_output_module(TemplateSlot::Still); - if let Some(transparent) = b_p(p, "transparent") { - if !transparent { - it.output.channels = Channels::Rgb; - } else if it.output.supports_alpha() { - it.output.channels = Channels::Rgba; - } else { - return Err(bad("comp.saveFrameAs", format!("{} doesn't support an alpha channel", it.output.format.label()))); - } + let transparent = b_p(p, "transparent").unwrap_or(true); + if !transparent { + it.output.channels = Channels::Rgb; + } else if it.output.supports_alpha() { + it.output.channels = Channels::Rgba; + } else { + return Err(bad("comp.saveFrameAs", format!("{} doesn't support an alpha channel", it.output.format.label()))); } if let Some(path) = str_p(p, "path") { it.output.output = path.to_string(); diff --git a/crates/engine/src/tests_frame_export.rs b/crates/engine/src/tests_frame_export.rs index c6b0847ec..d4273bc6c 100644 --- a/crates/engine/src/tests_frame_export.rs +++ b/crates/engine/src/tests_frame_export.rs @@ -219,3 +219,22 @@ fn save_frame_as_defaults_to_png_sequence_with_alpha() { assert_eq!(it.output.name, "PNG Sequence with Alpha"); assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgba); } + +#[test] +fn save_frame_as_defaults_to_transparent_even_with_rgb_frame_template() { + let mut s = Session::default(); + s.execute("comp.new", json!({"name": "Comp", "width": 32, "height": 32, "frameRate": 24, "duration": 1})).unwrap(); + + // Set Frame Default to an RGB output template ("PNG Sequence") + s.execute_checked("renderQueue.setTemplateDefault", json!({"kind": "outputModule", "slot": "still", "name": "PNG Sequence"})).unwrap(); + + // Omitting `transparent` must default to true and promote to Channels::Rgba + s.execute_checked("comp.saveFrameAs", json!({"queue": true})).unwrap(); + let it = s.project.render_queue.last().unwrap(); + assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgba); + + // Explicit `transparent: false` respects the request and stays Channels::Rgb + s.execute_checked("comp.saveFrameAs", json!({"queue": true, "transparent": false})).unwrap(); + let it = s.project.render_queue.last().unwrap(); + assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgb); +} From c31fad1b9008034e42ddd6f8979071dfe1f3c3f1 Mon Sep 17 00:00:00 2001 From: Kushagra Kumar Date: Thu, 29 Oct 2026 22:06:27 +0530 Subject: [PATCH 6/6] fix(engine): respect frame default template and force RGB only on transparent: false --- crates/engine/src/cmd/comp_more.rs | 7 +--- crates/engine/src/tests/frame_export.rs | 54 +++++++++++-------------- crates/project/src/render_templates.rs | 2 +- 3 files changed, 25 insertions(+), 38 deletions(-) diff --git a/crates/engine/src/cmd/comp_more.rs b/crates/engine/src/cmd/comp_more.rs index 0a1f63cb4..478dc8259 100644 --- a/crates/engine/src/cmd/comp_more.rs +++ b/crates/engine/src/cmd/comp_more.rs @@ -91,13 +91,8 @@ fn queue_frame(s: &mut Session, p: &Value) -> Result { it.settings = s.project.render_templates.default_render_settings(TemplateSlot::Still); it.settings.time_span = TimeSpan::Custom { start: t, end: t + comp.frame_duration() }; it.output = s.project.render_templates.default_output_module(TemplateSlot::Still); - let transparent = b_p(p, "transparent").unwrap_or(true); - if !transparent { + if b_p(p, "transparent") == Some(false) { it.output.channels = Channels::Rgb; - } else if it.output.supports_alpha() { - it.output.channels = Channels::Rgba; - } else { - return Err(bad("comp.saveFrameAs", format!("{} doesn't support an alpha channel", it.output.format.label()))); } if let Some(path) = str_p(p, "path") { it.output.output = path.to_string(); diff --git a/crates/engine/src/tests/frame_export.rs b/crates/engine/src/tests/frame_export.rs index d4273bc6c..a8dc938fb 100644 --- a/crates/engine/src/tests/frame_export.rs +++ b/crates/engine/src/tests/frame_export.rs @@ -191,50 +191,42 @@ fn save_frame_as_png_preserves_alpha_channel() { } #[test] -fn save_frame_as_defaults_to_png_sequence_with_alpha() { +fn save_frame_as_queued_respects_frame_default_template() { let mut s = Session::default(); s.execute("comp.new", json!({"name": "Comp", "width": 32, "height": 32, "frameRate": 24, "duration": 1})).unwrap(); + + // Default Still template is "PNG Sequence" (Channels::Rgb) let r = s.execute_checked("comp.saveFrameAs", json!({"queue": true})).unwrap(); assert_eq!(r["queued"], true); let it = s.project.render_queue.last().unwrap(); - assert_eq!(it.output.name, "PNG Sequence with Alpha"); - assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgba); - - // Queued save with transparent: false sets Channels::Rgb (composited over background). - s.execute_checked("comp.saveFrameAs", json!({"queue": true, "transparent": false})).unwrap(); - let it = s.project.render_queue.last().unwrap(); + assert_eq!(it.output.name, "PNG Sequence"); assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgb); - // Queued save with transparent: true preserves Channels::Rgba. - s.execute_checked("comp.saveFrameAs", json!({"queue": true, "transparent": true})).unwrap(); - let it = s.project.render_queue.last().unwrap(); - assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgba); - - s.execute("edit.undo", json!({})).unwrap(); - s.execute("edit.undo", json!({})).unwrap(); + // Test undo and redo of queuing a frame s.execute("edit.undo", json!({})).unwrap(); assert!(s.project.render_queue.is_empty()); s.execute("edit.redo", json!({})).unwrap(); let it = s.project.render_queue.last().unwrap(); - assert_eq!(it.output.name, "PNG Sequence with Alpha"); - assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgba); -} + assert_eq!(it.output.name, "PNG Sequence"); -#[test] -fn save_frame_as_defaults_to_transparent_even_with_rgb_frame_template() { - let mut s = Session::default(); - s.execute("comp.new", json!({"name": "Comp", "width": 32, "height": 32, "frameRate": 24, "duration": 1})).unwrap(); - - // Set Frame Default to an RGB output template ("PNG Sequence") - s.execute_checked("renderQueue.setTemplateDefault", json!({"kind": "outputModule", "slot": "still", "name": "PNG Sequence"})).unwrap(); - - // Omitting `transparent` must default to true and promote to Channels::Rgba - s.execute_checked("comp.saveFrameAs", json!({"queue": true})).unwrap(); - let it = s.project.render_queue.last().unwrap(); - assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgba); - - // Explicit `transparent: false` respects the request and stays Channels::Rgb + // Explicit transparent: false forces Channels::Rgb s.execute_checked("comp.saveFrameAs", json!({"queue": true, "transparent": false})).unwrap(); let it = s.project.render_queue.last().unwrap(); assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgb); + + // When Frame Default is set to an RGBA template, it is respected + s.execute_checked("renderQueue.setTemplateDefault", json!({"kind": "outputModule", "slot": "still", "name": "PNG Sequence with Alpha"})).unwrap(); + s.execute_checked("comp.saveFrameAs", json!({"queue": true})).unwrap(); + let it = s.project.render_queue.last().unwrap(); + assert_eq!(it.output.name, "PNG Sequence with Alpha"); + assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgba); + + // Passing transparent: false forces Channels::Rgb even with an RGBA template + s.execute_checked("comp.saveFrameAs", json!({"queue": true, "transparent": false})).unwrap(); + let it = s.project.render_queue.last().unwrap(); + assert_eq!(it.output.channels, effectcraft_project::render_queue::Channels::Rgb); + + // With JPEG Sequence as Frame Default (non-alpha format), queue succeeds without error + s.execute_checked("renderQueue.setTemplateDefault", json!({"kind": "outputModule", "slot": "still", "name": "JPEG Sequence"})).unwrap(); + assert!(s.execute_checked("comp.saveFrameAs", json!({"queue": true})).is_ok()); } diff --git a/crates/project/src/render_templates.rs b/crates/project/src/render_templates.rs index 8de342f4c..cf52b000e 100644 --- a/crates/project/src/render_templates.rs +++ b/crates/project/src/render_templates.rs @@ -88,7 +88,7 @@ impl Default for TemplateDefaults { ]), output_modules: s(&[ (Movie, "H.264 - Match Render Settings - 15 Mbps"), - (Still, "PNG Sequence with Alpha"), + (Still, "PNG Sequence"), (PreRender, "Lossless with Alpha"), (MovieProxy, "Lossless with Alpha"), (StillProxy, "PNG Sequence with Alpha"),