使用AVAssetWriter二次录制视频时抛出异常问题咨询
解决AVAssetWriter重复录制抛出异常的问题
问题根源
AVAssetWriter是一次性生命周期对象:一旦你调用了finishWriting(不管是带回调的异步版本还是同步版本),这个实例就彻底进入了完成/失效状态,再也不能调用startWriting或startSession了。你第二次录制时复用了同一个assetWriter实例,自然会触发异常。
解决方案:每次录制都创建新的AVAssetWriter实例
核心思路就是抛弃复用旧实例的想法,每次启动新录制时重新初始化一个完整的AVAssetWriter,包括对应的输入、输出配置。下面是具体的代码调整方案:
抽离AssetWriter初始化逻辑
写一个专门创建AVAssetWriter的方法,每次录制前调用它生成全新实例:private func createAssetWriter(outputURL: URL) -> AVAssetWriter? { do { // 先清理旧文件:如果输出路径已存在,删除后再创建新文件 if FileManager.default.fileExists(atPath: outputURL.path) { try FileManager.default.removeItem(at: outputURL) } // 创建新的AssetWriter实例 let writer = try AVAssetWriter(outputURL: outputURL, fileType: .mov) // 添加视频输入(根据你的需求配置参数) let videoSettings: [String: Any] = [ AVVideoCodecKey: AVVideoCodecType.h264, AVVideoWidthKey: 1920, AVVideoHeightKey: 1080 ] let videoInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoSettings) videoInput.expectsMediaDataInRealTime = true if writer.canAdd(videoInput) { writer.add(videoInput) } // 同理添加音频输入(如果需要) // ... return writer } catch { print("创建AssetWriter失败:\(error.localizedDescription)") return nil } }修改start方法:每次录制生成新实例
启动录制前,先生成新的输出文件路径,再创建新的assetWriter:func start() { // 生成唯一的输出文件URL(用时间戳命名,避免覆盖旧录制文件) let outputURL = getUniqueRecordingURL() // 创建全新的AssetWriter assetWriter = createAssetWriter(outputURL: outputURL) guard let writer = assetWriter else { print("无法启动录制:AssetWriter初始化失败") return } writer.startWriting() writer.startSession(atSourceTime: kCMTimeZero) // 这里记得开始向输入流写入媒体数据 // ... } // 辅助方法:生成唯一的录制文件路径 private func getUniqueRecordingURL() -> URL { let documentsDir = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first! let timestamp = Date().timeIntervalSince1970 return documentsDir.appendingPathComponent("recording_\(timestamp).mov") }完善finish方法:清理旧实例
在完成回调中清空assetWriter的引用,确保下次录制一定会创建新实例:func finish() { guard let writer = assetWriter else { return } print("before finish") writer.finishWriting { [weak self] in print("finish writing") // 完成后清空引用,避免内存泄漏+确保下次录制用新实例 self?.assetWriter = nil // 这里可以添加录制完成后的逻辑,比如通知用户、上传文件等 } }
额外注意事项
- 状态检查:在操作assetWriter前,可以通过
status属性判断当前状态,比如只有writer.status == .unknown或.writing时才执行对应操作,避免无效调用。 - 错误排查:如果assetWriter状态变为
.failed,可以通过error属性获取具体错误信息,方便调试。 - 文件管理:定期清理旧的录制文件,避免占用过多存储空间。
内容的提问来源于stack exchange,提问作者FuzzzzyBoy
相关产品推荐
相关产品推荐

