ffmpeg录制桌面视频和麦克风音频(音视频同步)

本文介绍使用FFmpeg实现音视频同步录制的方法,通过整合桌面录制和麦克风录音功能,实现高质量的音视频同步输出。文中详细介绍了如何配置FFmpeg版本、设置参数及编码格式等关键步骤。

vs版本:2017
ffmpeg版本号:
ffmpeg version N-102642-g864d1ef2fc Copyright © 2000-2021 the FFmpeg developers
built with gcc 8.1.0 (x86_64-win32-seh-rev0, Built by MinGW-W64 project)
configuration: --arch=x86_64 --prefix=/home/ffmpeg_static_x64 --disable-debug
libavutil 57. 0.100 / 57. 0.100
libavcodec 59. 1.100 / 59. 1.100
libavformat 59. 2.101 / 59. 2.101
libavdevice 59. 0.100 / 59. 0.100
libavfilter 8. 0.101 / 8. 0.101
libswscale 6. 0.100 / 6. 0.100
libswresample 4. 0.100 / 4. 0.100

关于ffmpeg的lib和dll,本人在csdn上上传了相关资源,并且免费下载。

本人之前写过ffmpeg录制麦克风声音ffmpeg录制桌面(队列方式)

现在将两者合入到一起,实现音视频同步,完整代码下面有给出,这里不做赘述,关于代码的理解,读者可以参看我前两篇博客。

半年前,我在写音视频同步的时候,参考过其他人的博客,其中最重要的是ffmpeg实现录屏+录音
,结果短时期未能成功,继而做其他事情去了。

如今半年过去,当我重新开始学ffmpeg时,我首先参考的是ffmpeg本身的demo,位于doc/examples文件夹下面,其中有个muxing.c,这个是关于音视频混合的例子,比较简单,容易懂,而半年前看别人的博客,对应的ffmpeg的版本比较旧,旧版本的ffmpeg里面有很多不建议的变量和方法,称之为deprecated,学习复杂度会高。新版本将deprecated的函数和变量去掉了,减少了学习的复杂性。

将新版本ffmpeg里面的demo看完后,然后再看ffmpeg实现录屏+录音,就会觉得帮助不小,多说一句,对于视频和音频的平面(planar)和打包(packed)模式,建议大家先了解下,对了解音视频至关重要。

// FfmpegAudioTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//

#include <Windows.h>
#include <conio.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/imgutils.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, "avfilter.lib")
	//#pragma comment(lib, "postproc.lib")
#pragma comment(lib, "swresample.lib")
#pragma comment(lib, "swscale.lib")
#ifdef __cplusplus
};
#endif




AVFormatContext	*pFormatCtx_Audio = NULL, *pFormatCtx_Out = NULL;
AVCodecContext *pReadCodecContext_Audio = NULL;

AVFormatContext	*pFormatCtx_Video = NULL;
AVCodecContext	*pReadCodecCtx_Video = NULL;
AVCodec			*pReadCodec_Video = NULL;

int VideoIndex = 0;
int AudioIndex_mic = 0;

AVCodecContext	*pCodecEncodeCtx_Audio = NULL;
AVCodec			*pCodecEncode_Audio = NULL;

AVCodecContext	*pCodecEncodeCtx_Video = NULL;
AVCodec			*pCodecEncode_Video = NULL;


AVFifoBuffer	*fifo_video = NULL;
AVAudioFifo		*fifo_audio_mic = NULL;

SwrContext *audio_convert_ctx = NULL;
SwsContext *img_convert_ctx = NULL;
int frame_size = 0;

uint8_t *picture_buf = NULL, *frame_buf = NULL;

int iPicCount = 0;

int64_t cur_pts_v = 0;
int64_t cur_pts_a = 0;


CRITICAL_SECTION VideoSection;
CRITICAL_SECTION AudioSection;

DWORD WINAPI AudioMicCapThreadProc(LPVOID lpParam);
DWORD WINAPI ScreenCapThreadProc(LPVOID lpParam);

static char *dup_wchar_to_utf8(const wchar_t *w)
{
   
   
	char *s = NULL;
	int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);
	s = (char *)av_malloc(l);
	if (s)
		WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);
	return s;
}


/* just pick the highest supported samplerate */
static int select_sample_rate(const AVCodec *codec)
{
   
   
	const int *p;
	int best_samplerate = 0;

	if (!codec->supported_samplerates)
		return 44100;

	p = codec->supported_samplerates;
	while (*p) {
   
   
		if (!best_samplerate || abs(44100 - *p) < abs(44100 - best_samplerate))
			best_samplerate = *p;
		p++;
	}
	return best_samplerate;
}




/* select layout with the highest channel count */
static int select_channel_layout(const AVCodec *codec)
{
   
   
	const uint64_t *p;
	uint64_t best_ch_layout = 0;
	int best_nb_channels = 0;

	if (!codec->channel_layouts)
		return AV_CH_LAYOUT_STEREO;

	p = codec->channel_layouts;
	while (*p) {
   
   
		int nb_channels = av_get_channel_layout_nb_channels(*p);

		if (nb_channels > best_nb_channels) {
   
   
			best_ch_layout = *p;
			best_nb_channels = nb_channels;
		}
		p++;
	}
	return best_ch_layout;
}


int OpenVideoCapture()
{
   
   
	const AVInputFormat *ifmt = av_find_input_format("gdigrab");
	//这里可以加参数打开,例如可以指定采集帧率
	AVDictionary *options = NULL;
	av_dict_set(&options, "framerate", "25", NULL);
	av_dict_set(&options, "probesize", "50000000", NULL);
	//av_dict_set(&options,"offset_x","20",0);
	//The distance from the top edge of the screen or desktop
	//av_dict_set(&options,"offset_y","40",0);
	//Video frame size. The default is to capture the full screen
	//av_dict_set(&options,"video_size","320x240",0);
	if (avformat_open_input(&pFormatCtx_Video, "desktop", ifmt, &options) != 0)
	{
   
   
		printf("Couldn't open input stream.(无法打开视频输入流)\n");
		return -
评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值