5

So I have two .mp4s already recorded and stored in app, and I want to append one to the other, and export as a new video. It sort of works, but not quite!

    let composition = AVMutableComposition()
    var track = composition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID:Int32(kCMPersistentTrackID_Invalid))

    let videoAsset = AVAsset(url: AAA as URL) as AVAsset
    let videoAsset2 = AVAsset(url: BBB as URL) as AVAsset
    do {
        try track?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: videoAsset.tracks(withMediaType: AVMediaType.video)[0] as AVAssetTrack, at: kCMTimeZero)
        try track?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: videoAsset2.tracks(withMediaType: AVMediaType.video)[0] as AVAssetTrack, at: kCMTimeZero)

    } catch {
        print("darn")
    }

    let exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality)
    exporter?.outputURL = CCC
    exporter?.outputFileType = AVFileType.mp4
    exporter?.shouldOptimizeForNetworkUse = true


    exporter?.exportAsynchronously {
        print("done?")
    }

This sort of combines the videos, but it adds massive chunks of black screen in between the two clips, and removes the audio. I cannot find any recent answers to this problem. Thanks for all help!

Jack Crawford
  • 51
  • 1
  • 6

1 Answers1

1

The video timeline looks wrong, e.g. you're inserting the both videos at the same point in time, zero, and using the wrong duration for videoAsset2.

The lack of audio is due to you not inserting any audio tracks into the composition.

Try something like this (repetitive) snippet:

// video
try track?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: videoAsset.tracks(withMediaType:.video)[0] as AVAssetTrack, at: kCMTimeZero)
try track?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset2.duration), of: videoAsset2.tracks(withMediaType:.video)[0] as AVAssetTrack, at: videoAsset.duration)

// audio
try track?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: videoAsset.tracks(withMediaType:.audio)[0] as AVAssetTrack, at: kCMTimeZero)
try track?.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset2.duration), of: videoAsset2.tracks(withMediaType:.audio)[0] as AVAssetTrack, at: videoAsset.duration)

Disclaimer: I'm not sure if it's good practice to use the AVAssetTrack's owning AVAsset duration as a proxy for track length. Maybe you should be using AVAssetTrack.timeRange.

Rhythmic Fistman
  • 34,352
  • 5
  • 87
  • 159