【发布时间】:2020-07-15 15:53:28
【问题描述】:
我在业余时间正在开发一款适用于 iOS 的视频编辑应用。
在参加其他项目几周后,我刚刚恢复了工作,并且 - 即使我没有对代码进行任何重大更改 - 现在每次尝试导出我的视频作品时它都会崩溃。
我检查并构建了与我当时成功上传到 TestFlight 完全相同的提交(并且它在多个设备上工作而没有崩溃),所以这可能是我更新后的最新 Xcode / iOS SDK 的问题那么呢?
代码在 _xpc_api_misuse 上崩溃,在一个线程上:
com.apple.coremedia.basicvideocompositor.output
调试导航器:
在崩溃时,调试导航器上有 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 中“通过”?
更新:我下载了 Ray Wenderlich's sample project 用于视频编辑并尝试为视频添加“字幕”(我不得不调整太旧的项目,以便它可以在 Xcode 11 下编译)。
瞧,它以完全相同的方式崩溃。
更新 2:我现在在设备(运行最新 iOS 13.5 的 iPhone 8)上进行了尝试,可以正常工作,没有崩溃。然而,iOS 13.5 的模拟器确实会崩溃。当我最初发布这个问题(iOS 13.4?)时,我确定它既是在设备上崩溃,也是在模拟器上崩溃。
我正在下载 iOS 12.0 模拟器进行检查,但距离它还有几 GB 的距离...
【问题讨论】:
-
我还在 Apple 的论坛 (forums.developer.apple.com/message/422504#422504) 上发布了一个问题,以便它可以收集一些风滚草。
-
您的问题解决了吗?我遇到了同样的问题。
-
@gstream79 最近没碰代码,忙于我的日常工作。有关最新进展,请参阅上面的“更新 2”。
-
在两台设备上崩溃,iOS 13.4、13.5 的模拟器
标签: ios avfoundation avcomposition