web-dev-qa-db-ja.com

AVAssetsをシーケンスするときに使用する正しい時間範囲はどれですか?

短い(1〜5秒)AVAssetsのシーケンスを多数必要とするプロジェクト(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
}

問題は、これによりオーディオとビデオの同期が失われることです(ビデオがオーディオより遅れているように見えます)。

  • 使用するクリップの数を減らすと、問題は解消するか、それほど深刻ではないようです。
  • クリップを単独で再生すると、この動作は発生しません
  • 一部のアセットには、時間範囲が異なるビデオトラックとオーディオトラックがあります。これは、議論されたプライミングフレームの問題が原因であると思います here
  • トラックの長さが異なるアセットをフィルターで除外しても問題は解決しません
  • 時間範囲はすべて44100タイムスケールでシステムによって与えられるため、タイムスケールの不一致/丸めの説明 here は適用されないようです

時間範囲を計算するためのいくつかの異なる戦略をテストしましたが、どれも問題を解決していないようです:

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に連絡しようとしていますが、私が見逃した簡単な何かがあることを望んでいます。私はiMovieについてもMacと同期問題なしでこれらのクリップを完全に並べることができますが、プレビュープレーヤーをバックアップするためにAVCompositionを使用しているようには見えません。

7
jefflovejapan

@Jeff、Appleのドキュメントを確認したかどうかはわかりませんが、プロセスでサイレントサンプルが削除されなかった場合に正確に2112サンプルで発生する可能性がある遅延について言及しているため、再生システムで2か所で手動で削除することを提案します。-最初に再生が開始されたとき-再生位置が別の場所に移動されたとき-たとえば、ユーザーがメディアの別の場所にスキップまたはスキップしてから再生を開始しますその新しい場所

https://developer.Apple.com/library/archive/technotes/tn2258/_index.html

それでも問題が解決しない場合は、使用しているテクノロジー、実装のタイプの詳細を教えてください。

0
Luan Naufal