8

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、プレビュー プレーヤーをバックアップするために を使用しているようには見えません。助けていただければ幸いです。

4

1 に答える 1