iOS - 使用AVFoundation合并视频的Swift代码

7
我正在尝试将一些视频合并为唯一的output.mov文件。导出的文件无法播放,我不知道原因。是否有人能帮助我?
func exportVideo2(path:String, outputPath:String, nMovie:Int) -> Bool{
    var composition = AVMutableComposition()
    let track:AVMutableCompositionTrack = composition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID())
    var insertTime = kCMTimeZero

    var movie = movieOfProject(path) 
    if movie.count == nMovie{
        for (index,mov) in enumerate(movie){
            let moviePath = path.stringByAppendingPathComponent(mov)
            // moviePath = path to the .mov file 
            println(moviePath)
            let moviePathUrl = NSURL(fileURLWithPath: moviePath)
            let sourceAsset = AVURLAsset(URL: moviePathUrl, options: nil)
            println(sourceAsset)
            let tracks = sourceAsset.tracksWithMediaType(AVMediaTypeVideo)
            println(sourceAsset.playable) // print true
            println(sourceAsset.exportable) // print true
            println(sourceAsset.readable) // print true
            if tracks.count > 0{
                let assetTrack:AVAssetTrack = tracks[0] as AVAssetTrack
                track.insertTimeRange(CMTimeRangeMake(kCMTimeZero,sourceAsset.duration), ofTrack: assetTrack, atTime: insertTime, error: nil)
                insertTime = CMTimeAdd(insertTime, sourceAsset.duration)
            }
        }
        let completeMovie = outputPath.stringByAppendingPathComponent("movie.mov")
        let completeMovieUrl = NSURL(fileURLWithPath: completeMovie)
        var exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality)
        exporter.outputURL = completeMovieUrl
        exporter.outputFileType = AVFileTypeMPEG4
        exporter.exportAsynchronouslyWithCompletionHandler(nil)
        let ass = AVURLAsset(URL: completeMovieUrl, options: nil)
        println(ass.readable) // print false
        println(ass.exportable) // print false
        println(ass.playable) // print false
        return true
    }else{
        return false
    }
} 

我需要合并的.mov文件都是可读的,所以我认为问题出在最后一部分,即导出输出视频的地方。

1个回答

8
解决了。
func exportVideo3(path:String, outputPath:String, nMovie:Int) -> Bool{
    var composition = AVMutableComposition()
    let trackVideo:AVMutableCompositionTrack = composition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID())
    let trackAudio:AVMutableCompositionTrack = composition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID())
    var insertTime = kCMTimeZero

    var movie = movieOfProject(path)
    if movie.count == nMovie{
        for (index,mov) in enumerate(movie){
            let moviePath = path.stringByAppendingPathComponent(mov)
            let moviePathUrl = NSURL(fileURLWithPath: moviePath)
            let sourceAsset = AVURLAsset(URL: moviePathUrl, options: nil)

            let tracks = sourceAsset.tracksWithMediaType(AVMediaTypeVideo)
            let audios = sourceAsset.tracksWithMediaType(AVMediaTypeAudio)

            if tracks.count > 0{
                let assetTrack:AVAssetTrack = tracks[0] as AVAssetTrack
                trackVideo.insertTimeRange(CMTimeRangeMake(kCMTimeZero,sourceAsset.duration), ofTrack: assetTrack, atTime: insertTime, error: nil)
                   let assetTrackAudio:AVAssetTrack = audios[0] as AVAssetTrack
                  trackAudio.insertTimeRange(CMTimeRangeMake(kCMTimeZero,sourceAsset.duration), ofTrack: assetTrackAudio, atTime: insertTime, error: nil)
                insertTime = CMTimeAdd(insertTime, sourceAsset.duration)
            }
        }

        let completeMovie = outputPath.stringByAppendingPathComponent("movie.mov")
        let completeMovieUrl = NSURL(fileURLWithPath: completeMovie)
        var exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality)
        exporter.outputURL = completeMovieUrl
        exporter.outputFileType = AVFileTypeMPEG4 //AVFileTypeQuickTimeMovie
        exporter.exportAsynchronouslyWithCompletionHandler({
            switch exporter.status{
            case  AVAssetExportSessionStatus.Failed:
                println("failed \(exporter.error)")
            case AVAssetExportSessionStatus.Cancelled:
                println("cancelled \(exporter.error)")
            default:
                println("complete")
            }
        })
        return true
    }else{
        return false
    }
}

1
看起来你做了两个更改:1)添加音频轨道和2)在完成处理程序中异步检查导出状态。你是需要这两个更改都来解决问题,还是只需要第二个更改? - acj
3
你是如何设置导出视频文件的尺寸?我们的源视频是竖屏的,但导出的视频变成了正方形。 - Crashalot
@马可,请看一下我的问题 https://stackoverflow.com/questions/55771275/duet-merge-2-videos-side-by-side - Ahtazaz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接