A adição de legendas de texto à faixa de vídeo (em Swift) falha com o código de erro -11841
Estou lutando para adicionar legendas de texto aos vídeos há um tempo. Eu adicionei alguns links que me referi em detalhes, mas eles não estão ajudando.
No código abaixo, estou tentando adicionar uma legenda a um vídeo. O caminho do arquivo de saída é o seguinte:
file:///var/mobile/Applications/03E49B29-1070-4541-B7CB-B1366732C179/Documents/output_movie.mov
Além disso, o arquivo de entrada foi gravado com uma chamada para o UIPickerView no mesmo aplicativo, no caminho temporário abaixo:
file:///private/var/mobile/Applications/03E49B29-1070-4541-B7CB-B1366732C179/tmp/capture/capturedvideo.MOV
O erro que estou recebendo é o seguinte,
Error:-
Domain=AVFoundationErrorDomain Code=-11841 "Operation Stopped" UserInfo=0x15ebcfb0 {NSLocalizedDescription=Operation Stopped, NSLocalizedFailureReason=The video could not be composed.}
Description:-
<AVAssetExportSession: 0x15d97c80, asset = <AVMutableComposition: 0x15d788d0 tracks = ("<AVMutableCompositionTrack: 0x15d86910 trackID = 1, mediaType = vide, editCount = 1>")>, presetName = AVAssetExportPresetHighestQuality, outputFileType = com.apple.quicktime-movie
Completed merging the video with status code 4
O código que estou usando é o seguinte. Estou executando-o no iOS 7.1.2 em um iPhone 4s.
class func mergeVideoWithTheme(outputUrl: NSURL, inputVideoUrl videoUrl: NSURL!, onComplete completionHandler: ((Int) -> ())!) -> Void {
// 1. mergeComposition adds all the AVAssets
var mergeComposition : AVMutableComposition = AVMutableComposition()
var trackVideo : AVMutableCompositionTrack = mergeComposition.addMutableTrackWithMediaType(AVMediaTypeVideo, preferredTrackID: CMPersistentTrackID())
//var trackAudio : AVMutableCompositionTrack = mergeComposition.addMutableTrackWithMediaType(AVMediaTypeAudio, preferredTrackID: CMPersistentTrackID())
// 2. Add a bank for theme insertion later
//trackVideo.insertTimeRange(range, ofTrack: VideoHelper.Static.blankTrack, atTime: kCMTimeZero, error: nil)
// 3. Source tracks
let sourceAsset = AVURLAsset(URL: videoUrl, options: nil)
let sourceDuration = CMTimeRangeMake(kCMTimeZero, sourceAsset.duration)
let vtrack: AVAssetTrack? = sourceAsset.tracksWithMediaType(AVMediaTypeVideo)[0] as? AVAssetTrack
let atrack: AVAssetTrack? = sourceAsset.tracksWithMediaType(AVMediaTypeAudio)[0] as? AVAssetTrack
if (vtrack == nil) {
return
}
let renderWidth = vtrack?.naturalSize.width
let renderHeight = vtrack?.naturalSize.height
let insertTime = kCMTimeZero
let endTime = sourceAsset.duration
let range = sourceDuration
// append tracks
trackVideo.insertTimeRange(sourceDuration, ofTrack: vtrack, atTime: insertTime, error: nil)
//if(atrack > 0){
// trackAudio.insertTimeRange(sourceDuration, ofTrack: atracks[0] as AVAssetTrack, atTime: insertTime, error: nil)
//}
// 4. Add subtitles (we call it theme)
var themeVideoComposition : AVMutableVideoComposition = AVMutableVideoComposition(propertiesOfAsset: sourceAsset)
// 4.1 - Create AVMutableVideoCompositionInstruction
let mainInstruction: AVMutableVideoCompositionInstruction = AVMutableVideoCompositionInstruction()
mainInstruction.timeRange = range
// 4.2 - Create an AVMutableVideoCompositionLayerInstruction for the video track and fix the orientation.
let videolayerInstruction : AVMutableVideoCompositionLayerInstruction = AVMutableVideoCompositionLayerInstruction()
videolayerInstruction.setTransform(trackVideo.preferredTransform, atTime: insertTime)
videolayerInstruction.setOpacity(0.0, atTime: endTime)
// 4.3 - Add instructions
mainInstruction.layerInstructions = NSArray(array: [videolayerInstruction])
themeVideoComposition.renderScale = 1.0
themeVideoComposition.renderSize = CGSizeMake(renderWidth!, renderHeight!)
themeVideoComposition.frameDuration = CMTimeMake(1, 30)
themeVideoComposition.instructions = NSArray(array: [mainInstruction])
// add the theme
// setup variables
// add text
let title = String("Testing this subtitle")
var titleLayer = CATextLayer()
titleLayer.string = title
titleLayer.frame = CGRect(x: 0, y: 0, width: renderWidth!, height: renderHeight!)
let fontName: CFStringRef = "Helvetica-Bold"
let fontSize = CGFloat(36)
titleLayer.font = CTFontCreateWithName(fontName, fontSize, nil)
titleLayer.alignmentMode = kCAAlignmentCenter
titleLayer.foregroundColor = UIColor.whiteColor().CGColor
var backgroundLayer = CALayer()
backgroundLayer.frame = CGRect(x: 0, y: 0, width: renderWidth!, height: renderHeight!)
backgroundLayer.masksToBounds = true
backgroundLayer.addSublayer(titleLayer)
// 2. set parent layer and video layer
var parentLayer = CALayer()
var videoLayer = CALayer()
parentLayer.frame = CGRect(x: 0, y: 0, width: renderWidth!, height: renderHeight!)
videoLayer.frame = CGRect(x: 0, y: 0, width: renderWidth!, height: renderHeight!)
parentLayer.addSublayer(backgroundLayer)
parentLayer.addSublayer(videoLayer)
// 3. make animation
themeVideoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, inLayer: parentLayer)
// Remove the file if it already exists (merger does not overwrite)
let fileManager = NSFileManager.defaultManager()
fileManager.removeItemAtURL(outputUrl, error: nil)
// export to output url
var exporter = AVAssetExportSession(asset: mergeComposition, presetName: AVAssetExportPresetHighestQuality)
exporter.outputURL = outputUrl
exporter.videoComposition = themeVideoComposition
exporter.outputFileType = AVFileTypeQuickTimeMovie
exporter.shouldOptimizeForNetworkUse = true
exporter.exportAsynchronouslyWithCompletionHandler({
if (exporter.error != nil) {
println("Error")
println(exporter.error)
println("Description")
println(exporter.description)
}
completionHandler(exporter.status.rawValue)
})
}
Aprecio muito sua ajuda. Não encontrei exemplos rápidos de adicionar animações aos vídeos. Querendo saber se funcionou para alguém rápido.
Referências: (1)https://gist.github.com/SheffieldKevin/c01789ccff2b2a87f5ea 2)http://www.raywenderlich.com/30200/avfoundation-tutorial-adding-overlays-and-animations-to-videos