命令行方式采集

ffmpeg在windows下查看设备的命令:
ffmpeg -list_devices true -f dshow -i dummy
音频采集:

  1. ffmpeg -f dshow -i audio="麦克风 (Realtek(R) Audio)" out.mp3
  2. ffmpeg -f dshow -i audio="麦克风 (Realtek(R) Audio)" -acodec aac out.aac
  3. ffmpeg -f dshow -i audio="麦克风 (Realtek(R) Audio)" -ar 16000 -ac 1 out.wav

ffplay播放yuv:

  1. ffplay -i F:\virtual-code\yuv_encode.c\video.yuv -pix_fmt yuv420p -s 1280x720

调用ffmpeg接口采集

  1. //采集windows下的麦克风数据, 并保存pcm文件
  2. //需要注意的两个点:
  3. //1、给avformat_open_input传入设备文件名时对文件名的格式有要求,故做了文件名的字符格式转换
  4. //2、采集设备下的音频数据时,设置采样参数无效,猜测是每个设备会有自己固定的采样参数
  5. #include <iostream>
  6. #include <strsafe.h>
  7. #define __STDC_CONSTANT_MACROS
  8. extern "C"
  9. {
  10. #include "libavutil/avutil.h"
  11. #include "libavdevice/avdevice.h"
  12. #include "libswscale/swscale.h"
  13. #include "libswresample/swresample.h"
  14. #include <stdio.h>
  15. }
  16. #ifdef _MSC_VER
  17. #include <tchar.h>
  18. #include <dshow.h>
  19. #include <atlcomcli.h>
  20. #pragma comment(lib, "Strmiids.lib")
  21. #endif
  22. void Convert(const char* strIn, char* strOut, int sourceCodepage, int targetCodepage)
  23. {
  24. //LPCTSTR
  25. LPCTSTR pStr = (LPCTSTR)strIn;
  26. int len = lstrlen(pStr);
  27. int unicodeLen = MultiByteToWideChar(sourceCodepage, 0, strIn, -1, NULL, 0);
  28. wchar_t* pUnicode = NULL;
  29. pUnicode = new wchar_t[unicodeLen + 1];
  30. memset(pUnicode, 0, (unicodeLen + 1) * sizeof(wchar_t));
  31. MultiByteToWideChar(sourceCodepage, 0, strIn, -1, (LPWSTR)pUnicode, unicodeLen);
  32. BYTE* pTargetData = NULL;
  33. int targetLen = WideCharToMultiByte(targetCodepage, 0, (LPWSTR)pUnicode, -1, (char*)pTargetData, 0, NULL, NULL);
  34. pTargetData = new BYTE[targetLen + 1];
  35. memset(pTargetData, 0, targetLen + 1);
  36. WideCharToMultiByte(targetCodepage, 0, (LPWSTR)pUnicode, -1, (char*)pTargetData, targetLen, NULL, NULL);
  37. lstrcpy((LPSTR)strOut, (LPCSTR)pTargetData);
  38. delete pUnicode;
  39. delete pTargetData;
  40. }
  41. void Get_Capture_Audio_Devices_Info(char* name)
  42. {
  43. #ifdef _MSC_VER
  44. CoInitialize(NULL);
  45. CComPtr<ICreateDevEnum> pCreateDevEnum;
  46. HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pCreateDevEnum);
  47. CComPtr<IEnumMoniker> pEm;
  48. hr = pCreateDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEm, 0);
  49. if (hr != NOERROR) {
  50. return;
  51. }
  52. pEm->Reset();
  53. ULONG cFetched;
  54. IMoniker* pM = NULL;
  55. while (hr = pEm->Next(1, &pM, &cFetched), hr == S_OK)
  56. {
  57. IPropertyBag* pBag = 0;
  58. hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pBag);
  59. if (SUCCEEDED(hr))
  60. {
  61. VARIANT var;
  62. var.vt = VT_BSTR;
  63. hr = pBag->Read(L"FriendlyName", &var, NULL); //还有其他属性,像描述信息等等...
  64. if (hr == NOERROR)
  65. {
  66. char str[128];
  67. //获取设备名称
  68. WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, name, 128, "", NULL);
  69. SysFreeString(var.bstrVal);
  70. }
  71. pBag->Release();
  72. }
  73. pM->Release();
  74. }
  75. pCreateDevEnum = NULL;
  76. pEm = NULL;
  77. #else
  78. memcpy(name, "default", strlen("default") + 1);
  79. #endif
  80. }
  81. int main()
  82. {
  83. int ret = 0;
  84. AVFormatContext* fmt_ctx = NULL;
  85. AVDictionary* options = NULL;
  86. char errors[1024] = { 0 };
  87. char device_name[256] = { 0 };
  88. char file_name[256] = "collection.pcm";
  89. char name[128] = { 0 };
  90. char name_utf8[128] = { 0 };
  91. //设置输入的字体,没有这部分会报错 //Immediate exit requested
  92. Get_Capture_Audio_Devices_Info(name);
  93. Convert(name, name_utf8, CP_ACP, CP_UTF8);
  94. sprintf(device_name, "audio=%s", name_utf8);
  95. printf("device_name:%s\n", device_name);
  96. av_register_all();
  97. avdevice_register_all();
  98. #if 0 //这里设置采样参数无效 我电脑上的采样参数为 双通道 采样率-44100 采样位数-s16le
  99. //ffplay 播放音频命令 ffplay -ar 44100 -f s16le -channels 2 -i collection.pcm
  100. char option_key[] = "ar";
  101. char option_value[] = "44100";
  102. av_dict_set(&options, option_key, option_value, 0);
  103. char option_key1[] = "ac";
  104. char option_value1[] = "2";
  105. av_dict_set(&options, option_key1, option_value1, 0);
  106. #endif
  107. AVInputFormat* in_format = av_find_input_format("dshow");
  108. if (in_format == NULL)
  109. {
  110. printf("av_find_input_format error\n");
  111. }
  112. //return 0;
  113. //fmt_ctx = avformat_alloc_context();
  114. if ((ret = avformat_open_input(&fmt_ctx, device_name, in_format, NULL)) != 0)
  115. //if ((ret = avformat_open_input(&fmt_ctx, device_name, in_format, &options)) != 0)
  116. {
  117. av_strerror(ret, errors, 1024);
  118. printf("Failed to open audio device, [%s][%d]\n", errors, ret);
  119. return -1;
  120. }
  121. AVPacket* pkt = av_packet_alloc();
  122. av_init_packet(pkt);
  123. FILE* out_file = fopen(file_name, "wb+");
  124. while (!av_read_frame(fmt_ctx, pkt))
  125. {
  126. printf("Size of collected data %d\n", pkt->size);
  127. fwrite(pkt->data, 1, pkt->size, out_file);
  128. fflush(out_file);
  129. av_packet_unref(pkt);
  130. }
  131. av_packet_free(&pkt);
  132. avformat_close_input(&fmt_ctx);
  133. //avformat_free_context(fmt_ctx);
  134. fclose(out_file);
  135. return 0;
  136. }

```