首页 > 解决方案 > 将音频样本缓冲区附加到 AVAssetwriterInput 时 AVAssetWiter 状态失败 - OSX,Swift

问题描述

我正在尝试使用 AVFoundation 在 OSX 中录制带有音频的屏幕,当我录制视频时效果很好。但是当添加音频输入并将其附加到 AVAssetWriterInput 时,资产编写器状态更改为 .failed。

if let sampleBuffer = sampleBuffer {
            if CMSampleBufferDataIsReady(sampleBuffer) {
                if assetWriter.status == .unknown {
                    let startTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer)
                    assetWriter.startWriting()
                    assetWriter.startSession(atSourceTime: startTime)
                }
                if assetWriter.status == .failed {
                    print("writer error \(String(describing: assetWriter.error?.localizedDescription))")
                    return false
                }
                if isVideo {
                    if videoInputWriter.isReadyForMoreMediaData {
                        videoInputWriter.append(sampleBuffer)
                        return true
                    }
                } else {
                    if audioInputWriter.isReadyForMoreMediaData {
                        audioInputWriter.append(sampleBuffer)
                        return true
                    }
                }
            }
        }

错误信息是

Error Domain=AVFoundationErrorDomain Code=-11800 "The operation could not be completed" UserInfo={NSLocalizedFailureReason=An unknown error occurred (-12780), NSLocalizedDescription=The operation could not be completed, NSUnderlyingError=0x600002841320 {Error Domain=NSOSStatusErrorDomain Code=-12780 "(null)"}}

标签: swiftmacosavfoundationavassetwriteravassetwriterinput

解决方案


欢迎!

我猜,但您似乎正在使用相同的回调来处理音频和视频样本。问题可能在于音频和视频样本将在不同的队列(线程)中同时传递,这意味着assetWriter.startSession(atSourceTime: startTime)可能会在不同的线程中意外执行多次——这是不允许的。

您需要以某种方式(原子地)保护该调用,例如通过使用单独的同步队列。或者,您可以只使用到达的第一个视频缓冲区开始会话,并忽略之前的任何音频缓冲区(这也可以防止视频开头出现意外的黑帧)。


推荐阅读