ffmpeg录制系统声音

这篇博客介绍了如何使用Windows API直接从声卡采集声音数据,并结合FFmpeg进行编码。通过创建IAudioClient和IAudioCaptureClient接口实例,实现了音频数据的实时捕获。然后利用Swresample库将原始数据转换为平面格式(AV_SAMPLE_FMT_FLTP),并进行编码。程序在主线程外启动两个线程分别负责音频数据的捕获和编码写入,确保了录音过程的顺畅。

之前本人写过ffmpeg录制系统声音的博客,但是用到的设备名称叫做virtual-audio-capturer,需要实现安装一个软件,ffmpeg才能找到这个设备,很不方便;
今天用windows api采集声卡声音,进行声卡数据抓取,然后放入ffmpeg进行编码。
关于声卡的数据采集api,可以参看下面博客:
声卡数据采集

本人从声卡中获取到的格式是:
采样率:48000
采样位数:32
通道数:双通道

最终编码时,编码后的的格式为AV_SAMPLE_FMT_FLTP(平面格式),代码如下:

av_opt_set_channel_layout(m_pAudioConvertCtx, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0);
av_opt_set_channel_layout(m_pAudioConvertCtx, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0);
av_opt_set_int(m_pAudioConvertCtx, "in_sample_rate", m_formatex.Format.nSamplesPerSec, 0);
av_opt_set_int(m_pAudioConvertCtx, "out_sample_rate", 48000, 0);
av_opt_set_sample_fmt(m_pAudioConvertCtx, "in_sample_fmt", AV_SAMPLE_FMT_S32, 0);
av_opt_set_sample_fmt(m_pAudioConvertCtx, "out_sample_fmt", AV_SAMPLE_FMT_FLTP, 0);

相应的采样转换代码如下:

uint8_t *audio_buf[2] = {
   
    0 };
audio_buf[0] = (uint8_t *)frame_mic_encode->data[0];
audio_buf[1] = (uint8_t *)frame_mic_encode->data[1];

int nb = swr_convert(m_pAudioConvertCtx, audio_buf, num_frames_to_read, (const uint8_t**)&p_audio_data, num_frames_to_read);

其中p_audio_data为从声卡中获取的数据buffer,num_frames_to_read为数据长度(以每个采样为单位)
由于编码格式是平面格式,所以定义了audio_buf[2]。

如果系统未播放任何声音,则num_frames_to_read为0,这种情况,本人尚未处理。本人给出的例子是系统中播放一段音乐时的处理。

main函数如下所示:

#include <iostream>
#include "GetSystemAudio.h"

int main()
{
   
   
	CGetSystemAudio cCGetSystemAudio;
	cCGetSystemAudio.SetSavePath("E:\\learn\\ffmpeg\\FfmpegTest\\x64\\Release");
	cCGetSystemAudio.StartCapture();
	Sleep(30000);
	cCGetSystemAudio.StopCapture();
	return 0;
}

可以看出,录了30秒。

GetSystemAudio.h的内容如下:

#pragma once
#include <string>
#include <combaseapi.h>
#include <mmdeviceapi.h>
#include <audioclient.h>


#ifdef	__cplusplus
extern "C"
{
   
   
#endif
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libswresample/swresample.h"
#include "libavdevice/avdevice.h"
#include "libavutil/audio_fifo.h"
#include "libavutil/avutil.h"
#include "libavutil/fifo.h"
#include "libavutil/frame.h"
#include "libavutil/imgutils.h"

#include "libavfilter/avfilter.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"


#pragma comment(lib, "avcodec.lib")
#pragma comment(lib, "avformat.lib")
#pragma comment(lib, "avutil.lib")
#pragma comment(lib, "avdevice.lib")
#pragma comment(lib, "avfilter.lib")
#pragma comment(lib, "postproc.lib")
#pragma comment(lib, "swresample.lib")
#pragma comment(lib, "swscale.lib")


#ifdef __cplusplus
};
#endif

class CGetSystemAudio
{
   
   
public:
	CGetSystemAudio();
	~CGetSystemAudio();
public:
	void SetSavePath(std::string strPath);
	int StartCapture();
	void StopCapture();
	int OpenOutPut();
private:
	static DWORD WINAPI AudioSystemCaptureProc(LPVOID lpParam);
	void AudioSystemCapture();

	static DWORD WINAPI AudioSystemWriteProc(LPVOID lpParam);
	void AudioSystemWrite();

	HRESULT IsFormatSupported(IAudioClient *audioClient);
private:
	std::string m_strRecordPath;
	bool m_bRecord;
	IAudioClient *pAudioClient = nullptr;
	IAudioCaptureClient *pAudioCaptureClient = nullptr;
	WAVEFORMATEXTENSIBLE m_formatex
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值