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

AudioKit首次录制正常,二次录制失败问题求助

AudioKit二次录制失败问题解决

问题描述

首次使用AudioKit框架时,首次录制功能运行正常。调用stopAKRecordingAndSave方法停止录制并关闭AudioEngine后,再次调用prepareToAKrecord尝试录制(已执行recorder.reset()操作)却无法成功,且二次录制时出现大量警告。疑问:是否遗漏总线清理的特殊方法?是否应保持引擎运行仅重置录制器?

相关代码

准备录制方法

func prepareToAKrecord() {
    // Setup microphone and reverb
    mic = engine.input
    reverb = Reverb(mic)
    reverb.loadFactoryPreset(.mediumRoom) //large hall etc
    engine.output = reverb

    do {
        // Check if the recorder is already recording
        if recorder?.isRecording == true {
            print("Recorder is already recording. Attempting to stop before reinitializing.")
            recorder?.stop()
        }

        // Reset the recorder if it exists
        if let existingRecorder = recorder {
            try existingRecorder.reset()
            print("Recorder reset successfully.")
        }
        recorder = try NodeRecorder(node: reverb, shouldCleanupRecordings: true)
        try self.engine.start()
        try self.recorder!.record()
    } catch {
        print("Failed to create recorder: \(error)")
    }
}

停止录制方法

func stopAKRecordingAndSave() {
    self.isRecording = false

    //recorder!.stop()
    recorder.stop()
    engine.stop()

    if let recordedAudioFile = recorder!.audioFile {
        self.voiceURL = recordedAudioFile.url
        print("Recording saved to: \(self.voiceURL!)")
        //dec-4
        self.mergeVoiceSong() // Merge this voice reverb and backing track
        //self.merging = false
    } else {
        print("Failed to get the recorded audio file")
    }

    UserDefaults.standard.set(false,forKey: "newSearch")
}

问题原因与解决方案

核心问题

  1. 频繁启停AudioEngine:引擎启停属于重操作,频繁执行会导致音频会话状态冲突,且旧节点资源未被正确释放。
  2. 重复创建音频节点:每次调用prepareToAKrecord都重新创建mic和reverb,旧节点未被清理,造成总线占用冲突。

优化方案

1. 保持AudioEngine持续运行

将引擎和音频节点的初始化逻辑移至全局初始化(如viewDidLoad),仅启动一次,避免频繁启停。

2. 复用音频节点,优化录制器逻辑

无需每次录制都重建节点,停止录制后仅重置录制器即可二次录制。

修改后的代码示例

全局初始化(以ViewController为例)

var engine = AudioEngine()
var mic: AudioEngine.InputNode!
var reverb: Reverb!
var recorder: NodeRecorder?

override func viewDidLoad() {
    super.viewDidLoad()
    // 仅初始化一次音频节点与引擎
    mic = engine.input
    reverb = Reverb(mic)
    reverb.loadFactoryPreset(.mediumRoom)
    engine.output = reverb
    
    do {
        try engine.start()
    } catch {
        print("引擎启动失败:\(error)")
    }
}

准备录制方法

func prepareToAKrecord() {
    do {
        // 若正在录制则先停止
        if recorder?.isRecording == true {
            recorder?.stop()
        }
        
        // 重置已有录制器或创建新录制器
        if let existingRecorder = recorder {
            try existingRecorder.reset()
        } else {
            recorder = try NodeRecorder(node: reverb, shouldCleanupRecordings: true)
        }
        
        try recorder!.record()
        self.isRecording = true
    } catch {
        print("录制准备失败:\(error)")
    }
}

停止录制方法

func stopAKRecordingAndSave() {
    self.isRecording = false
    recorder?.stop()
    
    if let recordedAudioFile = recorder?.audioFile {
        self.voiceURL = recordedAudioFile.url
        print("录制文件已保存至:\(self.voiceURL!)")
        self.mergeVoiceSong()
    } else {
        print("无法获取录制文件")
    }
    
    UserDefaults.standard.set(false, forKey: "newSearch")
}

额外注意事项

  • 确保音频权限已正确申请,二次录制前可检查权限状态
  • 若需在特定场景停止引擎,需彻底释放所有节点引用,下次启动时重新完整初始化
  • 可通过控制台警告定位具体资源冲突问题,针对性调整代码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 23:27:13