Swift Merge audio and video files into one video

后端 未结 5 1788
闹比i
闹比i 2020-12-04 12:55

I wrote a program in Swift.I want to merge a video with an audio file, but got this error.

\"failed Error Domain=AVFoundationErrorDomain Code=-11838 \

5条回答
  •  广开言路
    2020-12-04 13:14

    In Above question same error I found due to wrong savePathUrl, destination URL should be like below code including new video name.

    I was looking for the code to Merge audio and video files into one video but couldn't find anywhere so after spending hours while reading apple docs I wrote this code.

    NOTE : This is tested and 100% working code for me.

    Stap : 1 Import this modules in your viewController.

    import UIKit
    import AVFoundation
    import AVKit
    import AssetsLibrary
    

    step 2: Add this function in your code

    func mergeFilesWithUrl(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)
        let aAudioAsset : AVAsset = AVAsset(URL: audioUrl)
    
        mutableCompositionVideoTrack.append(mixComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: kCMPersistentTrackID_Invalid))
        mutableCompositionAudioTrack.append( mixComposition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: kCMPersistentTrackID_Invalid))
    
        let aVideoAssetTrack : AVAssetTrack = aVideoAsset.tracksWithMediaType(AVMediaTypeVideo)[0]
        let aAudioAssetTrack : AVAssetTrack = aAudioAsset.tracksWithMediaType(AVMediaTypeAudio)[0]
    
    
    
        do{
            try mutableCompositionVideoTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero, aVideoAssetTrack.timeRange.duration), ofTrack: aVideoAssetTrack, atTime: kCMTimeZero)
    
            //In my case my audio file is longer then video file so i took videoAsset duration
            //instead of audioAsset duration
    
            try mutableCompositionAudioTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero, aVideoAssetTrack.timeRange.duration), ofTrack: aAudioAssetTrack, atTime: kCMTimeZero)
    
            //Use this instead above line if your audiofile and video file's playing durations are same
    
            //            try mutableCompositionAudioTrack[0].insertTimeRange(CMTimeRangeMake(kCMTimeZero, aVideoAssetTrack.timeRange.duration), ofTrack: aAudioAssetTrack, atTime: kCMTimeZero)
    
        }catch{
    
        }
    
        totalVideoCompositionInstruction.timeRange = CMTimeRangeMake(kCMTimeZero,aVideoAssetTrack.timeRange.duration )
    
        let mutableVideoComposition : AVMutableVideoComposition = AVMutableVideoComposition()
        mutableVideoComposition.frameDuration = CMTimeMake(1, 30)
    
        mutableVideoComposition.renderSize = CGSizeMake(1280,720)
    
        //        playerItem = AVPlayerItem(asset: mixComposition)
        //        player = AVPlayer(playerItem: playerItem!)
        //
        //
        //        AVPlayerVC.player = player
    
    
    
        //find your video on this URl
        let savePathUrl : NSURL = NSURL(fileURLWithPath: NSHomeDirectory() + "/Documents/newVideo.mp4")
    
        let assetExport: AVAssetExportSession = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)!
        assetExport.outputFileType = AVFileTypeMPEG4
        assetExport.outputURL = savePathUrl
        assetExport.shouldOptimizeForNetworkUse = true
    
        assetExport.exportAsynchronouslyWithCompletionHandler { () -> Void in
            switch assetExport.status {
    
            case AVAssetExportSessionStatus.Completed:
    
                //Uncomment this if u want to store your video in asset
    
                //let assetsLib = ALAssetsLibrary()
                //assetsLib.writeVideoAtPathToSavedPhotosAlbum(savePathUrl, completionBlock: nil)
    
                print("success")
            case  AVAssetExportSessionStatus.Failed:
                print("failed \(assetExport.error)")
            case AVAssetExportSessionStatus.Cancelled:
                print("cancelled \(assetExport.error)")
            default:
                print("complete")
            }
        }
    
    
    }
    

    Step 3: Call function where u want like this

    let videoUrl : NSURL =  NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("SampleVideo", ofType: "mp4")!)
    let audioUrl : NSURL = NSURL(fileURLWithPath: NSBundle.mainBundle().pathForResource("SampleAudio", ofType: "mp3")!)
    
    mergeFilesWithUrl(videoUrl, audioUrl: audioUrl)
    

    hope this will help you and will save your time.

提交回复
热议问题