如何在 AVAudioRecorder 中控制 Opus 比特率

How to control Opus bitrate in AVAudioRecorder

我试图在 AVAudioRecorder 中设置 Opus (kAudioFormatOpus) 的比特率,但它不起作用。比特率始终在 20kb/s 左右。

let recordSettings =
    [AVEncoderBitRateKey: 32000,
     AVFormatIDKey: kAudioFormatOpus,
     AVSampleRateKey: 16000.0] as [String: Any]
let recordingFormat = AVAudioFormat(settings: recordSettings)!
let recorder = try! AVAudioRecorder(url: url, format: recordingFormat)
recorder.record()

我做错了什么吗?

事实证明,在这种情况下初始化 AVAudioRecorder 的正确方法应该是:

let recordSettings =
    [AVEncoderBitRateKey: 32000,
     AVFormatIDKey: kAudioFormatOpus,
     AVSampleRateKey: 16000.0] as [String: Any]
let recorder = try! AVAudioRecorder(url: url, settings: recordSettings)
recorder.record()

不要尝试先初始化AVAudioFormat,然后将其传递给AVAudioRecorder。 而是直接使用设置调用 init:

AVAudioRecorder(url: url, settings: recordSettings)
@IBOutlet var recordButton: UIButton!
var recorder: AVAudioRecorder!
var player: AVAudioPlayer!

@IBAction func recordBtnACtn(_ sender: Any){
    if player != nil && player.isPlaying {
        print("stopping")
        player.stop()
    }
    if recorder == nil {
        print("recording. recorder nil")
        recordButton.setTitle("Pause", for: .normal)
        recordWithPermission(true)
        return
    }
    if recorder != nil && recorder.isRecording {
        print("pausing")
        recorder.pause()
        recordButton.setTitle("Continue", for: .normal)
    } else {
        print("recording")
        recordButton.setTitle("Pause", for: .normal)

        recordWithPermission(false)
    }
}


func recordWithPermission(_ setup: Bool) {
    print("\(#function)")

    AVAudioSession.sharedInstance().requestRecordPermission {
        [unowned self] granted in
        if granted {
            DispatchQueue.main.async {
                print("Permission to record granted")
                self.setSessionPlayAndRecord()
                if setup {
                    self.setupRecorder()
                }
                self.recorder.record()
                self.meterTimer = Timer.scheduledTimer(timeInterval: 0.1,
                                                       target: self,
                                                       selector: #selector(self.updateAudioMeter(_:)),
                                                       userInfo: nil,
                                                       repeats: true)
            }
        }else{
            print("Permission to record not granted")
        }
    }
    if AVAudioSession.sharedInstance().recordPermission() == .denied {
        print("permission denied")
    }
}



func setupRecorder() {
    print("\(#function)")

    let format = DateFormatter()
    format.dateFormat="yyyy-MM-dd-HH-mm-ss"
    let currentFileName = "recording-\(format.string(from: Date())).m4a"
    print(currentFileName)

    let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
    self.soundFileURL = documentsDirectory.appendingPathComponent(currentFileName)
    print("writing to soundfile url: '\(soundFileURL!)'")

    if FileManager.default.fileExists(atPath: soundFileURL.absoluteString) {
        // probably won't happen. want to do something about it?
        print("soundfile \(soundFileURL.absoluteString) exists")
    }

    let recordSettings: [String: Any] = [
        AVFormatIDKey: kAudioFormatAppleLossless,
        AVEncoderAudioQualityKey: AVAudioQuality.max.rawValue,
        AVEncoderBitRateKey: 32000,
        AVNumberOfChannelsKey: 2,
        AVSampleRateKey: 44100.0
    ]
    do {
        recorder = try AVAudioRecorder(url: soundFileURL, settings: recordSettings)
        recorder.delegate = self
        recorder.isMeteringEnabled = true
        recorder.prepareToRecord() // creates/overwrites the file at soundFileURL
    } catch {
        recorder = nil
        print(error.localizedDescription)
    }

}