合并音频和视频Swift [英] Merging audio and video Swift

查看:113
本文介绍了合并音频和视频Swift的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将N个音轨合并到一个视频文件中. 视频为MP4格式,所有音频均为m4a.

Im trying to merge N audio tracks, to an video file. The video is in MP4 format, and all audios are m4a.

所有准备工作都很好,但是导出完成后,总是失败. 这是我的代码:

All the preparation works well but when the export finishes, always fails. Heres my code :

func mixAudioAndVideo() {
    self.player?.pause()
    let mixComposition = AVMutableComposition()
    let paths = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
    let docsDirect = paths[0]

    for audioTrack in self.audioTracks {
        let musicFile = docsDirect.URLByAppendingPathComponent(audioTrack.audioName)
        let audioAsset = AVURLAsset(URL: musicFile!, options: nil)
        let audioTimeRange = CMTimeRangeMake(audioTrack.audioTime!, audioAsset.duration)
        let compositionAudioTrack:AVMutableCompositionTrack = mixComposition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid)
        do {
            try compositionAudioTrack.insertTimeRange(audioTimeRange, ofTrack: audioAsset.tracksWithMediaType(AVMediaTypeAudio).first!, atTime: audioTrack.audioTime!)
        } catch let error {
            print(error)
        }
    }

    let videoAsset = AVURLAsset(URL: video!.movieURL, options: nil)
    let videoTimeRange = CMTimeRangeMake(kCMTimeZero, videoAsset.duration)
    let compositionVideoTrack = mixComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid)

    do {
        try compositionVideoTrack.insertTimeRange(videoTimeRange, ofTrack: videoAsset.tracksWithMediaType(AVMediaTypeVideo).first!, atTime: kCMTimeZero)
    } catch let error {
        print(error)
    }

    let videoName = "video\(self.audioTracks.count).mov"
    let outputFilePath = docsDirect.URLByAppendingPathComponent(videoName)

    let assetExport = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)
    assetExport!.outputFileType = AVFileTypeQuickTimeMovie
    assetExport!.outputURL = outputFilePath!

    assetExport?.exportAsynchronouslyWithCompletionHandler({
        dispatch_async(dispatch_get_main_queue()){
            print("finished exporting \(outputFilePath)")
            print("status \(assetExport?.status)")
            print("error \(assetExport?.error)")
            SVProgressHUD.dismiss()
        }
    })
}

我得到的代码:

error Optional(Error Domain=NSURLErrorDomain Code=-1 "unknown error" UserInfo={NSLocalizedDescription=unknown error, NSUnderlyingError=0x170056140 {Error Domain=NSOSStatusErrorDomain Code=-12935 "(null)"}})

推荐答案

快捷键:3 首先合并N条音轨

Swift: 3 first merge N audio tracks

var mergeAudioURL = NSURL()

func mergeAudioFiles(audioFileUrls: NSArray) {
        let composition = AVMutableComposition()

        for i in 0 ..< audioFileUrls.count {

            let compositionAudioTrack :AVMutableCompositionTrack = composition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID())

            let asset = AVURLAsset(url: (audioFileUrls[i] as! NSURL) as URL)

            let track = asset.tracks(withMediaType: AVMediaTypeAudio)[0]

            let timeRange = CMTimeRange(start: CMTimeMake(0, 600), duration: track.timeRange.duration)

            try! compositionAudioTrack.insertTimeRange(timeRange, of: track, at: composition.duration)
        }

        let documentDirectoryURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! as NSURL
        self.mergeAudioURL = documentDirectoryURL.appendingPathComponent("Merge Audio.m4a")! as URL as NSURL

        let assetExport = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetAppleM4A)
        assetExport?.outputFileType = AVFileTypeAppleM4A
        assetExport?.outputURL = mergeAudioURL as URL
        removeFileAtURLIfExists(url: mergeAudioURL)
        assetExport?.exportAsynchronously(completionHandler:
            {
                switch assetExport!.status
                {
                case AVAssetExportSessionStatus.failed:
                    print("failed \(assetExport?.error)")
                case AVAssetExportSessionStatus.cancelled:
                    print("cancelled \(assetExport?.error)")
                case AVAssetExportSessionStatus.unknown:
                    print("unknown\(assetExport?.error)")
                case AVAssetExportSessionStatus.waiting:
                    print("waiting\(assetExport?.error)")
                case AVAssetExportSessionStatus.exporting:
                    print("exporting\(assetExport?.error)")
                default:
                    print("-----Merge audio exportation complete.\(self.mergeAudioURL)")
                }
        })
    }

