命令行方式采集
ffmpeg在windows下查看设备的命令:ffmpeg -list_devices true -f dshow -i dummy
音频采集:
ffmpeg -f dshow -i audio="麦克风 (Realtek(R) Audio)" out.mp3ffmpeg -f dshow -i audio="麦克风 (Realtek(R) Audio)" -acodec aac out.aacffmpeg -f dshow -i audio="麦克风 (Realtek(R) Audio)" -ar 16000 -ac 1 out.wav
ffplay播放yuv:
ffplay -i F:\virtual-code\yuv_encode.c\video.yuv -pix_fmt yuv420p -s 1280x720
调用ffmpeg接口采集
//采集windows下的麦克风数据, 并保存pcm文件//需要注意的两个点://1、给avformat_open_input传入设备文件名时对文件名的格式有要求,故做了文件名的字符格式转换//2、采集设备下的音频数据时,设置采样参数无效,猜测是每个设备会有自己固定的采样参数#include <iostream>#include <strsafe.h>#define __STDC_CONSTANT_MACROSextern "C"{#include "libavutil/avutil.h"#include "libavdevice/avdevice.h"#include "libswscale/swscale.h"#include "libswresample/swresample.h"#include <stdio.h>}#ifdef _MSC_VER#include <tchar.h>#include <dshow.h>#include <atlcomcli.h>#pragma comment(lib, "Strmiids.lib")#endifvoid Convert(const char* strIn, char* strOut, int sourceCodepage, int targetCodepage){//LPCTSTRLPCTSTR pStr = (LPCTSTR)strIn;int len = lstrlen(pStr);int unicodeLen = MultiByteToWideChar(sourceCodepage, 0, strIn, -1, NULL, 0);wchar_t* pUnicode = NULL;pUnicode = new wchar_t[unicodeLen + 1];memset(pUnicode, 0, (unicodeLen + 1) * sizeof(wchar_t));MultiByteToWideChar(sourceCodepage, 0, strIn, -1, (LPWSTR)pUnicode, unicodeLen);BYTE* pTargetData = NULL;int targetLen = WideCharToMultiByte(targetCodepage, 0, (LPWSTR)pUnicode, -1, (char*)pTargetData, 0, NULL, NULL);pTargetData = new BYTE[targetLen + 1];memset(pTargetData, 0, targetLen + 1);WideCharToMultiByte(targetCodepage, 0, (LPWSTR)pUnicode, -1, (char*)pTargetData, targetLen, NULL, NULL);lstrcpy((LPSTR)strOut, (LPCSTR)pTargetData);delete pUnicode;delete pTargetData;}void Get_Capture_Audio_Devices_Info(char* name){#ifdef _MSC_VERCoInitialize(NULL);CComPtr<ICreateDevEnum> pCreateDevEnum;HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void**)&pCreateDevEnum);CComPtr<IEnumMoniker> pEm;hr = pCreateDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEm, 0);if (hr != NOERROR) {return;}pEm->Reset();ULONG cFetched;IMoniker* pM = NULL;while (hr = pEm->Next(1, &pM, &cFetched), hr == S_OK){IPropertyBag* pBag = 0;hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pBag);if (SUCCEEDED(hr)){VARIANT var;var.vt = VT_BSTR;hr = pBag->Read(L"FriendlyName", &var, NULL); //还有其他属性,像描述信息等等...if (hr == NOERROR){char str[128];//获取设备名称WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, name, 128, "", NULL);SysFreeString(var.bstrVal);}pBag->Release();}pM->Release();}pCreateDevEnum = NULL;pEm = NULL;#elsememcpy(name, "default", strlen("default") + 1);#endif}int main(){int ret = 0;AVFormatContext* fmt_ctx = NULL;AVDictionary* options = NULL;char errors[1024] = { 0 };char device_name[256] = { 0 };char file_name[256] = "collection.pcm";char name[128] = { 0 };char name_utf8[128] = { 0 };//设置输入的字体,没有这部分会报错 //Immediate exit requestedGet_Capture_Audio_Devices_Info(name);Convert(name, name_utf8, CP_ACP, CP_UTF8);sprintf(device_name, "audio=%s", name_utf8);printf("device_name:%s\n", device_name);av_register_all();avdevice_register_all();#if 0 //这里设置采样参数无效 我电脑上的采样参数为 双通道 采样率-44100 采样位数-s16le//ffplay 播放音频命令 ffplay -ar 44100 -f s16le -channels 2 -i collection.pcmchar option_key[] = "ar";char option_value[] = "44100";av_dict_set(&options, option_key, option_value, 0);char option_key1[] = "ac";char option_value1[] = "2";av_dict_set(&options, option_key1, option_value1, 0);#endifAVInputFormat* in_format = av_find_input_format("dshow");if (in_format == NULL){printf("av_find_input_format error\n");}//return 0;//fmt_ctx = avformat_alloc_context();if ((ret = avformat_open_input(&fmt_ctx, device_name, in_format, NULL)) != 0)//if ((ret = avformat_open_input(&fmt_ctx, device_name, in_format, &options)) != 0){av_strerror(ret, errors, 1024);printf("Failed to open audio device, [%s][%d]\n", errors, ret);return -1;}AVPacket* pkt = av_packet_alloc();av_init_packet(pkt);FILE* out_file = fopen(file_name, "wb+");while (!av_read_frame(fmt_ctx, pkt)){printf("Size of collected data %d\n", pkt->size);fwrite(pkt->data, 1, pkt->size, out_file);fflush(out_file);av_packet_unref(pkt);}av_packet_free(&pkt);avformat_close_input(&fmt_ctx);//avformat_free_context(fmt_ctx);fclose(out_file);return 0;}
```
