Как объединить видео клипы с помощью avfoundation? - PullRequest
0 голосов
/ 14 января 2019

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

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 Ответ

0 голосов
/ 14 января 2019

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

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

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

...