Cra*_*lot 18 avfoundation ios avassetexportsession swift
我们为用户录制的视频添加了字幕,但AVAssetExportSession对象的导出失败是非确定性的:有时它会起作用,有时它不起作用.目前还不清楚如何重现错误.
我们注意到出口期间资产跟踪似乎丢失了.
在导出之前,有两个轨道(一个用于音频,一个用于视频),如预期的那样.但是在exportDidFinish
显示0个曲目中检查相同文件URL的曲目数.所以出口过程似乎有些问题.
更新:注释会exporter.videoComposition = mutableComposition
修复错误,但当然不会对视频应用任何转换.所以问题似乎在于创造AVMutableVideoComposition
,这会在出口期间导致下游问题.文档和教程AVMutableVideoComposition
很少,所以即使您没有解决方案但可以推荐Apple以外的参考资料,这将有所帮助.
错误:
Error Domain = AVFoundationErrorDomain Code = -11841"Operation Stopped"UserInfo = 0x170676e80 {NSLocalizedDescription = Operation Stopped,NSLocalizedFailureReason =视频无法合成.}
码:
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)")
}
Run Code Online (Sandbox Code Playgroud)
问题:
1)导致问题的原因是什么,解决方案是什么?
2)关于如何一致地重现错误的建议,希望有助于调试问题?
Cra*_*lot 21
似乎是治愈方法是确保assetTrack
参数AVMutableVideoCompositionLayerInstruction
不是来自AVURLAsset
对象,而是来自返回的视频对象addMutableTrackWithMediaType
.
换句话说,这一行:
let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: sourceVideoTrack)
Run Code Online (Sandbox Code Playgroud)
应该:
let videoLayerInstruction = AVMutableVideoCompositionLayerInstruction(assetTrack: videoTrack)
Run Code Online (Sandbox Code Playgroud)
哎呀.几个小时无尽的挫败感,因为有时第一条线路有效,有时却没有.
仍然想将赏金奖励给某人.
如果您可以解释为什么第一行不确定地失败,而不是每次都失败,或者提供更深入的AVMutableComposition及其相关类的教程 - 为了向用户录制的视频添加文本叠加 - 赏金就是你的全部.:)
我通过使用AVAssetExportPresetPassthrough
导出预设而不是使用特定分辨率解决了这个问题,或者AVAssetExportHighestQuality
……
let exportSession = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetPassthrough)
Run Code Online (Sandbox Code Playgroud)
这应该使用导出文件中导入视频的分辨率。
我猜你的一些视频sourceVideoTrack
是:
videoTrack
另一方面,可变轨道保证了正确的时间范围(按照指示AVMutableVideoCompositionInstruction
),因此它始终有效.
归档时间: |
|
查看次数: |
7309 次 |
最近记录: |