You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何录制4K 60FPS至内部存储?遇ProRes录制异常

解决方案:用AVAssetWriter替代AVCaptureMovieFileOutput实现内部存储ProRes录制

系统的AVCaptureMovieFileOutput对高码率ProRes格式的内部存储录制有硬性限制,但Blackmagic Cam这类应用是通过手动捕获视频帧并使用AVAssetWriter写入文件的方式绕过了这个限制。以下是具体实现步骤:

1. 替换输出组件,配置AVCaptureVideoDataOutput

移除原有的AVCaptureMovieFileOutput,改用AVCaptureVideoDataOutput获取原始视频帧数据,并指定ProRes编码格式:

// 配置视频数据输出
let videoOutput = AVCaptureVideoDataOutput()
videoOutput.setSampleBufferDelegate(self, queue: DispatchQueue(label: "videoQueue"))

// 设置ProRes编码参数(根据设备支持的格式调整)
guard let videoSettings = [
    AVVideoCodecKey: AVVideoCodecType.proRes422HQ, // 可替换为其他ProRes格式
    AVVideoWidthKey: 1920,
    AVVideoHeightKey: 1080
] as [String: Any] else {
    fatalError("Invalid video settings")
}
videoOutput.videoSettings = videoSettings

// 添加到捕获会话
if captureSession.canAddOutput(videoOutput) {
    captureSession.addOutput(videoOutput)
}

2. 初始化AVAssetWriter用于写入内部存储

在开始录制时,初始化AVAssetWriter并指定内部存储的文件路径:

var assetWriter: AVAssetWriter?
var videoInput: AVAssetWriterInput?

func startRecording() {
    let outputFileName = UUID().uuidString
    let outputFilePath = (NSTemporaryDirectory() as NSString).appendingPathComponent("\(outputFileName).mov")
    let outputURL = URL(fileURLWithPath: outputFilePath)
    
    do {
        assetWriter = try AVAssetWriter(outputURL: outputURL, fileType: .mov)
        
        // 配置视频输入,匹配ProRes格式和分辨率
        let videoInputSettings = [
            AVVideoCodecKey: AVVideoCodecType.proRes422HQ,
            AVVideoWidthKey: 1920,
            AVVideoHeightKey: 1080,
            AVVideoCompressionPropertiesKey: [
                AVVideoAverageBitRateKey: 380_000_000 // 根据需求调整码率
            ]
        ] as [String: Any]
        
        videoInput = AVAssetWriterInput(mediaType: .video, outputSettings: videoInputSettings)
        videoInput?.expectsMediaDataInRealTime = true
        
        if let input = videoInput, assetWriter?.canAdd(input) == true {
            assetWriter?.add(input)
        }
        
        assetWriter?.startWriting()
        assetWriter?.startSession(atSourceTime: CMTime.zero)
    } catch {
        print("Failed to initialize asset writer: \(error)")
    }
}

3. 实现代理方法写入帧数据

通过AVCaptureVideoDataOutputSampleBufferDelegate处理捕获到的视频帧,写入到AVAssetWriter:

extension YourViewController: AVCaptureVideoDataOutputSampleBufferDelegate {
    func captureOutput(_ output: AVCaptureOutput, didOutput sampleBuffer: CMSampleBuffer, from connection: AVCaptureConnection) {
        guard let assetWriter = assetWriter, let videoInput = videoInput, videoInput.isReadyForMoreMediaData else {
            return
        }
        
        if assetWriter.status == .writing {
            videoInput.append(sampleBuffer)
        }
    }
}

4. 停止录制的收尾处理

func stopRecording() {
    videoInput?.markAsFinished()
    assetWriter?.finishWriting(completionHandler: {
        switch self.assetWriter?.status {
        case .completed:
            print("Recording saved to: \(self.assetWriter?.outputURL ?? URL(fileURLWithPath: ""))")
        case .failed:
            print("Recording failed: \(self.assetWriter?.error?.localizedDescription ?? "Unknown error")")
        default:
            break
        }
    })
}

关键说明

  • 系统的AVCaptureMovieFileOutput受限于Apple的存储保护策略,禁止高码率ProRes格式写入内部存储,但手动使用AVAssetWriter直接处理帧数据可以绕过这个限制,这也是Blackmagic Cam等应用的核心实现方式。
  • 需提前验证设备支持的ProRes格式和分辨率,可通过AVCaptureDevice的formats属性查询。
  • 确保已获取相机、存储权限,同时注意后台录制的兼容性。

内容的提问来源于stack exchange,提问作者Utkarsh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 10:11:10