Как объединить видео клипы с помощью avfoundation?

Я успешно объединил видеоклипы в одно видео, но у меня возникла проблема в окончательном объединенном видео, в котором в конце каждого видеоклипа отображается белая рамка. Я много пытался удалить это, но не смог добиться успеха. Пожалуйста, просмотрите мой код ниже.

func merge(arrayVideos:[AVAsset], completion:@escaping (_ exporter: AVAssetExportSession) -> ()) -> Void {

    let mainComposition = AVMutableComposition()
    let compositionVideoTrack = mainComposition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)
    compositionVideoTrack?.preferredTransform = CGAffineTransform(rotationAngle: .pi / 2)
    let soundtrackTrack = mainComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
    var time:Double = 0.0

    for (index, videoAsset) in arrayVideos.enumerated() {
        let atTime = CMTime(seconds: time, preferredTimescale: 1)
        try! compositionVideoTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: videoAsset.duration), of: videoAsset.tracks(withMediaType: .video)[0], at: atTime)
        try! soundtrackTrack?.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: videoAsset.duration), of: videoAsset.tracks(withMediaType: .audio)[0], at: atTime)
        time += videoAsset.duration.seconds
    }

    let outputFileURL = URL(fileURLWithPath: NSTemporaryDirectory() + "merge.mp4")
    print("final URL:\(outputFileURL)")
    let fileManager = FileManager()

    do {
        try fileManager.removeItem(at: outputFileURL)
    } catch let error as NSError {
        print("Error: \(error.domain)")
    }

    let exporter = AVAssetExportSession(asset: mainComposition, presetName: AVAssetExportPresetHighestQuality)
    exporter?.outputURL = outputFileURL
    exporter?.outputFileType = AVFileType.mp4
    exporter?.shouldOptimizeForNetworkUse = true
    exporter?.exportAsynchronously {
        DispatchQueue.main.async {
            completion(exporter!)
        }
    }
}

1 ответ

Решение

Не используйте Double для отслеживания времени вставки это может привести к пробелам из-за ошибок округления. И не используйте preferredTimescale из 1 при преобразовании секунд, это будет эффективно округлять все до целых секунд (1000 будет более распространенной шкалой времени для этого).

Вместо этого, чтобы отслеживать время вставки, используйте CMTime инициализирован в kCMTimeZeroи использовать CMTimeAdd продвигать это.

И еще одна вещь: видео и аудио дорожки могут иметь различную продолжительность, особенно при записи. Таким образом, чтобы держать вещи в синхронизации, вы можете использовать CMTimeRangeGetIntersection чтобы получить общий диапазон времени аудио и видео в активе, а затем использовать результат для вставки в композицию.

Другие вопросы по тегам