This library is under heavy development!
This Swift Package extends OpenTimelineIO's Swift Bindings to provide functionality for Apple platforms.
The goal is to enable easy interoperability OpenTimelineIO and AVFoundation objects in a correct, lossless and useful manner to enable real world workflows.
Timeline
objects and introspect using the standard Swift bindings.AVComposition
AVVideoComposition
and AVAudioMix
objects from an OTIO Timeline
instance allowing for playback via AVPlayer
and export via AVExportSession
or AVAssetWriter
to Quicktime compatible file formats.AVMutableCompositions
into a OTIO Timeline
This library should be compatible with the following Apple platforms:
but to date has only been extensively tested on macOS
The app should register itself as a reader of OTIO files.
.otio
file which will launch the app, or control click with open as. To ensure the widest media support possible, please make sure to install Apple's Pro Video Formats package.
Thats it!
Assuming you have a basic AVPlayer
setup, this will let you import a .otio
file with basic jump cut editing.
See roadmap for transitions / effects.
do {
if
let timeline = try Timeline.fromJSON(url: url) as? Timeline,
let (composition, videoComposition, audioMix) = try await timeline.toAVCompositionRenderables()
{
let playerItem = AVPlayerItem(asset: composition)
playerItem.videoComposition = videoComposition
playerItem.audioMix = audioMix
self.player.replaceCurrentItem(with: playerItem)
}
}
catch
{
print(error)
}
Assuming you have succssfuly created an AVCompostion
- this will export a basic .otio
file without effects or transition metadata.
See roadmap for transitions / effects.
do {
let timeline = try compositon.toOTIOTimeline(named: toURL.lastPathComponent)
try timeline.toJSON(url: toURL)
}
catch
{
print(error)
}
RationalTime
to CoreMedia CMTime
TimeRange
to CoreMedia CMTimeRange
ExternalReference
to AVFoundation AVAsset
Timeline
to playable/exportable AVFoundation AVCompostion
AVVideoCompostion
and AVAudioMix
CMTime
to OpenTimelineIO RationalTime
CMTimeRange
to OpenTimelineIO TimeRange
AVCompositionTrackSegment
to OpenTimelineIO Clip
with an embedded OpenTimelineIO ExternalReference
which has url metadataAVCompositionTrack
to OpenTimelineIO Track
with each AVCompositionTrackSegment
converted to OpenTimelineIO Clip
associationsAVComposition
to OpenTimelineIO Timeline
with associated Tracks
convertedOTIO Formats | Status | Notes |
---|---|---|
OTIO | :white_check_mark: | |
OTIOD | :white_check_mark: | |
OTIOZ | :x: | Planned |
NLE | Import from NLE | Export to NLE |
---|---|---|
Davinci Resolve 18.6 | :white_check_mark: | :white_check_mark: |
Davinci Resolve 19 | :white_check_mark: | :white_check_mark: |
Sample Project | Import to AVFoundation | Export from AVFoundation |
---|---|---|
ALab Trailer | :white_check_mark: | :white_check_mark: |
AWS Picchu Edit | :white_check_mark: (Decompress .otioz zip file and open the bundled .otio file) | :white_check_mark: |
OTIO-OC-Examples | :white_check_mark: | :white_check_mark: |
Generally if Quicktime or Final Cut Pro X Can support it, it should just work.
Video Formats | Status | Notes |
---|---|---|
H.264 | :white_check_mark: | Native |
HEVC | :white_check_mark: | Native |
Apple ProRes | :white_check_mark: | Requires Apple Pro Video Formats for some variants |
Apple Intermediate Codec | :white_check_mark: | Requires Apple Pro Video Formats for some variants |
MXF wrapped Pro Res | :white_check_mark: | For developers: Requires MTRegisterProfessionalVideoWorkflowFormatReaders() and VTRegisterProfessionalVideoWorkflowVideoDecoders() to be enabled |
MXF Wrapped DNx | :white_check_mark: | Requires Apple Pro Video Formats for Avid DNxHD® / Avid DNxHR®. For developers: Requires MTRegisterProfessionalVideoWorkflowFormatReaders() and VTRegisterProfessionalVideoWorkflowVideoDecoders() to be enabled - only some DNx variants work: |
MXF Wrapped DNxHD_36 | :white_check_mark: | |
MXF Wrapped DNxHD_80 | :warning: | (codec specifically gets subsampled down to 1440 x 1080) |
MXF Wrapped DNxHD_115 | :white_check_mark: | |
MXF Wrapped DNxHD_175 | :white_check_mark: | |
MXF Wrapped DNxHR_SQ | :white_check_mark: | |
MXF Wrapped DNxHR_LB | :white_check_mark: | |
MXF Wrapped DNxHR_HQ | :white_check_mark: | |
Image Frames | :x: | Requires custom compositor |
Image Sequences | :x: | Requires custom compositor |
Raw Formats (BRaw, Red, etc) | :x: | Requires you to have SDK - manage decode and roll your own custom compositor |
Enable viable metadata from AVAssets
to ExternalRefernce
and other objects where appropriate to faciliate correctness and robustness in conversion.
Enable robust support for transitions / effects metadata to be passed between AVFoundation and OTIO
RationalTime uses double as numerator and denimonator for rational time calculations. CMTime uses Int64 and Int32 for its value and time base. In order to get most accurate conversions, OpenTimleineIO-AVFoundation uses looks at the number of decimal places in a RationalTime representation and scales it to a whole number to maximally represent the same ratio without rounding or truncating which would happen with naive Double
<-> Int
casting.
See our Unit tests for conversion notes. In general, for integer frame rates (ie 120, 60, 30, 25, 24) there is zero loss conversions. For non integer frame rates like 59.97, 29.97, 24.98 (23.976) there may be very minor differences in the conversions as of today (our Unit testing uses an accuracy factor of 0.00000000001
)
If you have ideas on lossless conversion, PR's are welcome! This was a first pass :)
OpenTimelineIO and TimecodeKit, and Ozu.ai for supporting this effort.