otio: write importable OTIO/FCPXML (DaVinci Resolve rejects both)
CI / Build & test (Linux) (push) Successful in 23m59s
CI / Build & test (Windows) (push) Successful in 31m18s

- available_range declared a zero duration for every clip (the media
  was 'unusable', so Resolve invalidated all of them): it now covers
  the whole media - video clips in the probed frame rate, audio clips
  in the probed sample rate (no more hardcoded 48000/0).
- Gap ranges mixed time bases (a 24 fps block start, a 1.0 trailing
  duration): gaps now stay in the sequence's time base, the trailing
  pad in whole frames.
- Empty sequences (no clips) are skipped, so a lone edited sequence
  exports as a bare Timeline root instead of a SerializableCollection
  Resolve cannot read.
- FCPXML: an asset used on both video and audio tracks now declares
  hasVideo AND hasAudio (the first registration's track kind used to
  hide the other stream); asset durations recover with available_range.
This commit is contained in:
2026-09-10 16:55:12 +08:00
parent 71e41d2d82
commit 280118a342
4 changed files with 387 additions and 22 deletions
+9
View File
@@ -953,6 +953,15 @@ impl ResourceSet {
};
let src = external.target_url();
if self.asset_ids.contains_key(src) {
// Already registered from another track: union the
// stream flags so a file used on both a video and an
// audio track declares hasVideo AND hasAudio (the
// first registration's track kind must not hide the
// other stream from the importer).
if let Some(existing) = self.assets.iter_mut().find(|a| a.src == src) {
existing.has_video |= is_video;
existing.has_audio |= is_audio;
}
continue;
}
let (asset_format_id, asset_duration) = match external.available_range() {