mirror of
https://github.com/storytold/effectcraft.git
synced 2026-10-27 03:28:22 -06:00
Merge main into M13.4 (codec completion): HEVC/AV1 on the export pipeline (Cx), one key-frame interval for all movie codecs
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -27,6 +27,10 @@ pub struct ExportJob<'a> {
|
||||
pub accel: Option<&'a dyn effectcraft_render::Accelerator>,
|
||||
/// Resolved output path (templates expanded except the `#` frame-number run).
|
||||
pub path: &'a str,
|
||||
/// Free-space hook (Use Storage Overflow).
|
||||
pub storage: Option<&'a dyn effectcraft_project::render_queue::StorageQuota>,
|
||||
/// "#n Comp Name", for the render log.
|
||||
pub label: String,
|
||||
/// Settings ▸ General ▸ Switches Affect Nested Comps.
|
||||
pub nested_switches: bool,
|
||||
}
|
||||
@@ -41,6 +45,12 @@ pub struct ExportResult {
|
||||
pub bytes: u64,
|
||||
pub seconds: f64,
|
||||
pub audio: bool,
|
||||
/// The render log written next to the output, if any.
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub log: Option<String>,
|
||||
/// Files that went to storage overflow folders.
|
||||
#[serde(skip_serializing_if = "Vec::is_empty")]
|
||||
pub overflow: Vec<String>,
|
||||
}
|
||||
|
||||
/// Encodes render queue items (implemented by the export layer).
|
||||
@@ -129,6 +139,7 @@ struct Work {
|
||||
expr: Option<Arc<dyn ExprHost>>,
|
||||
accel: Option<Arc<dyn effectcraft_render::Accelerator>>,
|
||||
exporter: Arc<dyn Exporter>,
|
||||
storage: Option<Arc<dyn effectcraft_project::render_queue::StorageQuota>>,
|
||||
/// Per queue item: one (item with that output module, resolved path) per output module
|
||||
/// (and per segment, see [`Session::segments`]).
|
||||
items: Vec<Vec<(RenderQueueItem, String)>>,
|
||||
@@ -199,6 +210,7 @@ pub(crate) fn run_items(
|
||||
expr: s.expr.clone(),
|
||||
accel: s.accel.clone(),
|
||||
exporter,
|
||||
storage: s.storage_quota.clone(),
|
||||
items,
|
||||
nested_switches: s.prefs.general.switches_affect_nested_comps,
|
||||
};
|
||||
@@ -232,6 +244,8 @@ fn run_work(w: Work, shared: &JobShared, notify: &mut dyn FnMut(&JobShared)) {
|
||||
// first module's file is the item's output.
|
||||
let mut r: Result<ExportResult, String> = Err("no output module".into());
|
||||
for (mi, (mitem, path)) in modules.iter().enumerate() {
|
||||
let name = w.project.item(mitem.comp).map(|i| i.name.clone()).unwrap_or_default();
|
||||
let index = w.project.render_queue.iter().position(|i| i.id == mitem.id).map_or(0, |i| i + 1);
|
||||
let job = ExportJob {
|
||||
project: &w.project,
|
||||
footage: w.footage.as_ref(),
|
||||
@@ -239,6 +253,8 @@ fn run_work(w: Work, shared: &JobShared, notify: &mut dyn FnMut(&JobShared)) {
|
||||
accel: w.accel.as_deref(),
|
||||
item: mitem,
|
||||
path,
|
||||
storage: w.storage.as_deref(),
|
||||
label: format!("#{index} {name} (output module {})", mi + 1),
|
||||
nested_switches: w.nested_switches,
|
||||
};
|
||||
let rr = w.exporter.export(&job, &mut |done, total| {
|
||||
@@ -301,8 +317,7 @@ impl Session {
|
||||
if tpl.is_empty() {
|
||||
return None;
|
||||
}
|
||||
let (w, h) = item.settings.output_size(comp);
|
||||
let (w, h) = item.output.format.coded_size(w, h);
|
||||
let (w, h) = item.output.output_size(comp, &item.settings);
|
||||
let rate = item.settings.rate(comp);
|
||||
let n = item.settings.frame_count(comp) as i64;
|
||||
let f0 = item.settings.first_frame(comp);
|
||||
@@ -453,6 +468,7 @@ impl Session {
|
||||
expr: self.expr.clone(),
|
||||
accel: self.accel.clone(),
|
||||
exporter,
|
||||
storage: self.storage_quota.clone(),
|
||||
items,
|
||||
nested_switches: self.prefs.general.switches_affect_nested_comps,
|
||||
};
|
||||
@@ -552,6 +568,10 @@ impl Session {
|
||||
} else {
|
||||
format!("Rendered {} item(s) in {:.1} s", st.items_total, st.elapsed)
|
||||
};
|
||||
if self.project.render_prefs.notify {
|
||||
// Notify: the frontend plays a sound and shows a system notification.
|
||||
self.events.push(Event::Frontend { command: "renderQueue.notify".into(), params: serde_json::json!({"message": msg, "error": failed > 0}) });
|
||||
}
|
||||
self.events.push(Event::Toast { message: msg, error: failed > 0 });
|
||||
}
|
||||
for (id, path) in post {
|
||||
|
||||
Reference in New Issue
Block a user