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

如何在FFMPEG C/C++中从ALSA读取帧时设置采样率

解决ALSA音频采样率无法设置为8000Hz的问题

先排查硬件支持性

首先要确认你的音频硬件(麦克风/声卡)是否支持8000Hz采样率——很多消费级设备默认只支持44100Hz、48000Hz这类标准采样率,低采样率可能不在硬件支持范围内。

可以用ALSA自带的命令行工具验证:

arecord --device=hw:0 --format=S16_LE --rate=8000 test.wav

如果命令执行失败(比如抛出Invalid argument错误),说明硬件不支持8000Hz,此时只能通过软件重采样来转换采样率;如果能正常录制,说明硬件支持,继续调整FFmpeg参数。

调整FFmpeg参数设置

你当前的代码中已经设置了sample_rate选项,但可以尝试补充声道数参数——部分设备在双声道模式下不支持低采样率,强制指定单声道可能解决问题:

AVDictionary* options = NULL;
av_dict_set(&options, "sample_rate", "8000", 0);
av_dict_set(&options, "channels", "1", 0); // 添加单声道设置

int res = avformat_open_input(&format_context, "hw:0", input_format, &options);

另外,调用avformat_open_input后,可以检查options中是否有未被FFmpeg识别的选项(未识别的参数会保留在字典中),这能帮你确认sample_rate是否被ALSA设备正确处理:

// 在avformat_open_input后添加
AVDictionaryEntry* entry = NULL;
while ((entry = av_dict_get(options, "", entry, AV_DICT_IGNORE_SUFFIX))) {
    fprintf(stderr, "未识别的选项: %s = %s\n", entry->key, entry->value);
}
av_dict_free(&options);

硬件不支持时的软件重采样方案

如果硬件确实无法输出8000Hz采样率,就需要用FFmpeg的Swresample模块对采集到的音频进行重采样转换。以下是核心实现代码:

1. 初始化重采样上下文

#include <libswresample/swresample.h>

// 初始化重采样上下文,根据实际原参数调整
SwrContext* swr_ctx = swr_alloc_set_opts(
    NULL,
    av_get_default_channel_layout(1),    // 目标声道(单声道)
    AV_SAMPLE_FMT_S16,                  // 目标采样格式
    8000,                               // 目标采样率
    av_get_default_channel_layout(2),    // 原声道(双声道,对应你当前的输出)
    AV_SAMPLE_FMT_S16,                  // 原采样格式
    44100,                              // 原采样率
    0, NULL
);
if (!swr_ctx || swr_init(swr_ctx) < 0) {
    // 初始化失败处理
    exit(1);
}

2. 对读取的音频帧进行重采样

AVFrame* src_frame = av_frame_alloc();
AVFrame* dst_frame = av_frame_alloc();

// 配置目标帧参数
dst_frame->format = AV_SAMPLE_FMT_S16;
dst_frame->channel_layout = av_get_default_channel_layout(1);
dst_frame->sample_rate = 8000;

// 读取原音频帧(省略av_read_frame等逻辑)
if (av_read_frame(format_context, &pkt) >= 0) {
    avcodec_send_packet(codec_ctx, &pkt);
    avcodec_receive_frame(codec_ctx, src_frame);

    // 计算重采样后的样本数量
    int dst_nb_samples = av_rescale_rnd(
        src_frame->nb_samples, 8000, 44100, AV_ROUND_UP
    );
    av_frame_get_buffer(dst_frame, 0);

    // 执行重采样
    swr_convert(swr_ctx,
                dst_frame->data, dst_nb_samples,
                (const uint8_t**)src_frame->data, src_frame->nb_samples);
    dst_frame->nb_samples = dst_nb_samples;

    // 此时dst_frame就是8000Hz的音频帧,可后续处理
}

3. 资源释放

记得在程序结束时释放重采样上下文和帧资源:

swr_free(&swr_ctx);
av_frame_free(&src_frame);
av_frame_free(&dst_frame);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 17:18:13