Skip to content

Commit d4cc8d6

Browse files
committed
update our AVComposition building to ensure we disregard zero time edits which seem to appear in some content. We now can match Premieres integration of OTIO?
1 parent c28aa12 commit d4cc8d6

File tree

1 file changed

+51
-9
lines changed
  • Sources/OpenTimelineIO-AVFoundation/OpenTimelineIO-Extensions

1 file changed

+51
-9
lines changed

Sources/OpenTimelineIO-AVFoundation/OpenTimelineIO-Extensions/Timeline.swift

Lines changed: 51 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,14 @@ public extension Timeline
9191
{
9292
let gapTimeRangeOTIO = try gap.trimmedRangeInParent() ?? gap.rangeInParent()
9393
let gapTimeRange = gapTimeRangeOTIO.toCMTimeRange()
94+
95+
guard
96+
gapTimeRange.duration != .zero
97+
else
98+
{
99+
continue
100+
}
101+
94102
compositionVideoTrack.insertEmptyTimeRange(gapTimeRange)
95103
compositionVideoTrack.preferredTransform = .identity
96104

@@ -122,6 +130,13 @@ public extension Timeline
122130
let trackTimeRange = clipTimeMapping.source
123131
let sourceAssetTimeRange = clipTimeMapping.target
124132

133+
guard trackTimeRange.duration != .zero,
134+
sourceAssetTimeRange.duration != .zero
135+
else
136+
{
137+
continue
138+
}
139+
125140
// We attempt to re-use a track per OTIO track, but we may have CMFormatDesc inconsistencies which means insertion will fails
126141
// If so - we make a new one
127142
do
@@ -130,7 +145,7 @@ public extension Timeline
130145
}
131146
catch
132147
{
133-
if let compositionVideoTrack = composition.mutableTrack(compatibleWith: sourceAssetFirstVideoTrack) ?? composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
148+
if let compositionVideoTrack = composition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
134149
{
135150
try compositionVideoTrack.insertTimeRange(sourceAssetTimeRange, of: sourceAssetFirstVideoTrack, at: trackTimeRange.start)
136151
}
@@ -172,7 +187,7 @@ public extension Timeline
172187
{
173188
guard
174189
let clip = child as? Clip,
175-
let (sourceAsset, clipTimeMapping) = try clip.toAVAssetAndMapping(baseURL: baseURL, useTimecode: useAssetTimecode, rescaleToAsset: rescaleToAsset),
190+
let (sourceAsset, clipTimeMapping) = try clip.toAVAssetAndMapping(baseURL: baseURL, trackType: .audio, useTimecode: useAssetTimecode, rescaleToAsset: rescaleToAsset),
176191
let sourceAssetFirstAudioTrack = try await sourceAsset.loadTracks(withMediaType: .audio).first,
177192
let compositionAudioTrack = compositionAudioTrack
178193
else
@@ -183,7 +198,16 @@ public extension Timeline
183198
{
184199
do
185200
{
186-
let gapTimeRange = try gap.rangeInParent().toCMTimeRange()
201+
let gapTimeRangeOTIO = try gap.trimmedRangeInParent() ?? gap.rangeInParent()
202+
let gapTimeRange = gapTimeRangeOTIO.toCMTimeRange()
203+
204+
guard
205+
gapTimeRange.duration != .zero
206+
else
207+
{
208+
continue
209+
}
210+
187211
compositionAudioTrack.insertEmptyTimeRange(gapTimeRange)
188212

189213
let audioMixParams = AVMutableAudioMixInputParameters(track: compositionAudioTrack)
@@ -202,6 +226,13 @@ public extension Timeline
202226
let trackTimeRange = clipTimeMapping.source
203227
let sourceAssetTimeRange = clipTimeMapping.target
204228

229+
guard trackTimeRange.duration != .zero,
230+
sourceAssetTimeRange.duration != .zero
231+
else
232+
{
233+
continue
234+
}
235+
205236
// We attempt to re-use a track per OTIO track, but we may have CMFormatDesc inconsistencies which means insertion will fails
206237
// If so - we make a new one
207238
do
@@ -210,28 +241,39 @@ public extension Timeline
210241
}
211242
catch
212243
{
213-
if let compositionAudioTrack = composition.mutableTrack(compatibleWith: sourceAssetFirstAudioTrack) ?? composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
244+
if let compositionAudioTrack = composition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
214245
{
215-
try compositionAudioTrack.insertTimeRange(sourceAssetTimeRange, of: sourceAssetFirstAudioTrack, at: trackTimeRange.start)
246+
do {
247+
try compositionAudioTrack.insertTimeRange(sourceAssetTimeRange, of: sourceAssetFirstAudioTrack, at: trackTimeRange.start)
248+
249+
}
250+
catch {
251+
print("swallowing traack insertion error \(error)")
252+
}
216253
}
217254
}
218255

219256
// TODO: - FIX Support Time Scaling
220257
// let unscaledTrackTime = CMTimeRangeMake(start: trackTimeRange.start, duration: sourceAssetTimeRange.duration)
221258
// compositionAudioTrack.scaleTimeRange(unscaledTrackTime, toDuration: trackTimeRange.duration)
222259

223-
compositionAudioTrack.isEnabled = try await sourceAssetFirstAudioTrack.load(.isEnabled)
224-
225260
// TODO: a few milliseconds fade up / fade out to avoid pops
226261
let audioMixParams = AVMutableAudioMixInputParameters(track: compositionAudioTrack)
227262

228263
compositionAudioMixParams.append(audioMixParams)
229264
}
230265
}
231266

267+
268+
232269
// Composition Validation
233270
for track in composition.tracks
234271
{
272+
if track.segments.isEmpty
273+
{
274+
composition.removeTrack(track)
275+
}
276+
235277
do {
236278
try track.validateSegments(track.segments)
237279
}
@@ -246,7 +288,8 @@ public extension Timeline
246288
// TODO: - Custom Resolution overrides?
247289
videoComposition.renderSize = largestRasterSizeFound //CGSize(width: 1920, height: 1080)
248290
videoComposition.renderScale = 1.0
249-
291+
audioMix.inputParameters = compositionAudioMixParams
292+
250293
// TODO: It seems as though our custom instructions occasionally have a minor time gap
251294
// likely due to numerical conversion precision which throws a validation error
252295
// Im not entirely sure what to do there!
@@ -261,7 +304,6 @@ public extension Timeline
261304
// Video Composition Validation
262305
try await videoComposition.isValid(for: composition, timeRange: CMTimeRange(start: .zero, end: composition.duration), validationDelegate:validator)
263306

264-
audioMix.inputParameters = compositionAudioMixParams
265307

266308
return (composition:composition, videoComposition:videoComposition, audioMix:audioMix)
267309
}

0 commit comments

Comments
 (0)