Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to loop audio while merging audio and video

I am following this code to merge audio and video files. It works great. Suppose, audio length is 5 seconds and video length is 20 seconds. While I merged this files in the exported video there is no sound after 5 second. That is obvious cause my audio length is 5 seconds. But is it possible to run the audio in loop throughout the full video session.

var finalVideoURL = NSURL()
var finalVideoName = String()

func mergeAudio&VideoFiles(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)
    finalVideoURL = NSURL(fileURLWithPath: NSHomeDirectory() + "/Documents/FinalVideo.mp4")
    finalVideoName = "FinalVideo.mp4"
    let assetExport: AVAssetExportSession = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality)!
    assetExport.outputFileType = AVFileTypeMPEG4
    assetExport.outputURL = finalVideoURL as URL
    assetExport.shouldOptimizeForNetworkUse = true
    assetExport.exportAsynchronously { () -> Void in
        switch assetExport.status {
        case AVAssetExportSessionStatus.completed:
            print("Export movie to document directory from trimmed audio and mutable video complete :)")
        case  AVAssetExportSessionStatus.failed:
            print("failed \(assetExport.error)")
        case AVAssetExportSessionStatus.cancelled:
            print("cancelled \(assetExport.error)")
        default:
            print("complete")
        }
    }
}
like image 332
pigeon_39 Avatar asked Oct 18 '22 19:10

pigeon_39


1 Answers

It was asked a long time ago, but it can certainly help someone in the future, you can do it by inserting the time range of the AVAssetTrack multiple times:

let vDuration = aVideoAsset.duration
let audioAssetTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)
do {
    var currentDuration = CMTime.zero
    while currentDuration < vDuration {
        let restTime = CMTimeSubtract(vDuration, currentDuration)
        let maxTime = CMTimeMinimum(aAudioAsset.duration, restTime)
        try audioAssetTrack.insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: maxTime),
                                          of: aAudioAsset.tracks(withMediaType: .audio)[0],
                                          at: currentDuration)
        currentDuration = CMTimeAdd(currentDuration, aAudioAsset.duration)
    }
} catch {
     print("Failed to load audio track")
     continue
}
     
like image 96
Developeder Avatar answered Oct 21 '22 07:10

Developeder