AVAssetExportSession导出非确定性地失败并出现错误:“Operation Stopped,NSLocalizedFailureReason =视频无法合成。” [英] AVAssetExportSession export fails non-deterministically with error: "Operation Stopped, NSLocalizedFailureReason=The video could not be composed."

查看:1163
本文介绍了AVAssetExportSession导出非确定性地失败并出现错误:“Operation Stopped,NSLocalizedFailureReason =视频无法合成。”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们为用户录制的视频添加字幕,但我们的AVAssetExportSession对象的导出无法确定性地失败:有时它会起作用,有时它不起作用。目前还不清楚如何重现错误。

We add subtitles to a video recorded by the user, but the export by our AVAssetExportSession object fails non-deterministically: sometimes it works, and sometimes it doesn't. It's unclear even how to reproduce the error.

我们注意到出口期间资产轨迹似乎丢失了。

We noticed the asset tracks seem to get lost during export.

在导出之前,有两个轨道(一个用于音频,一个用于视频),如预期的那样。但是,在 exportDidFinish 中检查同一文件URL的曲目数量会显示0个曲目。因此导出过程似乎出现了问题。

Before exporting, there are two tracks (one for audio, one for video) as expected. But checking the number of tracks for the same file URL in exportDidFinish shows 0 tracks. So something seems wrong with the export process.

更新:注释掉 exporter.videoComposition = mutableComposition 修复错误,但当然没有变换应用于视频。所以问题似乎在于创建 AVMutableVideoComposition ,这会在导出期间导致下游问题。关于 AVMutableVideoComposition 的文档和教程很少,所以即使你没有解决方案但可以推荐Apple以外的参考资料,这会有所帮助。

Update: Commenting out exporter.videoComposition = mutableComposition fixes the error, but of course no transforms are applied to the video. So the problem seems to lie in creating AVMutableVideoComposition, which causes problems downstream during export. Documentation and tutorials on AVMutableVideoComposition are sparse, so even if you don't have a solution but could recommend sources for reference beyond Apple, that would be helpful.

错误:


错误域= AVFoundationErrorDomain代码= -11841操作已停止
UserInfo = 0x170676e80 {NSLocalizedDescription =操作已停止,
NSLocalizedFailureReason =视频无法合成。}

Error Domain=AVFoundationErrorDomain Code=-11841 "Operation Stopped" UserInfo=0x170676e80 {NSLocalizedDescription=Operation Stopped, NSLocalizedFailureReason=The video could not be composed.}

代码:

    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, videoAsset.duration), ofTrack: sourceAudioTrack, atTime: kCMTimeZero, 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)导致问题的原因是什么,解决方案是什么?

1) What's causing the problem, and what's the solution?

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

2) Suggestions on how to reproduce the error consistently, which hopefully helps debug the problem?

推荐答案

似乎可以解决的问题是确保 AVMutableVideoCompositionLayerInstruction 中的 assetTrack 参数不是来自 AVURLAsset 对象,但来自 addMutableTrackWithMediaType 返回的视频对象。

What seems to be the cure is making sure the assetTrack parameter in AVMutableVideoCompositionLayerInstruction is not from the AVURLAsset object, but from the video object returned by addMutableTrackWithMediaType.

换句话说,这一行:

let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: sourceVideoTrack)

应该是:

let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)

Argh。几个小时的无尽沮丧,因为有时第一行有效,有时它没有。

Argh. Hours of endless frustration because sometimes the first line worked, and sometimes it didn't.

仍然想将赏金奖给某人。

Still would like to award the bounty to someone.

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

If you can explain why the first line failed non-deterministically, instead of every time, or provide a deeper tutorial into AVMutableComposition and its related classes -- for the purposes of adding text overlays to user-recorded videos -- the bounty is all yours. :)

这篇关于AVAssetExportSession导出非确定性地失败并出现错误:“Operation Stopped,NSLocalizedFailureReason =视频无法合成。”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