不要轻易使用ffmpeg的audio_device_number来设置音频设备

时间:2024-02-19 15:35:58

最近项目中需要使用ffmpeg实现录音功能,使用的ffmpeg-3.4.4的库,根据源代码dshow.c中的定义

{ "audio_device_number", "set audio device number for devices with same name (starts at 0)", OFFSET(audio_device_number), AV_OPT_TYPE_INT, {.i64 = 0}, 0, INT_MAX, DEC },

在PC机存在两个麦克风设备的场合,添加一个[录音设备选择]对话框,可供用户选择。

打个比方:目前的PC机存在两个音频输入设备:

  • 0:麦克风 (HD Webcam C270)
  • 1:麦克风 (Realtek High Definition Audio)

备注:

  • 0号采集设备可以采集音频与视频,不能播放音频;1号采集设备仅可以采集音频,可以播放音频。
  • PC机设备播放设备只有1个,那就是:麦克风 (Realtek High Definition Audio),即为0号播放设备。
  • 音频采集设备的序号与音频播放设备的序号很可能不一致。

如果指定 0号采集设备:麦克风 (HD Webcam C270)作为音频采集设备,简化代码如下:

char *pchDeviceName = "麦克风 (HD Webcam C270)";
AVInputFormat        *m_pAudioInputFormat = av_find_input_format("dshow");
AVDictionary *options = NULL;
av_dict_set(&options, "audio_device_number", "0", 0);
char str_device_gb2312_name[128];
_snprintf(str_device_gb2312_name, sizeof(str_device_gb2312_name), "audio=%s", pchDeviceName);
char *pchUtfName = gb2312_to_utf8(str_device_gb2312_name);
int ret = -1;
AVFormatContext *m_pAudioFmtCtx = avformat_alloc_context();
ret = avformat_open_input(&m_pAudioFmtCtx, pchUtfName, m_pAudioInputFormat, &options);

这时avformat_open_input函数成功,推测是因为0号音频采集设备与0号音频播放设备都存在所致。

如果指定 1号采集设备:麦克风 (Realtek High Definition Audio)作为音频采集设备,简化代码如下:

char *pchDeviceName = "麦克风 (Realtek High Definition Audio)";
AVInputFormat        *m_pAudioInputFormat = av_find_input_format("dshow");
AVDictionary *options = NULL;
av_dict_set(&options, "audio_device_number", "1", 0);
char str_device_gb2312_name[128];
_snprintf(str_device_gb2312_name, sizeof(str_device_gb2312_name), "audio=%s", pchDeviceName);
char *pchUtfName = gb2312_to_utf8(str_device_gb2312_name);
int ret = -1;
AVFormatContext *m_pAudioFmtCtx = avformat_alloc_context();
ret = avformat_open_input(&m_pAudioFmtCtx, pchUtfName, m_pAudioInputFormat, &options);

这时avformat_open_input函数失败原因是I/O fail,推测是因为1号音频采集设备存在但0号音频播放设备不存在所致。

此时的ffmpeg日志如下:

2019-12-10 13:57:21 076[ERR] Could not find audio only device with name [麦克风 (Realtek High Definition Audio)] among source devices of type audio.
2019-12-10 13:57:21 077[INF] Searching for audio device within video devices for 麦克风 (Realtek High Definition Audio)
2019-12-10 13:57:21 090[ERR] Could not find audio only device with name [麦克风 (Realtek High Definition Audio)] among source devices of type video.

  

解决方法如下(不指定音频设备序号,仅仅指定音频设备名称):

char *pchDeviceName = "麦克风 (Realtek High Definition Audio)";
AVInputFormat        *m_pAudioInputFormat = av_find_input_format("dshow");
AVDictionary *options = NULL;
char str_device_gb2312_name[128];
_snprintf(str_device_gb2312_name, sizeof(str_device_gb2312_name), "audio=%s", pchDeviceName);
char *pchUtfName = gb2312_to_utf8(str_device_gb2312_name);
int ret = -1;
AVFormatContext *m_pAudioFmtCtx = avformat_alloc_context();
ret = avformat_open_input(&m_pAudioFmtCtx, pchUtfName, m_pAudioInputFormat, &options);