AVAssetExportSession导出不确定性失败,并显示以下错误:“操作已停止,NSLocalizedFailureReason =无法合成视频 ”

科技网编2023-04-07 09:391860

解决方法似乎是确保assetTrackin中的参数AVMutableVideoCompositionLayerInstruction不是来自AVURLAsset对象,而是来自所返回的视频对象addMutableTrackWithMediaType

换句话说,这一行:

let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: sourceVideoTrack)

应该:

let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)

啊 数小时无尽的挫败感,因为有时第一行有效,有时却没有。

仍然想将赏金奖励给某人。

如果您可以解释为什么第一行会不确定地失败,而不是每次都失败,或者为AVMutableComposition及其相关类提供更深入的教程- 为了向用户录制的视频中添加文字叠加层-赏金全由您自己。:)

解决方法

我们在用户录制的视频中添加了字幕,但是AVAssetExportSession对象的导出不确定性失败:有时可以,有时不能。甚至还不清楚如何重现该错误。

我们注意到资产追踪似乎在出口期间丢失了。

导出之前,有两个音轨(一个用于音频,一个用于视频)。但是,检查中的相同文件URL的轨道数exportDidFinish显示为0。因此,导出过程似乎有些问题。

更新:注释掉可以exporter.videoComposition = mutableComposition解决该错误,但是当然不对视频应用任何变换。因此,问题似乎出在create上AVMutableVideoComposition,这在导出期间导致下游问题。文档和教程AVMutableVideoComposition很少,因此,即使您没有解决方案,但可以推荐Apple以外的参考来源,这也会有所帮助。

错误:

错误域= AVFoundationErrorDomain代码= -11841“操作已停止” UserInfo = 0x170676e80

码:

    let videoAsset = AVURLAsset(URL: fileUrl,options: nil)
    let mixComposition = AVMutableComposition 
    let videoTrack = mixComposition.addMutableTrackWithMediaType(AVMediaTypeVideo,preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))
    let audioTrack = mixComposition.addMutableTrackWithMediaType(AVMediaTypeAudio,preferredTrackID: CMPersistentTrackID(kCMPersistentTrackID_Invalid))

    let sourceVideoTrack = videoAsset.tracksWithMediaType(AVMediaTypeVideo)[0] as! AVAssetTrack
    let sourceAudioTrack = videoAsset.tracksWithMediaType(AVMediaTypeAudio)[0] as! AVAssetTrack
    videoTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero,videoAsset.duration),ofTrack: sourceVideoTrack,atTime: kCMTimeZero,error: nil)
    audioTrack.insertTimeRange(CMTimeRangeMake(kCMTimeZero,ofTrack: sourceAudioTrack,error: nil)

    // Create something mutable???
    // -- Create instruction
    let instruction = AVMutableVideoCompositionInstruction 
    instruction.timeRange = CMTimeRangeMake(kCMTimeZero,videoAsset.duration)
    let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: sourceVideoTrack)
    instruction.layerInstructions = [videoLayerInstruction]

    let mutableComposition = AVMutableVideoComposition 
    //mutableComposition.renderSize = videoTrack.naturalSize
    mutableComposition.renderSize = CGSize(width: 320,height: 320)
    mutableComposition.frameDuration = CMTimeMake(1,60)
    mutableComposition.instructions = [instruction]

    // Animate
    mutableComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer,inLayer: parentLayer)

    // -- Get path
    let fileName = "/editedVideo-\(arc4random  % 10000).mp4"
    let allPaths = NSSearchPathForDirectoriesInDomains(.DocumentDirectory,.UserDomainMask,true)
    let docsPath = allPaths[0] as! NSString
    let exportPath = docsPath.stringByAppendingFormat(fileName)
    let exportUrl = NSURL.fileURLWithPath(exportPath as String)!

    println("Tracks before export: \(mixComposition.tracks.count). File URL: \(exportUrl)")

    // -- Remove old video?
    if NSFileManager.defaultManager .fileExistsAtPath(exportPath as String) {
        println("Deleting existing file\n")
        NSFileManager.defaultManager .removeItemAtPath(exportPath as String,error: nil)
    }

    // -- Create exporter
    let exporter = AVAssetExportSession(asset: mixComposition,presetName: AVAssetExportPresetHighestQuality)
    exporter.videoComposition = mutableComposition
    exporter.outputFileType = AVFileTypeMPEG4
    exporter.outputURL = exportUrl
    exporter.shouldOptimizeForNetworkUse = true

    // -- Export video
    exporter.exportAsynchronouslyWithCompletionHandler({
        self.exportDidFinish(exporter)
    })


func exportDidFinish(exporter: AVAssetExportSession) {
    println("Exported video with status: \(getExportStatus(exporter))")

    // Save video to photo album
    let assetLibrary = ALAssetsLibrary 
    assetLibrary.writeVideoAtPathToSavedPhotosAlbum(exporter.outputURL,completionBlock: {(url: NSURL!,error: NSError!) in
        println("Saved video to album \(exporter.outputURL)")
        if (error != nil) {
            println("Error saving video")
        }
    })

    // Check asset tracks
    let asset = AVAsset.assetWithURL(exporter.outputURL) as? AVAsset
    println("Tracks after export: \(asset!.tracks.count). File URL: \(exporter.outputURL)")
}

问题:

1)是什么引起问题,解决方案是什么?

2)关于如何一致地重现错误的建议,希望可以帮助调试问题?

评论区