Merging sound with video causes the loss of video transparency

22 Views Asked by At

When attempting to merge audio with video, I notice a loss of video transparency in the resulting merged video. How can I maintain the video's transparency?

Video details:

  • AVVideoCodecKey: .hevcWithAlpha
  • fileType: .mov

Audio details:

  • fileType: .m4a

Merging code:

func mergeMovieWithAudio(movieUrl: URL, audioUrl: URL, success: @escaping ((URL) -> Void), failure: @escaping ((Error?) -> Void)) async {

        let mixComposition: AVMutableComposition = AVMutableComposition()
        var mutableCompositionVideoTrack: [AVMutableCompositionTrack] = []
        var mutableCompositionAudioTrack: [AVMutableCompositionTrack] = []
        let totalVideoCompositionInstruction : AVMutableVideoCompositionInstruction = AVMutableVideoCompositionInstruction()

        let aVideoAsset: AVAsset = AVAsset(url: movieUrl)
        let aAudioAsset: AVAsset = AVAsset(url: audioUrl)
        
        guard let videoTrack = mixComposition.addMutableTrack(withMediaType: .video, preferredTrackID: kCMPersistentTrackID_Invalid) else { return }
        guard let audioTrack = mixComposition.addMutableTrack(withMediaType: .audio, preferredTrackID: kCMPersistentTrackID_Invalid) else { return }

        mutableCompositionVideoTrack.append(videoTrack)
        mutableCompositionAudioTrack.append(audioTrack)

        do {
            guard let aVideoAssetTrack = try await aVideoAsset.loadTracks(withMediaType: .video).first else { return }
            guard let aAudioAssetTrack = try await aAudioAsset.loadTracks(withMediaType: .audio).first else { return }
            
            let aVideoTimeRange = try await aVideoAssetTrack.load(.timeRange)
            
            try mutableCompositionVideoTrack.first?.insertTimeRange(aVideoTimeRange, of: aVideoAssetTrack, at: CMTime.zero)
            try mutableCompositionAudioTrack.first?.insertTimeRange(aVideoTimeRange, of: aAudioAssetTrack, at: CMTime.zero)
            videoTrack.preferredTransform = try await aVideoAssetTrack.load(.preferredTransform)
            totalVideoCompositionInstruction.timeRange = aVideoTimeRange
            
            let mutableVideoComposition: AVMutableVideoComposition = AVMutableVideoComposition()
            mutableVideoComposition.frameDuration = try await aVideoAssetTrack.load(.minFrameDuration)
            mutableVideoComposition.renderSize = try await aVideoAssetTrack.load(.naturalSize)
        }
        catch {
            print(error.localizedDescription)
        }

        guard let outputURL = makeFileOutputURL(fileName: "movie.mov") else { return }
        if let exportSession = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPresetHighestQuality) {
            exportSession.outputURL = outputURL
            exportSession.outputFileType = AVFileType.mov
            exportSession.shouldOptimizeForNetworkUse = true

            await exportSession.export()
            switch exportSession.status {
            case .failed:
                if let _error = exportSession.error {
                    failure(_error)
                }

            case .cancelled:
                if let _error = exportSession.error {
                    failure(_error)
                }

            default:
                success(outputURL)
            }
        } else {
            failure(nil)
        }
    }
func makeFileOutputURL(fileName: String) -> URL? {
        do {
            var cachesDirectory: URL = try FileManager.default.url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
            cachesDirectory.appendPathComponent(fileName)
            if FileManager.default.fileExists(atPath: cachesDirectory.path) {
                try FileManager.default.removeItem(atPath: cachesDirectory.path)
            }
            return cachesDirectory
        } catch {
            print(error)
            return nil
        }
    }

Transparent video tester: https://rotato.app/tools/transparent-video

0

There are 0 best solutions below