Waker的个人空间

回环录制系统音频

目录

开始

我想做个播客系统,那就要录制麦克风和系统声音。 起初我认为非常简单,毕竟obs能做到,我基于obs基于的ffmpeg也能做到。

然而现实狠狠地给了我一嘴巴

  1. 麦克风是很容易获取,但系统音频并不容易。Windows使用dshow可以实现,但Mac就需要新的驱动BlackHole了。跨平台问题需要解决。
  2. 现成的库都是执行ffmpeg的命令,我总不能写入文件再读文件吧,那样延迟太大了。而且还要在包中再打包一个ffmpeg执行文件,太笨重。

这时我发现了cpal,一个rust的跨平台音频库。它对接了windows的WASAPI、Mac的CoreAudio、Linux的ALSA,甚至移动端都有对接。虽然我用不到那么多平台,但这也太棒了。

实现

首先要获取设备

let host = cpal::default_host();
// 两种方案
// 直接获取默认的输出音频设备
let mut out_device = host
        .default_output_device()
        .ok_or_else(|| anyhow::anyhow!("no output device available"))?;
// 或者获取所有输出音频设备再遍历名称选择想要的设备
let output_devices = host.output_devices().expect("list output device error");

再获取设备配置

// 这里需要mac安装blackhole,windows不需要其他安装
let config = if out_device.supports_input() {
    out_device.default_input_config()
} else {
    out_device.default_output_config()
}
// 如果需要对采样率,采样精度做修改就重新生成一份config
let config = cpal::SupportedStreamConfig::new(
        1,
        cpal::SampleRate(16000),
        *config.buffer_size(),
        cpal::SampleFormat::I16,
    );

开始录制

// 因为我直接设置了采样精度是i16,如果直接使用默认就需要对多个精度match
// record是把pcm存入本地,如果希望使用其他格式,需要自行找库
let sys_stream = match config.sample_format() {
        cpal::SampleFormat::I16 => out_device.build_input_stream(
            &config.into(),
            move |data, _: &_| record_audio::<i16, i16>(data),
            err_fn,
            None,
        )?,
        sample_format => {
            println!("匹配的采样格式:{}", sample_format);
            return Err(
                anyhow::Error::msg(format!("Unsupported sample format '{sample_format}'")).into(),
            );
        }
    };
    sys_stream.play()?;

好了,成功录制!

仍需解决

Tags: #音频 #Rust