用ffmpeg实现录音

1、概述

2、代码

/*
*最简单的录音程序
*缪国凯 MK
*[email protected]
*本程序实现采集麦克风音频数据,压制为aac
*2015-6-19
*/

#include "stdafx.h"
#include <windows.h>
#include <DShow.h>
#include <comutil.h>
#pragma comment(lib,"Strmiids")
#pragma comment(lib,"comsuppw.lib")
#include <conio.h>
#pragma comment(lib,"winmm")
#define	SAFE_RELEASE(x)	{if(x != NULL) x->Release();x=NULL;}

#ifdef __cplusplus
extern "C"
{
#endif
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavdevice/avdevice.h"
#include "libavutil/audio_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, "postproc.lib")
//#pragma comment(lib, "swresample.lib")
//#pragma comment(lib, "swscale.lib")
#ifdef __cplusplus
};
#endif

_bstr_t	strDeviceName;

static char *dup_wchar_to_utf8(wchar_t *w);

int _tmain(int argc, _TCHAR* argv[])
{
	AVFormatContext		*	pFmtCtx = NULL, *ofmt_ctx_a = NULL;
	AVInputFormat		*	pAudioInputFmt = NULL;
	AVOutputFormat		*	pAudioOutputFmt = NULL;
	AVStream			*	pAudioStream = NULL;
	AVCodecContext		*	pOutputCodecCtx = NULL;
	AVCodecContext		*	pInputCodecCtx = NULL;
	AVCodec				*	pCodec = NULL;
	AVFrame				*	pAudioFrame = NULL;
	uint8_t				*	pFrameBuffer = NULL;
	int						iAudioIndex = -1;
	//注册FFMPEG库
	av_register_all();
	avdevice_register_all();

	//查找输入方式
	pAudioInputFmt =av_find_input_format("dshow");
	assert(pAudioInputFmt != NULL);
	//以Direct Show的方式打开设备,并将 输入方式 关联到格式上下文
	char * psDevName = dup_wchar_to_utf8(L"audio=麦克风 (Realtek High Definition Au");
	assert(avformat_open_input(&pFmtCtx,psDevName,pAudioInputFmt,NULL) == 0);

//	avformat_find_stream_info(pFmtCtx,NULL);

	if(avformat_find_stream_info(pFmtCtx,NULL)<0)
		return -1; 

	for(int i=0; i<pFmtCtx->nb_streams; i++)
	{
		if(pFmtCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO)
		{
			iAudioIndex=i;
			AVCodec *tmpCodec = avcodec_find_decoder(pFmtCtx->streams[i]->codec->codec_id);
			if(0 > avcodec_open2(pFmtCtx->streams[i]->codec, tmpCodec, NULL))
			{
				printf("can not find or open decoder!\n");
			}

			break;
		}
	}

	av_dump_format(pFmtCtx, 0, NULL, 0);

	avformat_alloc_output_context2(&ofmt_ctx_a, NULL, NULL, "abc.aac");

	pAudioStream = avformat_new_stream(ofmt_ctx_a, NULL);
	pAudioStream->codec->codec = avcodec_find_encoder(ofmt_ctx_a->oformat->audio_codec);

	pOutputCodecCtx = pAudioStream->codec;

	pOutputCodecCtx->sample_rate = pFmtCtx->streams[0]->codec->sample_rate;
	pOutputCodecCtx->channel_layout = ofmt_ctx_a->streams[0]->codec->channel_layout;
	pOutputCodecCtx->channels = av_get_channel_layout_nb_channels(pAudioStream->codec->channel_layout);
	if(pOutputCodecCtx->channel_layout == 0)
	{
		pOutputCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO;
		pOutputCodecCtx->channels = av_get_channel_layout_nb_channels(pOutputCodecCtx->channel_layout);

	}
	pOutputCodecCtx->sample_fmt = pAudioStream->codec->codec->sample_fmts[0];
	AVRational time_base={1, pAudioStream->codec->sample_rate};
	ofmt_ctx_a->streams[0]->time_base = time_base;
	//audioCodecCtx->time_base = time_base;

	pOutputCodecCtx->codec_tag = 0;
	if (ofmt_ctx_a->oformat->flags & AVFMT_GLOBALHEADER)
		pOutputCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;

	if (avcodec_open2(pOutputCodecCtx, pOutputCodecCtx->codec, 0) < 0)
	{
		//编码器打开失败,退出程序
		exit(0);
	}

	if (!(ofmt_ctx_a->oformat->flags & AVFMT_NOFILE))
	{
		if (avio_open(&ofmt_ctx_a->pb, "abc.aac", AVIO_FLAG_WRITE) < 0)
		{
			printf( "Could not open output file abc.aac");
		}
	}

	if (avformat_write_header(ofmt_ctx_a, NULL) < 0)
	{
		printf( "Error occurred when opening audio output file\n");
	}

	AVPacket pkt, pkt_out;

// 	FILE * fp = fopen("C:\\Users\\jk\\Desktop\\abc","wb+");
// 	assert(fp != NULL);
	AVFrame *frame;
	AVAudioFifo *fifo = NULL;
	fifo = av_audio_fifo_alloc(pOutputCodecCtx->sample_fmt,pOutputCodecCtx->channels,1);
	int frameIndex = 0;

	while (av_read_frame(pFmtCtx,&pkt) == 0 && _kbhit()==0)
	{
		int gotframe = -1;

		frame = av_frame_alloc();
		if (avcodec_decode_audio4(pFmtCtx->streams[iAudioIndex]->codec, frame, &gotframe, &pkt) < 0)
		{
			av_frame_free(&frame);
			printf("can not decoder a frame");
			break;
		}
		av_free_packet(&pkt);

		if (!gotframe)
		{
			continue;//没有获取到数据,继续下一次
		}

		//test write pcm
		if(0)
		{
			FILE *p = NULL;
			p = fopen("test.pcm", "a+b");
			int tempLenght = 2 * frame->nb_samples;//由于实验中知道这是16位深,所以才这么写
			uint8_t *tmpPtr = frame->data[0];
			if (NULL != p)
			{
				while(tempLenght > 0)
				{
					size_t temp = fwrite(tmpPtr, 1, tempLenght, p);
					tmpPtr+= temp;
					tempLenght = tempLenght - temp;
				}
				fclose(p);
			}
		}

		if (pFmtCtx->streams[iAudioIndex]->codec->sample_fmt != pOutputCodecCtx->sample_fmt
			|| pFmtCtx->streams[iAudioIndex]->codec->channels != pOutputCodecCtx->channels
			|| pFmtCtx->streams[iAudioIndex]->codec->sample_rate != pOutputCodecCtx->sample_rate)
		{
			//如果输入和输出的音频格式不一样 需要重采样,这里是一样的就没做
		}

		av_audio_fifo_realloc(fifo, av_audio_fifo_size(fifo) + frame->nb_samples);

		av_audio_fifo_write(fifo, (void **)frame->data, frame->nb_samples);

		//循环读取数据,直到buf里数据采样数不够
		while(av_audio_fifo_size(fifo) >= (pOutputCodecCtx->frame_size > 0 ? pOutputCodecCtx->frame_size : 1024))
		{
			av_frame_free(&frame);
			frame = av_frame_alloc();
			frame->nb_samples = pOutputCodecCtx->frame_size>0 ? pOutputCodecCtx->frame_size: 1024;
			frame->channel_layout = pOutputCodecCtx->channel_layout;
			frame->format = pOutputCodecCtx->sample_fmt;
			frame->sample_rate = pOutputCodecCtx->sample_rate;
			av_frame_get_buffer(frame, 0);

			av_audio_fifo_read(fifo, (void **)frame->data, (pOutputCodecCtx->frame_size > 0 ? pOutputCodecCtx->frame_size : 1024));
			av_init_packet(&pkt_out);
			//frame->pts = pFrame->pts;
			int got_picture = -1;
			pkt_out.data = NULL;
			pkt_out.size = 0;
			if (avcodec_encode_audio2(pOutputCodecCtx, &pkt_out, frame, &got_picture) < 0)
			{
				printf("can not decoder a frame");
			}
			av_frame_free(&frame);
			if (got_picture)
			{
				pkt_out.pts = frameIndex * pOutputCodecCtx->frame_size;
				pkt_out.dts = frameIndex * pOutputCodecCtx->frame_size;
				pkt_out.duration = pOutputCodecCtx->frame_size;
				av_write_frame(ofmt_ctx_a, &pkt_out);
				frameIndex++;
			}
		}
	}

	av_write_trailer(ofmt_ctx_a);

	avio_close(ofmt_ctx_a->pb);
	avformat_free_context(ofmt_ctx_a);

	//解初始化
	if (pFmtCtx != NULL)
	{
		avformat_free_context(pFmtCtx);
		pFmtCtx = NULL;
	}
	return 0;
}

