ios - 如何使用 avfoundation 合并视频剪辑?

标签 ios swift avfoundation avmutablecomposition

我已成功将视频剪辑合并为单个视频,但我在最终合并视频中遇到问题,最终视频在每个视频剪辑结束后显示一个白框。我已经尝试了很多来删除它,但找不到成功。请在下面查看我的代码。

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!)
        }
    }
}

最佳答案

不要使用 Double 来跟踪插入时间,这可能会由于舍入错误而导致间隙。并且在转换秒时不要使用 1 的 preferredTimescale,这将有效地将所有内容四舍五入为整秒(1000 将是更常见的时间刻度)。

要跟踪插入时间,请使用初始化为 kCMTimeZeroCMTime,并使用 CMTimeAdd 来推进它。

还有一件事:视频和音频轨道可以有不同的持续时间,特别是在录制时。因此,为了保持同步,您可能需要使用 CMTimeRangeGetIntersection 获取 Assets 中音频和视频的公共(public)时间范围,然后使用结果插入组合。

关于ios - 如何使用 avfoundation 合并视频剪辑?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54180669/

相关文章:

ios - Google.com Admob 显示错误的 admob/iAd 中介,正确的方法是什么?

swift - 因关系改变而出错

avfoundation - 是否可以在没有文件扩展名的情况下使 AVURLAsset 工作?

swift - 如何在 Swift 3 中向图像添加文本?

ios - 在 iPhone 上将照片保存到磁盘的最有效内存方式?

ios - 约束/自动布局栏隐藏,Xcode 6

iphone - 以编程方式使用 ios-core 数据创建新表

iOS 辅助功能提示未在文本字段上说出

ios - 删除行后,UITableView 不会更新

ios - 在 HMEventTrigger 启用触发器中显示错误