微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

无法使用 cpal 录制音频并使用 opus 进行编码总是创建不正确的文件

如何解决无法使用 cpal 录制音频并使用 opus 进行编码总是创建不正确的文件

我已经工作了几个小时,试图简单地从我的麦克风录制音频并使用 opus 对其进行编码,以便我最终可以将其流式传输并在其他地方播放。目前,我正在努力尝试让它简单地播放文件。我在很大程度上基于 cpal 示例以及 libopus c 示例。目前,它只是输出一个 VLC 甚至无法读取的无意义文件。但是,如果我在编码时打印原始字节,我可以肯定地知道发生了一些事情。我也试过弄乱字节序,但它根本不起作用。我也一直在使用 rubato 将原始输出重新采样为作品可以使用的方式。

fn main() -> Result<(),anyhow::Error> {

    let mut encoder = opus::Encoder::new(48000,opus::Channels::Stereo,opus::Application::Voip).unwrap();

    let mut resampler = rubato::FftFixedInOut::<f32>::new(44100,48000,896,2);

    let host = cpal::default_host();

    let device = host.default_input_device().unwrap();


    println!("Input device: {}",device.name()?);

    let config = device
        .default_input_config()
        .expect("Failed to get default input config");
    println!("Default input config: {:?}",config);

    println!("Begin recording...");

    let err_fn = move |err| {
        eprintln!("an error occurred on stream: {}",err);
    };

    let sample_format = config.sample_format();

    // let socket = std::net::UdpSocket::bind("192.168.1.82:1337")?;
    const PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"),"/recorded.pcm");
    let socket = std::fs::File::create(PATH).unwrap();
    let mut socket = BufWriter::new(socket);

    let stream = device
        .build_input_stream_raw(
            &config.into(),sample_format,move |data,_: &_| write_input_data_f32(data,&mut encoder,&mut resampler,&mut socket),err_fn,)
        .unwrap();


    stream.play()?;

    std::thread::sleep(std::time::Duration::from_secs(10));
    drop(stream);

    Ok(())
}

type ResamplerHandle = rubato::FftFixedInOut<f32>;
// type SocketHandle = std::net::UdpSocket;
type SocketHandle = BufWriter<std::fs::File>;

fn write_input_data_f32(
    input: &Data,encoder: &mut Encoder,resampler: &mut ResamplerHandle,socket: &mut SocketHandle,) {

        let mut inp = input.as_slice::<f32>().unwrap().to_vec();

        inp.truncate(resampler.nbr_frames_needed());
        if inp.len() < resampler.nbr_frames_needed() {
            inp.append(&mut vec![0f32; resampler.nbr_frames_needed() - inp.len()]);
        }
        let mut wave_out = resampler.process(&vec![Vec::from(inp); 2]).unwrap();//[0].to_owned();

        use itertools::interleave;
        let v1 = wave_out[0].to_owned();
        let v2 = wave_out[1].to_owned();
        let v = interleave(v1.chunks(1),v2.chunks(1)).flatten().copied().collect::<Vec<f32>>();

        let buff = encoder.encode_vec_float(v.as_slice(),960).unwrap();

        use std::io::Write;
        socket.write(&buff);
}

解决方法

我发现问题在于对 opus 的工作方式的误解。它似乎在块中明显工作,而不是输入流。所以我继续并开始通过网络流式传输它们,当我放入确切的输出块时,它工作得很好!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。