Как объединить видео клипы с помощью 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
чтобы получить общий диапазон времени аудио и видео в активе, а затем использовать результат для вставки в композицию.