目录
[一、Windows 下 FFmpeg 抓音频的唯一正解:dshow](#一、Windows 下 FFmpeg 抓音频的唯一正解:dshow)
[二、先确认你的 FFmpeg 能行](#二、先确认你的 FFmpeg 能行)
[四、C/C++(FFmpeg 6 API)最小录音流程](#四、C/C++(FFmpeg 6 API)最小录音流程)
[五、完整可编译示例代码(Windows / FFmpeg 6)](#五、完整可编译示例代码(Windows / FFmpeg 6))
[六、PCM 参数是谁决定的?](#六、PCM 参数是谁决定的?)
[七、为什么不用 swr_convert?](#七、为什么不用 swr_convert?)
[八、常见坑(Windows + FFmpeg 专属)](#八、常见坑(Windows + FFmpeg 专属))
在 Windows 系统中使用 FFmpeg 录制麦克风并将其输出为 PCM(脉冲码调制)格式,你可以按照以下步骤操作。首先,确保你已经安装了 FFmpeg。如果没有安装,可以从 FFmpeg官网 下载适用于 Windows 的版本并安装。
很多人以为 FFmpeg 只能解封装、播视频,其实它原生就能抓 Windows 麦克风 ------而且不依赖 Qt Multimedia、不碰 Win32 Audio API,一条 dshow设备链就能干活。
今天这篇,目标是:
FFmpeg 6
Windows
打开默认麦克风
录 N 秒
直接写 裸 PCM(16bit / 44.1kHz / 双声道)
不整花活,能拷就能跑。
一、Windows 下 FFmpeg 抓音频的唯一正解:dshow
FFmpeg 在 Windows 支持三种音频输入:
| 方式 | 现状 |
|---|---|
dshow |
主流、稳定 |
wasapi |
更底层,采样率诡异 |
wavein |
老古董 |
麦克风录音 = DirectShow = dshow
二、先确认你的 FFmpeg 能行
ffmpeg -hide_banner -devices
看到 D后有 dshow,说明 libavdevice 编进去了:
Devices:
D. = Demuxer
---
D dshow DirectShow input device

再看看有哪些麦克风:
ffmpeg -list_devices true -f dshow -i dummy

输出里找:
[dshow @ xxx] "麦克风阵列 (适用于数字麦克风的英特尔® 智音技术)" (audio)
名字要原样复制,中文也没事,但要引号包住。
三、最简命令行版
ffmpeg -f dshow -i audio="Microphone (Realtek Audio)" ^
-t 5 ^
-f s16le -ar 44100 -ac 2 ^
out.pcm
用 Audacity 打开 PCM:
-
Signed 16-bit PCM
-
Little Endian
-
44100 Hz
-
Stereo
能听 → 代码一定行
四、C/C++(FFmpeg 6 API)最小录音流程
核心思路
av_find_input_format("dshow")
↓
avformat_open_input(audio=...)
↓
av_read_frame → AVPacket
↓
直接写 packet.data(PCM)
dshow 默认输出就是 交错 PCM packet,不用 filter 也能直接落盘。
五、完整可编译示例代码(Windows / FFmpeg 6)
extern "C" {
#include <libavdevice/avdevice.h>
#include <libavformat/avformat.h>
}
int main()
{
AVFormatContext* fmt_ctx = nullptr;
AVInputFormat* ifmt = av_find_input_format("dshow");
const char* dev_name = "audio=Microphone (Realtek Audio)";
if (avformat_open_input(&fmt_ctx, dev_name, ifmt, nullptr) < 0) {
printf("open mic failed\n");
return -1;
}
FILE* fp = fopen("mic.pcm", "wb");
AVPacket pkt;
int count = 0;
while (av_read_frame(fmt_ctx, &pkt) >= 0 && count < 220) { // ~5s @44k
fwrite(pkt.data, 1, pkt.size, fp);
av_packet_unref(&pkt);
count++;
}
fclose(fp);
avformat_close_input(&fmt_ctx);
return 0;
}
六、PCM 参数是谁决定的?
dshow 默认给你:
| 参数 | 值 |
|---|---|
| sample_fmt | s16 |
| rate | 44100 |
| ch | 2 |
| layout | stereo |
| packing | interleaved |
packet.data 就是裸 PCM
如果你想改:
AVDictionary* opts = nullptr;
av_dict_set(&opts, "sample_rate", "48000", 0);
av_dict_set(&opts, "channels", "1", 0);
avformat_open_input(&fmt_ctx, dev_name, ifmt, &opts);
有些声卡 只认特定组合,失败就回退默认。
七、为什么不用 swr_convert?
你现在是:
麦克风 → dshow → PCM packet → 文件
链路里:
-
无 resample
-
无 latency
-
CPU ≈ 0
只有两种理由碰 swresample:
-
要 float / s32
-
重采样成 AAC / OPUS
否则:裸写文件就行
八、常见坑(Windows + FFmpeg 专属)
中文设备名乱码
UTF-8 源码 + MSVC / mingw-w64 都能过
用 audio="...",别手敲空格
打开成功但没数据
-
麦克风被独占(Teams / Chrome)
-
隐私设置没开"允许桌面应用访问麦克风"
录出来全是杂音
-
Audacity 声道数选错
-
用
s32le打开s16le
九、进阶路线
| 需求 | 下一步 |
|---|---|
| 边录边播 | abuffer → aformat → sink |
| 存 WAV | 写 44-byte header |
| 实时推流 | encode opus → RTP |
| Qt UI | QThread + av_read_frame |
| 低延迟 | wasapi+ exclusive |
十、总结
FFmpeg 6 + Windows 麦克风 = libavdevice + dshow + avformat_open_input + av_read_frame,PCM 直接落盘;不折腾 WASAPI、不碰 WinMM,5 分钟就能录到能用的音频。