然后将音频与视频合并

var mergedAudioVideoURl = NSURL()

    func mergeMutableVideoWithAudio(videoUrl:NSURL, audioUrl:NSURL){
        let mixComposition : AVMutableComposition = AVMutableComposition()
        var mutableCompositionVideoTrack : [AVMutableCompositionTrack] = []
        var mutableCompositionAudioTrack : [AVMutableCompositionTrack] = []
        let totalVideoCompositionInstruction : AVMutableVideoCompositionInstruction = AVMutableVideoCompositionInstruction()
        //start merge
        let aVideoAsset : AVAsset = AVAsset(url: videoUrl as URL)
        let aAudioAsset : AVAsset = AVAsset(url: audioUrl as URL)
        mutableCompositionVideoTrack.append(mixComposition.addMutableTrack(withMediaType: AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid))
        mutableCompositionAudioTrack.append( mixComposition.addMutableTrack(withMediaType: AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid))
        let aVideoAssetTrack : AVAssetTrack = aVideoAsset.tracks(withMediaType: AVMediaTypeVideo)[0]
        let aAudioAssetTrack : AVAssetTrack = aAudioAsset.tracks(withMediaType: AVMediaTypeAudio)[0]
        do{
            try mutableCompositionVideoTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero, aVideoAssetTrack.timeRange.duration), of: aVideoAssetTrack, at: kCMTimeZero)
            try mutableCompositionAudioTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero, aVideoAssetTrack.timeRange.duration), of: aAudioAssetTrack, at: kCMTimeZero)
        }catch{

        }
        totalVideoCompositionInstruction.timeRange = CMTimeRangeMake(kCMTimeZero,aVideoAssetTrack.timeRange.duration )
        let mutableVideoComposition : AVMutableVideoComposition = AVMutableVideoComposition()
        mutableVideoComposition.frameDuration = CMTimeMake(1, 30)
        mutableVideoComposition.renderSize = CGSize(width: 1280, height: 720)
        mergedAudioVideoURl = NSURL(fileURLWithPath: NSHomeDirectory() + "/Documents/FinalVideo.mp4")
        let assetExport: AVAssetExportSession = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)!
        assetExport.outputFileType = AVFileTypeMPEG4
        assetExport.outputURL = mergedAudioVideoURl as URL
        removeFileAtURLIfExists(url: mergedAudioVideoURl)
        assetExport.shouldOptimizeForNetworkUse = true
        assetExport.exportAsynchronously { () -> Void in
            switch assetExport.status {
            case AVAssetExportSessionStatus.completed:
                print("-----Merge mutable video with trimmed audio exportation complete.\(self.mergedAudioVideoURl)")
            case  AVAssetExportSessionStatus.failed:
                print("failed \(assetExport.error)")
            case AVAssetExportSessionStatus.cancelled:
                print("cancelled \(assetExport.error)")
            default:
                print("complete")
            }
        }
    }

    func removeFileAtURLIfExists(url: NSURL) {
        if let filePath = url.path {
            let fileManager = FileManager.default
            if fileManager.fileExists(atPath: filePath) {
                do{
                    try fileManager.removeItem(atPath: filePath)
                } catch let error as NSError {
                    print("-----Couldn't remove existing destination file: \(error)")
                }
            }
        }
    }

这篇关于合并音频和视频Swift的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