Swift: объединяйте видео вплотную с AVAssetExportSession () - PullRequest
0 голосов
/ 17 марта 2020

У меня есть массив видеозаписей, сохраненных как AVURLAsset, и я хочу объединить видео в 1 клип, чтобы они воспроизводились подряд без промежутков времени между видео. Ниже я надеюсь, что покажу только первое видео. Примечание. Я хочу, чтобы видео воспроизводилось последовательно и без пробелов между ними. Например, если между записью1 и записью2 есть реальное время, когда телефон не записывал, на выходе НЕ должно отображаться это.

Спасибо за помощь!

func mergeVideos(handler: @escaping (_ asset: AVAssetExportSession)->()) {
    let mixComposition = AVMutableComposition()
    var videoTime = CMTime.zero
    for video in self.recordings {

        let tracks = video.tracks(withMediaType: .video)
        let videoTrack = tracks[0]
        let videoTimeRange = CMTimeRangeMake(start: .zero, duration: video.duration)
        guard let compositionVideoTrack: AVMutableCompositionTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { return }
        do {
            try compositionVideoTrack.insertTimeRange(videoTimeRange, of: videoTrack, at: videoTime)
            videoTime = CMTimeAdd(videoTime, video.duration)
        } catch {
            print("An error occurred")
            return
        }
    }

    guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
    let dateFormatter = DateFormatter()
    dateFormatter.dateStyle = .long
    dateFormatter.timeStyle = .short
    let date = dateFormatter.string(from: Date())
    let url = documentDirectory.appendingPathComponent("mergeVideo-\(date).mov")

    guard let exporter = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) else { return }
    exporter.outputURL = url
    exporter.outputFileType = AVFileType.mov
    exporter.shouldOptimizeForNetworkUse = true
    handler(exporter)
}

1 Ответ

0 голосов
/ 17 марта 2020

Решение состоит в том, чтобы переместить AVMutableCompositionTrack за пределы для l oop. Моя обновленная функция для объединения видео (со звуком) ниже. Надеюсь, это кому-нибудь поможет!

var recordings = [AVURLAsset]()

func mergeVideos(handler: @escaping (_ asset: AVAssetExportSession)->()) {
    let videoComposition = AVMutableComposition()
    var lastTime: CMTime = .zero

    guard let videoCompositionTrack = videoComposition.addMutableTrack(withMediaType: .video, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { return }
    guard let audioCompositionTrack = videoComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: Int32(kCMPersistentTrackID_Invalid)) else { return }

    for video in self.recordings {
        //add audio/video
        do {
            try videoCompositionTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: video.duration), of: video.tracks(withMediaType: .video)[0], at: lastTime)
            try audioCompositionTrack.insertTimeRange(CMTimeRangeMake(start: .zero, duration: video.duration), of: video.tracks(withMediaType: .audio)[0], at: lastTime)

        } catch {
            print("Failed to insert audio or video track")
            return
        }

        //update time
        lastTime = CMTimeAdd(lastTime, video.duration)
    }

    //create url
    guard let documentDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
    let dateFormatter = DateFormatter()
    dateFormatter.dateStyle = .long
    dateFormatter.timeStyle = .short
    let date = dateFormatter.string(from: Date())
    let url = documentDirectory.appendingPathComponent("mergeVideo-\(date).mov")

    //export
    guard let exporter = AVAssetExportSession(asset: videoComposition, presetName: AVAssetExportPresetHighestQuality) else { return }
    exporter.outputURL = url
    exporter.outputFileType = AVFileType.mp4
    exporter.shouldOptimizeForNetworkUse = true
    handler(exporter)
}
...