【问题标题】:AVAudioFile.length is 0 even if file existsAVAudioFile.length 为 0 即使文件存在
【发布时间】:2025-12-15 23:25:05
【问题描述】:

我正在创建一个用于将声音写入声音文件的 AVAudioFile。如果文件已经存在,我想将 framePosition 移动到文件末尾,以便在末尾继续写入,而不是替换现有文件。

我做了一些测试,试图将文件中的缓冲区读取到具有不同 URL 的新文件中,这样它就不会覆盖原始文件。当我尝试将缓冲区读入新文件时发生崩溃:

let audioFile = try AVAudioFile(forReading: [URL to existing .caf file])
let audioFrameCount = AVAudioFrameCount(UInt32(audioFile.length))
let audioBuffer = AVAudioPCMBuffer(PCMFormat: audioFile.processingFormat, frameCapacity: audioFrameCount)

let newAudioFile = try AVAudioFile(forWriting: [another URL], settings: self.engine.mainMixerNode.outputFormatForBus(0).settings)
try newAudioFile.readIntoBuffer(audioBuffer, frameCount: audioFrameCount!) <-- CRASHES ON THIS LINE

崩溃日志:由于未捕获的异常“com.apple.coreaudio.avfaudio”而终止应用程序,原因:“错误 -50”

伙计,我真的很讨厌 CoreAudio 崩溃日志。他们什么也没告诉我!

难道不能将数据读入为写入而创建的文件中吗?

更新

好的,所以在一些建议之后我做了一些改变。基本上,这些是我正在采取的步骤:

  1. 检查文件是否已存在。
  2. 如果是,打开它进行读取并获取音频缓冲区。
  3. 创建一个新文件进行写入(使用相同的文件 URL)
  4. 使用 writeFromBuffer 将缓冲区从旧文件写入新文件
  5. 将新文件的 framePosition 移到末尾,以便我可以继续对其进行写入/录制。

但是,新文件的长度在我写入后为0。

这是我的代码:

//Check if a file already exists. If so continue to record at the end of it
var audioBuffer : AVAudioPCMBuffer!
var audioFrameCount : AVAudioFrameCount!
if (NSFileManager.defaultManager().fileExistsAtPath(self.audioRecordURL.path!)) {
    do {
        let existingAudioFile = try AVAudioFile(forReading: self.audioRecordURL)
        audioFrameCount = AVAudioFrameCount(existingAudioFile.length)
        if (audioFrameCount > 0) {
            audioBuffer = AVAudioPCMBuffer(PCMFormat: existingAudioFile.processingFormat, frameCapacity: audioFrameCount)
        }
    } catch let error as NSError {
        NSLog("Error reading buffer from file %@", error.localizedDescription)
    }
}

//Create a new file. This will replace the old file
do {
    self.audioFile = try AVAudioFile(forWriting: self.audioRecordURL, settings: self.engine.mainMixerNode.outputFormatForBus(0).settings)
} catch let error as NSError {
    NSLog("Error creating AVAudioFile %@", error.localizedDescription)
}

//Read the audio buffer from the old file into the new file
if (audioBuffer != nil) {
    do {
        try self.audioFile.writeFromBuffer(audioBuffer)
        self.audioFile.framePosition = self.audioFile.length
    } catch let error as NSError {
        NSLog("Error reading buffer into file %@", error.localizedDescription)
    }
}

顺便说一句,readIntoBuffer 的命名让我非常困惑。听起来好像您应该使用该方法将文件读入缓冲区,但是根据文档,您应该使用它将缓冲区读入文件吗?那么为什么我不能使用该方法将缓冲区添加到我的文件中呢?为什么我必须使用 writeFromBuffer?

更新 2

所以,我设法解决了它。显然,我必须先调用 readIntoBuffer 才能用数据实际填充缓冲区,然后才能使用它。所以我添加了这一行

try existingAudioFile.readIntoBuffer(audioBuffer)

之后

audioBuffer = AVAudioPCMBuffer(PCMFormat: existingAudioFile.processingFormat, frameCapacity: audioFrameCount)

【问题讨论】:

  • -50 通常是参数错误。 ! 后面的 audioFrameCount 真的有必要吗? audioFrameCount 是否有有效值?
  • 我删除了! (不知道为什么我在那里有那个)。是的,audioFrameCount 有一个有效值。
  • 你仍然得到-50?要么真的不可能从打开的文件中读取,要么你的设置与音频缓冲区格式不匹配。为什么不先打开文件进行读取、读取、关闭文件,然后再打开文件进行写入以解决此问题?
  • 嗨@andlin,我有一个问题想和你讨论。我正在使用 AVAudioEngine 和 AVAudioFile 保存音频文件,但问题是我的应用程序在创建新文件时崩溃。在我的代码中,在“AVAudioFile(forWriting: MyUrl, settings: self.recordingEngine.mainMixerNode.outputFormatForBus(0).settings)”这一行上崩溃。你能指导我吗?谢谢

标签: swift core-audio avaudioengine avaudiofile


【解决方案1】:

不确定这是否只是您在此处提供的代码中的一个错字,而且我不是这方面的专家,但大概您的意思是崩溃的行是:

try audioFile.readIntoBuffer(audioBuffer, frameCount: audioFrameCount!)

因为按理说您无法从打开的文件中读取数据 (newAudioFile)。

然后在填充该缓冲区后,您将希望使用 writeFromBuffer 写入新文件 https://developer.apple.com/library/ios/documentation/AVFoundation/Reference/AVAudioFile_Class/#//apple_ref/occ/instm/AVAudioFile/writeFromBuffer:error:

【讨论】:

  • 我想将旧音频文件中的缓冲区添加到新创建的文件中(然后继续录制到最后)。我应该改用 writeFromBuffer 吗?这样做我不会崩溃,我的音频文件的长度在写入后为 0。我会用更多信息更新我的问题
  • 感谢您帮我解决这个问题。我没有意识到我必须调用 readIntoBuffer 才能用旧文件中的数据实际填充缓冲区,然后才能使用缓冲区。 readIntoBuffer 的文档指出“要读入文件的缓冲区”。对我来说,这听起来与它的实际用途完全相反。
  • 嗨@andlin,我有一个问题想和你讨论。我正在使用 AVAudioEngine 和 AVAudioFile 保存音频文件,但问题是我的应用程序在创建新文件时崩溃。在我的代码中,在此行“AVAudioFile(forWriting:MyUrl,设置:self.recordingEngine.mainMixerNode.outputFormatForBus(0).settings)”上崩溃,上面相同的崩溃日志“崩溃日志:由于未捕获的异常'com.apple而终止应用程序.coreaudio.avfaudio',原因:'错误 -50'”。你能指导我吗?谢谢