I am developing an application that should record and stick together recorded videos from camera and videos from resources. Stitching works fine and the final video plays well on the device. But when the final video is uploaded to Facebook or YouTube, a green and gray background appears when the video is played there. This background appears in the places where the recorded video ends and the video from the resources begins.

This is what it looks like:

I use AVFoundation for stitching. Here is an example code:

let finalMixComposition : AVMutableComposition = AVMutableComposition()

    var videoCompositionTrack : [AVMutableCompositionTrack] = []
    var audioCompositionTrack : [AVMutableCompositionTrack] = []

    let finalVideoCompositionInstruction : AVMutableVideoCompositionInstruction = AVMutableVideoCompositionInstruction()

    let renderSize = CGSize(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)

    var startTime = CMTime.zero

    videoCompositionTrack.append(finalMixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid)!)
    audioCompositionTrack.append(finalMixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid)!)

    let arrayVideos : [URL] = [firstVideo, secondVideo, thirdVideo, fourthVideo…]

    for url in arrayVideos {
        let videoAsset : AVAsset = AVAsset(url: url)

        let aVideoAssetTrack = videoAsset.tracks(withMediaType: AVMediaType.video)[0]

        var aAudioAssetTrack = videoAsset.tracks(withMediaType: AVMediaType.audio)[0]

        do {
            try videoCompositionTrack[0].insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: aVideoAssetTrack.timeRange.duration),
                                                         of: aVideoAssetTrack,
                                                         at: startTime)

            try audioCompositionTrack[0].insertTimeRange(CMTimeRangeMake(start: CMTime.zero, duration: aVideoAssetTrack.timeRange.duration),
                                                            of: aAudioAssetTrack,
                                                            at: startTime)
        catch {

        startTime = CMTime(seconds: startTime.seconds + aVideoAssetTrack.timeRange.duration.seconds)

    finalVideoCompositionInstruction.timeRange = CMTimeRangeMake(start: CMTime.zero, duration: startTime)

    let mutableVideoComposition : AVMutableVideoComposition = AVMutableVideoComposition()
    mutableVideoComposition.frameDuration = CMTimeMake(value: 0, timescale: 60)

    mutableVideoComposition.renderSize = renderSize

    let savePathUrl = tempURL()

    let assetExport: AVAssetExportSession = AVAssetExportSession(asset: finalMixComposition,
                                                                 presetName: AVAssetExportPresetHighestQuality)!
    assetExport.outputFileType = AVFileType.mp4
    assetExport.outputURL = savePathUrl
    assetExport.shouldOptimizeForNetworkUse = true

    assetExport.exportAsynchronously {}

There is a suspicion that this is due to different parameters of the videos. Does anyone have any idea how to solve this? Thanks for the help ;)

1 Answers

Community On Best Solutions

Solved the problem with video stitching. It was necessary to specify BitRate, Codec, ProfileLevel in the video settings. For the solution, I found a library that did it: SDAVAssetExportSession

Here is an example code:

let encoder = SDAVAssetExportSession(asset: finalMixComposition)
    encoder!.outputFileType = AVFileType.mp4.rawValue
    encoder!.outputURL = savePathUrl
    encoder!.videoSettings = [AVVideoCodecKey: AVVideoCodecType.h264,
                              AVVideoWidthKey: 1024,
                              AVVideoHeightKey: 768,
                              AVVideoCompressionPropertiesKey: [AVVideoAverageBitRateKey: 6000000,
                                                                AVVideoProfileLevelKey: AVVideoProfileLevelH264High40]]

    encoder!.audioSettings = [AVFormatIDKey: kAudioFormatMPEG4AAC,
                              AVNumberOfChannelsKey: 2,
                              AVSampleRateKey: 44100,
                              AVEncoderBitRateKey: 128000]

    encoder!.exportAsynchronously {}