static char *dup_wchar_to_utf8(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;
}

3、工程下载地址

http://download.csdn.net/detail/dancing_night/8822669

时间: 2024-09-30 11:52:43

用ffmpeg实现录音的相关文章

使用ffmpeg录音

在ubuntu下进行语音识别,就要录音啦 用ffmpeg录音简单- 方法: 开始找到了这个方法,但是不行呀,好像是没有这个oss吧. oss 是linux 下的声音相关的东西,与alsa 一样,不过oss 是商业的, 而/dev/dsp 是oss 用到的麦克的设备吧 ffmpeg -f oss -i /dev/dsp wheer.mp3 ffmpeg -f oss -i /dev/dsp -ar 8000 -ab 10200 wheer.amr 采用 alsa-oss 录制,就可以啦 ffmpe

ffmpeg实现录屏+录音

1.概述 最简单的基于FFmpeg的AVDevice例子(屏幕录制+声音采集),视频采用mpeg4编码,音频采用aac编码,并生成mp4文件,其中fifo是此程序的关键,此程序只是一个demo很多优化都没做,仅供参考. 2.代码 /** *最简单的基于FFmpeg的AVDevice例子(屏幕录制+声音采集),视频采用mpeg4编码,音频采用aac编码,并生成mp4文件 *缪国凯 MK *[email protected] */ #include "stdafx.h" #ifdef __

