基于FFmpeg源码实现一个简单的混音demo,把文件a和文件b的音频混为一个音频流输出并存为文件

这个博客通过FFmpeg源码展示了如何将两个音频文件(文件a和文件b)的音频流混合在一起,并输出为新的音频文件。内容包括一个简单的混音demo,仅处理每个输入文件的第一个音频流。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 /*
*一个简单的混音demo,把文件a和文件b的音频混为一个音频流输出并存为文件,只处理每个文件的第一个音频流
*/

 命令行实现:

ffmpeg -i INPUT1 -i INPUT2 -i INPUT3 -filter_complex amix=inputs=3:duration=first:dropout_transition=3 OUTPUT

 

inputs
The number of inputs. If unspecified, it defaults to 2.//输入的数量,如果没有指明,默认为2.

duration
How to determine the end-of-stream.//决定了流的结束

longest
The duration of the longest input. (default)//最长输入的持续时间

shortest
The duration of the shortest input.//最短输入的持续时间

first
The duration of the first input.//第一个输入的持续时间

dropout_transition
The transition time, in seconds, for volume renormalization when an input stream ends. The default value is 2 seconds.
//输入流结束时(音频)容量重整化的转换时间(以秒为单位)。 默认值为2秒。
extern "C"
{
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libavdevice/avdevice.h"
#include "libavfilter/avfilter.h"
#include "libavfilter/avfiltergraph.h"
#include "libavfilter/buffersink.h"
#include "libavfilter/buffersrc.h"
#include "libavutil/audio_fifo.h"
#include "libavutil/avutil.h"
#include "libavutil/fifo.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")

#include <windows.h>
#include <conio.h>
#include <time.h>
#include<iostream>
using namespace std;

enum CaptureState
{
	PREPARED,
	RUNNING,
	STOPPED,
	FINISHED
};

 typedef struct BufferSourceContext {
 	const AVClass    *bscclass;
 	AVFifoBuffer     *fifo;
 	AVRational        time_base;     ///< time_base to set in the output link
 	AVRational        frame_rate;    ///< frame_rate to set in the output link
 	unsigned          nb_failed_requests;
 	unsigned          warning_limit;
 
 	/* video only */
 	int               w, h;
 	enum AVPixelFormat  pix_fmt;
 	AVRational        pixel_aspect;
 	char              *sws_param;
 
 	AVBufferRef *hw_frames_ctx;
 
 	/* audio only */
 	int sample_rate;
 	enum AVSampleFormat sample_fmt;
 	int channels;
 	uint64_t channel_layout;
 	char    *channel_layout_str;
 
 	int got_format_from_params;
 	int eof;
 } BufferSourceContext;

AVFormatContext* _fmt_ctx_spk = NULL;
AVFormatContext* _fmt_ctx_mic = NULL;
AVFormatContext* _fmt_ctx_out = NULL;
int _index_spk = -1;
int _index_mic = -1;
int _index_a_out = -1;

AVFilterGraph* _filter_graph = NULL;
AVFilterContext* _filter_ctx_src_spk = NULL;
AVFilterContext* _filter_ctx_src_mic = NULL;
AVFilterContext* _filter_ctx_sink = NULL;

CaptureState _state = CaptureState::PREPARED;

CRITICAL_SECTION _section_spk;
CRITICAL_SECTION _section_mic;
AVAudioFifo* _fifo_spk = NULL;
AVAudioFifo* _fifo_mic = NULL;

void InitRecorder()
{
	av_register_all();//注册编解码器
	avdevice_register_all();
	avfilter_register_all();
}
//构建输入封装器上下文input avformat
int OpenSpeakerInput(char* inputForamt, char* url)
{
	AVInputFormat* ifmt = av_find_input_format(inputForamt);
	AVDictionary* opt1 = NULL;
	av_dict_set(&opt1, "rtbufsize", "10M", 0);

	int ret = 0;
	ret = avformat_open_input(&_fmt_ctx_spk, url, ifmt, &opt1);
	if (ret < 0)
	{
		printf("Speaker: failed to call avformat_open_input\n");
		return -1;
	}
	ret = avformat_find_stream_info(_fmt_ctx_spk, NULL);
	if (ret < 0)
	{
		printf("Speaker: failed to call avformat_find_stream_info\n");
		return -1;
	}
	for (int i = 0; i < _fmt_ctx_spk->nb_streams; i++)
	{
		if (_fmt_ctx_spk->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO)
		{
			_index_spk = i;
			break;
		}
	}
	if (_index_spk < 0)
	{
		printf("Speaker: negative audio index\n");
		return -1;
	}
	AVCodecContext* codec_ctx = _fmt_ctx_spk->streams[_index_spk]->codec;
	AVCodec* codec = avcodec_find_decoder(codec_ctx->codec_id);
	if (codec == NULL)
	{
		printf("Speaker: null audio decoder\n");
		return -1;
	}
	ret = avcodec_open2(codec_ctx, codec, NULL);
	if (ret < 0)
	{
		printf("Speaker: failed to call avcodec_open2\n");
		return -1;
	}
	av_dump_format(_fmt_ctx_spk, _index_spk, url, 0);

	return 0;
}
//输入音频文件
int OpenMicrophoneInput(char* inputForamt, char* url)
{
	AVInputFormat* ifmt = av_find_input_format(inputForamt);
	AVDictionary* opt1 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值