Swift AVFoundation将多个视频拼接在一起并保持首选变换

时间:2018-02-14 18:43:45

标签: ios swift video avfoundation

我试图将多个视频剪辑拼接在一起。如果我在一个AVMutableCompositionTrack中缝合每个AVAsset它可以工作,但是通过在前置摄像头上添加另一个具有启用镜像模式的转换来丢失第一个资产上的转换。我可以在一个AVMutableComposition中以某种方式使用多个AVMutableCompositionTrack类型的视频吗?

        // create mix composition
        let mixComposition = AVMutableComposition()

        // insert video track
        let videoCompositionTrack = mixComposition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: kCMPersistentTrackID_Invalid)

        // keep track of total duration
        var totalDuration = kCMTimeZero

        // for each video clip add to mutable composition and transform each video layer
        for (index, videoClip) in videoClips.enumerated() {

            if let videoAsset = videoClip.asset, let videoAssetTrack = videoAsset.tracks(withMediaType: AVMediaType.video).first {

                // insert current video track to composition
                try videoCompositionTrack!.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: videoAssetTrack, at: totalDuration)
                videoCompositionTrack?.preferredTransform = videoAssetTrack.preferredTransform

                // shift duration to next
                totalDuration = CMTimeAdd(totalDuration, videoAsset.duration)
            }
        }

        // Use AVAssetExportSession to export video
        let assetExport = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPreset1920x1080)
        assetExport?.outputFileType = AVFileType.mp4

        // get needed save url to save the video to recommended url
        let movieDestinationUrl = self.getRecommendedSaveUrl()

        // seting up asset export session
        assetExport?.outputURL = movieDestinationUrl
        assetExport?.shouldOptimizeForNetworkUse = true

        // export video to file system asyc
        assetExport?.exportAsynchronously(completionHandler: {
            assetExport?.cancelExport()
            switch assetExport!.status {
            case AVAssetExportSessionStatus.failed:
                break
            case AVAssetExportSessionStatus.cancelled:
                break
            default:
                DispatchQueue.main.async {
                    completion?(movieDestinationUrl, nil)
                }
            }
            if ((assetExport?.error) != nil) {
                AppDelegate.logger.error("Could not create user video: \((assetExport?.error)!)")
                DispatchQueue.main.async {
                    completion?(nil, assetExport?.error)
                }
            }
        })

我试图使用这样的东西和多个AVMutableCompositionTrack与不同的CGAffineTransform对象。

        // create mix composition
        let mixComposition = AVMutableComposition()

        // keep track of total duration
        var totalDuration = kCMTimeZero

        // for each video clip add to mutable composition and transform each video layer
        for (index, videoClip) in videoClips.enumerated() {

            if let videoAsset = videoClip.asset, let videoAssetTrack = videoAsset.tracks(withMediaType: AVMediaType.video).first {

                // insert video track
                let videoCompositionTrack = mixComposition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: CMPersistentTrackID(index))

                // insert current video track to composition
                try videoCompositionTrack!.insertTimeRange(CMTimeRangeMake(kCMTimeZero, videoAsset.duration), of: videoAssetTrack, at: totalDuration)
                videoCompositionTrack?.preferredTransform = videoAssetTrack.preferredTransform

                // shift duration to next
                totalDuration = CMTimeAdd(totalDuration, videoAsset.duration)
            }
        }

        // Use AVAssetExportSession to export video
        let assetExport = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPreset1920x1080)
        assetExport?.outputFileType = AVFileType.mp4

        // get needed save url to save the video to recommended url
        let movieDestinationUrl = self.getRecommendedSaveUrl()

        // seting up asset export session
        assetExport?.outputURL = movieDestinationUrl
        assetExport?.shouldOptimizeForNetworkUse = true

        // export video to file system asyc
        assetExport?.exportAsynchronously(completionHandler: {
            assetExport?.cancelExport()
            switch assetExport!.status {
            case AVAssetExportSessionStatus.failed:
                break
            case AVAssetExportSessionStatus.cancelled:
                break
            default:
                DispatchQueue.main.async {
                    completion?(movieDestinationUrl, nil)
                }
            }
            if ((assetExport?.error) != nil) {
                AppDelegate.logger.error("Could not create user video: \((assetExport?.error)!)")
                DispatchQueue.main.async {
                    completion?(nil, assetExport?.error)
                }
            }
        })

在上述情况下,我无法获得任何可用的视频:它比应有的短得多。我试图避免使用任何AVMutableVideoCompositionInstruction,因为它需要很长时间来处理,但如果它适用于任何分辨率,特别是镜像支持,它仍然是一个选项。

        // create mix composition
        let mixComposition = AVMutableComposition()

        // keep track of total duration
        var totalDuration = kCMTimeZero

        // keeps all layer transformations for each video asset
        var videoCompositionLayerInstructions = [AVMutableVideoCompositionLayerInstruction]()

        // for each video clip add to mutable composition and transform each video layer
        for (index, videoClip) in videoClips.enumerated() {

            if let videoAsset = videoClip.asset {

                // use first video asset track for setting like height and width
                let videoAssetTrack = videoAsset.tracks(withMediaType: AVMediaType.video).first!

                // insert video trakc
                let videoCompositionTrack = mixComposition.addMutableTrack(withMediaType: AVMediaType.video, preferredTrackID: CMPersistentTrackID(index))

                // insert current video track to composition
                try videoCompositionTrack!.insertTimeRange(CMTimeRangeMake(totalDuration, videoAssetTrack.timeRange.duration), of: videoAssetTrack, at: totalDuration)
                videoCompositionTrack?.preferredTransform = videoAssetTrack.preferredTransform

                let videoCompositionLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoAssetTrack)
                videoCompositionLayerInstruction.setTransform((videoCompositionTrack?.preferredTransform)!, at: totalDuration)
                videoCompositionLayerInstruction.setOpacity(0.0, at: videoAsset.duration)

                // apply instruction
                videoCompositionLayerInstructions.append(videoCompositionLayerInstruction)

                // shift duration to next
                totalDuration = CMTimeAdd(totalDuration, videoAsset.duration)
            }
        }

        let videoCompositionInstruction = AVMutableVideoCompositionInstruction()
        videoCompositionInstruction.timeRange = CMTimeRangeMake(kCMTimeZero, totalDuration)
        videoCompositionInstruction.layerInstructions = videoCompositionLayerInstructions

        let mainComposition = AVMutableVideoComposition()
        mainComposition.renderSize = CGSize(width: 1080, height: 1920)
        mainComposition.frameDuration = CMTimeMake(1, 30)
        mainComposition.instructions = [videoCompositionInstruction]

        // Use AVAssetExportSession to export video
        let assetExport = AVAssetExportSession(asset: mixComposition, presetName: AVAssetExportPreset1920x1080)
        assetExport?.outputFileType = AVFileType.mp4

        // get needed save url to save the video to recommended url
        let movieDestinationUrl = self.getRecommendedSaveUrl()

        // seting up asset export session
        assetExport?.outputURL = movieDestinationUrl
        assetExport?.shouldOptimizeForNetworkUse = true
        assetExport?.videoComposition = mainComposition

有人知道如何实现此功能吗?

  • 注意:我根本不需要关心音频。

0 个答案:

没有答案