iOS开发系列--音频播放、录音、视频播放、拍照、视频录制

iOS开发系列--音频播放.录音.视频播放.拍照.视频录制 转载:http://www.cnblogs.com/kenshincui/p/4186022.html#avFoundationCamera --iOS多媒体 概览 随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像头的操作都提供了多套API.在今天的文章中将会对这些内容进行一一介绍: 音频 音

java利用ffmpeg将amr、caf转mp3格式

最近再做一个项目,要将手机APP上的文件上传到服务器上来,包括图片.声音.视频文件.起初只有Android版,大家知道,Android的录音格式amr,在电脑上播放不出来,必须转码.因为之前只有Android版的,所以就用jave给方便的解决了.但是后来又增加了iPhone版,传上来的录音格式是caf.jave虽然支持几十种音视频格式,但是却支持不了这个caf格式.后来也尝试了lame,也是不行.网上的资料绝大部分是说在iPhone手机上转的,可是我要在服务器上转.搞了一个星期,没有一点进展.后

linux下使用ffmpeg将amr转成mp3

说明:AMR格式是智能手机上的常用音频文件格式,比MP3格式的压缩比大.同样时长的AMR文件大概是MP3的十分之一,所以在移动互联项目中应用比较广泛.但目前AMR格式在个人电脑上应用较少,所以目前大部门播放器都不支持AMR,为了解决这个问题我们打算在服务器端将AMR转成MP3,以便在个人电脑上通过浏览器的方式进行播放.最近公司一款基于移动互联网的产品有个短暂的录音(留言)功能,因为录音需要传输到服务器上,所以为了用户体验及节省用户流量,我们采用了AMR的语音格式. 目前并没有找到合适的支持AMR

音频播放、录音、视频播放、拍照、视频录制-b

随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像头的操作都提供了多套API.在今天的文章中将会对这些内容进行一一介绍: 音频 音效 音乐 音频会话 录音 音频队列服务 视频 MPMoviePlayerController MPMoviePlayerViewController AVPlayer 摄像头 UIImagePickerController拍照

FFMpeg ver 20160219-git-98a0053 滤镜中英文对照 2016.02.21 by 1CM

FFMpeg ver 20160219-git-98a0053 滤镜中英文对照 2016.02.21 by 1CM T.. = Timeline support 支持时间轴 .S. = Slice threading 分段线程 ..C = Command support 支持命令传送 A = Audio input/output 音频 输入/输出 V = Video input/output 视频 输入/输出 N = Dynamic number and/or type of input/out

ffmpeg文档28-重采样选项

28 重采样选项 音频重采样支持下面一些选项. 选项可以在ffmpeg工具集中采用-option value的形式进行设置,或者在aresample滤镜中以option=value形式设置,也可以通过libavutil/opt.h的API或明确设置在SwrContext选项中. ich, in_channel_count 设置输入通道序数.默认为0.如果in_channel_layout被设置,则并不强制要求设置这个值. och, out_channel_count 设置输出通道序数,默认为0.

ffmpeg文档34-音频滤镜

34 音频滤镜 当你配置编译FFmpeg时,先采用--disable-filters可以禁止所有的滤镜,然后显式配置想要支持的滤镜. 下面是当前可用的音频滤镜 adelay 延迟一个或者多个音频通道 它接受如下选项: delays 参数是以|分隔的列表字符串,分别用于指明对应各个通道延迟的微秒(milliseconds)数.应提供至少一个大于0的延迟.未使用的延迟将被静默忽略.如果延迟值数量小于通道数量,则剩余通道不会被延迟. adelay例子 第一通道延迟1.5秒,第三通道0.5秒(其它通道均