带有文本层的视频导出AVFoundation崩溃

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了带有文本层的视频导出AVFoundation崩溃相关的知识,希望对你有一定的参考价值。

我将在业余时间为ios开发视频编辑应用。

[我参加了几场其他节目后几周才恢复了工作,即使我没有对代码进行任何重大更改-现在每次尝试导出视频作品时它都崩溃了

我签出并构建了与我当时成功上传到TestFlight的提交完全相同的提交(并且它可以在多个设备上运行而不会崩溃),所以这可能是我从那时起更新的最新Xcode / iOS SDK的问题?

代码在线程上的_ xpc_api_misuse上崩溃:

com.apple.coremedia.basicvideocompositor.output

调试导航器:

enter image description here

崩溃时,调试导航器上有70多个线程,所以也许出了点问题,应用程序使用了太多线程(从未见过这么多线程)。


我的应用程序使用文本图层在导出的视频上叠加了“水印”。玩了之后,我发现如果我注释掉水印代码,可以避免崩溃:

    guard let exporter = AVAssetExportSession(asset: composition, presetName: AVAssetExportPresetHighestQuality) else 
        return failure(ProjectError.failedToCreateExportSession)
    
    guard let documents = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) else 
        return failure(ProjectError.temporaryOutputDirectoryNotFound)
    
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd_HHmmss"
    let fileName = dateFormatter.string(from: Date())
    let fileExtension = "mov"
    let fileURL = documents.appendingPathComponent(fileName).appendingPathExtension(fileExtension)
    exporter.outputURL = fileURL

    exporter.outputFileType = AVFileType.mov
    exporter.shouldOptimizeForNetworkUse = true // check if needed

    // OFFENDING BLOCK (commenting out averts crash)
    if addWaterMark 
        let frame = CGRect(origin: .zero, size: videoComposition.renderSize)
        let watermark = WatermarkLayer(frame: frame)
        let parentLayer = CALayer()
        let videoLayer = CALayer()

        parentLayer.frame = frame
        videoLayer.frame = frame
        parentLayer.addSublayer(videoLayer)
        parentLayer.addSublayer(watermark)
        videoComposition.animationTool = AVVideoCompositionCoreAnimationTool(postProcessingAsVideoLayer: videoLayer, in: parentLayer)
    
    // END OF OFFENDING BLOCK

    exporter.videoComposition = videoComposition

    exporter.exportAsynchronously 
    // etc.

水印层的代码是:

class WatermarkLayer: CATextLayer 

    private let defaultFontSize: CGFloat = 48

    private let rightMargin: CGFloat = 10
    private let bottomMargin: CGFloat = 10

    init(frame: CGRect) 
        super.init()
        guard let appName = Bundle.main.infoDictionary?["CFBundleName"] as? String else 
            fatalError("!!!")
        
        self.foregroundColor = CGColor.srgb(r: 255, g: 255, b: 255, a: 0.5)
        self.backgroundColor = CGColor.clear
        self.string = String(format: String.watermarkFormat, appName)
        self.font = CTFontCreateWithName(String.watermarkFontName as CFString, defaultFontSize, nil)
        self.fontSize = defaultFontSize
        self.shadowOpacity = 0.75
        self.alignmentMode = .right
        self.frame = frame
    

    required init?(coder: NSCoder) 
        fatalError("init(coder:) has not been implemented. Use init(frame:) instead.")
    

    override func draw(in ctx: CGContext) 
        let height = self.bounds.size.height
        let fontSize = self.fontSize
        let yDiff = (height-fontSize) - fontSize/10 - bottomMargin // Bottom (minus margin)

        ctx.saveGState()
        ctx.translateBy(x: -rightMargin, y: yDiff)
        super.draw(in: ctx)
        ctx.restoreGState()
    

任何想法会发生什么?

也许我的代码做错了什么,由于某些Apple错误已修复或实现的“漏洞”被堵塞,所以在先前的SDK中以某种方式“获得通过”?

答案

我遇到同样的问题。在iOS 13.4之后启动,仅在模拟器上显示(设备运行正常)。如果我注释掉parentLayer.addSublayer(videoLayer),则该应用不会崩溃,但是导出的视频不是所需的输出。

以上是关于带有文本层的视频导出AVFoundation崩溃的主要内容,如果未能解决你的问题,请参考以下文章

使用 AVFoundation 的方形视频

使用 AVFoundation 覆盖两个视频

带有 Core Audio AudioQueue 的 AVFoundation 会话

使用 AVFoundation 裁剪视频

AVFoundation下的视频分帧处理

iOS开发进阶 - 用AVFoundation自定义视频录制功能