命令行方式采集
ffmpeg在windows下查看设备的命令:ffmpeg -list_devices true -f dshow -i dummy
音频采集:
ffmpeg -f dshow -i audio="麦克风 (Realtek(R) Audio)" out.mp3
ffmpeg -f dshow -i audio="麦克风 (Realtek(R) Audio)" -acodec aac out.aac
ffmpeg -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_MACROS
extern "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")
#endif
void Convert(const char* strIn, char* strOut, int sourceCodepage, int targetCodepage)
{
//LPCTSTR
LPCTSTR 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_VER
CoInitialize(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;
#else
memcpy(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 requested
Get_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.pcm
char 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);
#endif
AVInputFormat* 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;
}
```