AVAsset
私は、短い (1 ~ 5 秒) sを多数 (n = 30 以下で問題が見られる) シーケンスする必要があるプロジェクトに取り組んでいます。CMTimeRange(start: .zero, end: asset.duration)
私が見つけることができるすべての参考資料とサンプルプロジェクトは、コンポジショントラックへの挿入に範囲を使用するポイントを見つけることができるので、次のようになります。
let audioTrack: AVAssetTrack = ...
let videoTrack: AVAssetTrack = ...
var playhead = CMTime.zero
for asset in assets {
let assetRange = CMTimeRange(start: .zero, end: asset.duration)
let (sourceAudioTrack, sourceVideoTrack) = sourceTracks(from: asset)
try! audioTrack.insertTimeRange(assetRange, of: sourceAudioTrack, at: playhead)
try! videoTrack.insertTimeRange(assetRange, of: sourceVideoTrack, at: playhead)
playhead = playhead + assetRange.duration
}
問題は、これによりオーディオとビデオが同期しなくなることです (ビデオがオーディオより遅れているように見えます)。
- 使用するクリップの数を減らすと、問題が解決するか、深刻度が低くなるようです
- クリップを単独で再生すると、この動作は発生しません。
- 一部のアセットには、時間範囲が異なるビデオ トラックとオーディオ トラックがあります。これは、ここで説明したプライミング フレームの問題が原因である可能性があると思います
- トラックの長さが異なるアセットを除外しても問題は解決しません
- 時間範囲はすべてシステムによって 44100 タイムスケールで指定されるため、ここで説明するタイムスケールの不一致 / 丸めは適用されないようです。
時間範囲を計算するためのさまざまな戦略をいくつかテストしましたが、どれも問題を解決していないようです:
enum CompositionStrategy: Int, CaseIterable {
case each // Time range of source video track for video track, audio for audio
case videoTimeRange // Time range of source video track for both
case audioTimeRange // Time range of source audio track for both
case intersection // Intersection of source video and audio time ranges for both
case assetDuration // (start: .zero, end: asset.duration) for both
case trim // Apply audio trim from CoreMedia attachments: https://stackoverflow.com/a/33907747/266711
}
private static func calculateTimeRanges(strategy: CompositionStrategy, audioRange: CMTimeRange, videoRange: CMTimeRange, audioTrimFromStart: CMTime, audioTrimFromEnd: CMTime, assetDuration: CMTime) -> (video: CMTimeRange, audio: CMTimeRange) {
switch strategy {
case .each:
return (video: videoRange, audio: audioRange)
case .audioTimeRange:
return (video: audioRange, audio: audioRange)
case .videoTimeRange:
return (video: videoRange, audio: videoRange)
case .intersection:
let startTime = max(audioRange.start, videoRange.start)
let endTime = min(audioRange.end, videoRange.end)
let range = CMTimeRange(start: startTime, end: endTime)
return (video: range, audio: range)
case .assetDuration:
let range = CMTimeRange(start: .zero, duration: assetDuration)
return (video: range, audio: range)
case .trim:
let audioStart = audioRange.start + audioTrimFromStart
let audioEnd = audioRange.end - audioTrimFromEnd
let trimmedAudio = CMTimeRange(start: audioStart, end: audioEnd)
return (video: videoRange, audio: trimmedAudio)
}
}
(前のスニペットの再生ヘッドの増分は、オーディオとビデオの時間範囲が異なる場合に計算されたものの最大値によって増分されます)
これらの戦略のいずれも問題を解決するものではなく、コード レベルのサポートについて Apple に連絡しようとしていますが、見落としている単純なものがあることを願っています。また、Mac で iMovie を調べてみたところ、これらのクリップを同期の問題なく完全に並べることができましたがAVComposition
、プレビュー プレーヤーをバックアップするために を使用しているようには見えません。助けていただければ幸いです。