傲瑞组件开发手册(01) -- 语音视频录制 MFile
在很多语音视频软件系统中,经常有将实时的音频或视频录制为文件保存到磁盘的需求,比如,视频监控系统中录制监控到的视频、视频会议系统中录制整个会议的过程、语音通话系统中录制完整的对话内容、电脑桌面录制、等等。
MFile组件(Oraycn.MFile.dll)是傲瑞实用组件之一,它可以将原始的语音数据和视频数据按照指定的格式进行编码,并将它们写入到视频文件(如.mp4)中。
一.MFile 简介
MFile组件内部的核心技术包括以下4点:
(1)音频数据编码。
(2)视频数据编码。
(3)将编码后的数据按文件格式的要求写入到文件容器中。
(4)保证音频视频播放的同步。
使用MFile有三种模式可供选择:
(1)生成音频文件(.mp3,.m4a,.wav):声音编码格式为MP3,或AAC,或PCM。
(2)生成无声的视频文件(.mp4):视频编码格式为H264。
(3)生成普通视频的文件(.mp4):声音编码格式为AAC,视频编码格式为H264。
生成的这些文件,可以直接使用我们常见的播放器进行播放。
二.MFile 结构
对于使用者而言,MFile组件中的主要类的结构图如下所示:
其中,AudioFileMaker用于生成音频文件、SilenceVideoFileMaker用于生成无声的视频文件、而VideoFileMaker用于生成既有声音又有图像的普通视频文件。这三个类都从基类BaseMaker继承,它们的使用方式也是一致的。接下来,我们仅仅详细讲解VideoFileMaker类的使用,SilenceVideoFileMaker 和 AudioFileMaker的使用方法可以类推之。
三.VideoFileMaker类
下面是VideoFileMaker类的public方法的签名:
public class VideoFileMaker :IDisposable { /// <summary> /// 初始化视频文件。 /// </summary> /// <param name="filePath">文件路径</param> /// <param name="videoWidth">视频宽度</param> /// <param name="videoHeight">视频高度</param> /// <param name="videoFrameRate">帧频</param> /// <param name="audioSampleRate">音频采样率。【注:采样位数必须为16位】</param> /// <param name="audioChannelCount">声道数</param> void Initialize(string filePath, int videoWidth, int videoHeight, int videoFrameRate, int audioSampleRate, int audioChannelCount); /// <summary> /// 初始化视频文件。 /// </summary> /// <param name="filePath">文件路径</param> /// <param name="videoWidth">视频宽度</param> /// <param name="videoHeight">视频高度</param> /// <param name="videoFrameRate">帧频</param> /// <param name="videoQuality">录制生成视频的清晰度</param> /// <param name="audioSampleRate">音频采样率。【注:采样位数必须为16位】</param> /// <param name="audioChannelCount">声道数</param> void Initialize(string filePath, int videoWidth, int videoHeight, int videoFrameRate, VideoQuality videoQuality, int audioSampleRate, int audioChannelCount); /// <summary> /// 添加音频帧。 /// </summary> void AddAudioFrame(byte[] audioframe); /// <summary> /// 添加视频帧。如果autoSyncToAudio开启,则自动同步到音频。 /// </summary> void AddVideoFrame(Bitmap frame); /// <summary> /// 添加视频帧。 /// </summary> /// <param name="frame">视频帧</param> /// <param name="timeStamp">离开始时的时间长度</param> void AddVideoFrame(Bitmap frame, TimeSpan timeStamp); /// <summary> /// 关闭视频文件。 /// </summary> /// <param name="waitFinished">如果还有帧等待写入文件,是否等待它们全部写入文件。</param> void Close(bool waitFinished); }
(1)Initialize 方法
Initialize方法传入了生成视频文件时所需要的所有参数。它有一个重载方法,两个方法的差别在于videoQuality参数,该参数用于控制录制生成的视频的清晰度。
MFile要求录制的视频帧的长和宽( videoWidth 和 videoHeight)必须是4的整数倍。如果图像帧不满足这一要求,则应先对图像帧进行裁剪。(MFile Demo中有相应的操作)
Initialize如果执行失败(比如,参数设置错误),其将会抛出相应的异常。
Initialize成功调用后,VideoFileMaker 会启动一个独立的后台线程,该线程的职责就是将后面加入的音频帧、视频帧异步写入到文件中。
(2)AddAudioFrame 方法
用于向文件中写入音频数据,至于参数audioframe的字节长度,AddAudioFrame方法并没有任何限制。也就是说,可以一次写入10ms的数据,也可一次写入100ms的数据。但是,MFile要求音频采集的位宽必须为16bit。
另外要注意,audioframe的字节长度必须与Initialize方法传入的audioSampleRate参数和audioChannelCount参数保持一致的关系。比如,采样率16k、采样位数16bit、声道数1,那么一个10ms的音频帧的大小为:(16000*16*1*0.01)/8 = 320 字节。也就是说,在这种情况下,如果参数audioframe的长度为320字节,就表示其为10ms的数据,如果为640字节,就表示其为20ms的数据。
如果需要录制多路语音数据,那么在调用AddAudioFrame方法之前,必须先自行将多路语音数据混音成一路,MFile没有提供混音的功能。(如果您使用了我们的OMCS语音视频框架,那么,OMCS有内置的混音功能可以直接使用)
(3)AddVideoFrame 方法
AddVideoFrame 方法的参数直接是一个位图,表示一个视频帧,很容易理解。如果需要手动控制每一视频帧写入的时间戳,那么可以调用带两个参数的重载方法。
(4)Close 方法
当不再有新的视频帧和音频帧写入时,可以调用Close方法,以完成文件的生成。但是,由于实际的写文件操作是在一个独立的后台线程中进行的,在某些情况下,在调用Close的时候,可能后台线程还正在忙碌(比如,在一些比较慢的机器上面,实时录制视频时,消费的速度跟不上生产的速度,便会出现这种情况),那么,Close方法的参数waitFinished就用于指示是否等待后台线程将所有帧写入线程,如果等待发生,Close调用将被阻塞,直至后台线程工作完成,Close才会返回。
(5)WriteErrorOccured 事件
当当后台写线程在向文件写入视频帧或音频帧时,如果发生任何错误,将会触发WriteErrorOccured事件,并且,结束写线程。
四.MFile Demo
下面我们使用一个demo来介绍如何使用MFile组件,在这个demo中,我们借助语音视频采集组件MCapture采集来自麦克风输入的音频数据、以及来自摄像头采集的视频数据,并将它们录制生成mp4文件。Demo 运行的截图如下所示:
首先,当点击启动设备按钮时,我们创建一个摄像头采集器实例和一个麦克风采集器实例,并启动它们开始采集:
this.cameraCapturer = CapturerFactory.CreateCameraCapturer(0, new Size(int.Parse(this.textBox_width.Text), int.Parse(this.textBox_height.Text)), this.fps); this.cameraCapturer.ImageCaptured += new CbGeneric<Bitmap>(cameraCapturer_ImageCaptured); this.cameraCapturer.CaptureError += new CbGeneric<Exception>(cameraCapturer_CaptureError); this.microphoneCapturer = CapturerFactory.CreateMicrophoneCapturer(0); this.microphoneCapturer.AudioCaptured += new CbGeneric<byte[]>(microphoneCapturer_AudioCaptured); this.microphoneCapturer.CaptureError += new CbGeneric<Exception>(microphoneCapturer_CaptureError); //开始采集 this.cameraCapturer.Start(); this.microphoneCapturer.Start();
接下来,点击开始录制按钮时,我们初始化VideoFileMaker组件:
this.videoFileMaker = new VideoFileMaker(); this.videoFileMaker.AutoDisposeVideoFrame = true; this.videoFileMaker.Initialize("test.mp4", VideoCodecType.H264, int.Parse(this.textBox_width.Text), int.Parse(this.textBox_height.Text), this.fps, AudioCodecType.AAC, 16000, 1, true); this.isRecording = true;
参数中设定,使用h.264对视频进行编码,使用aac对音频进行编码,并生成mp4格式的文件。然后,我们可以通过OMCS获取实时的音频数据和视频数据,并将它们写到文件中。
void microphoneCapturer_AudioCaptured(byte[] audioData) //采集到的语音数据 { if (this.isRecording) { this.videoFileMaker.AddAudioFrame(audioData); } } //采集到的视频图像 void cameraCapturer_ImageCaptured(Bitmap img) { if (this.isRecording) { this.DisplayVideo((Bitmap)img.Clone()); this.videoFileMaker.AddVideoFrame(img); } else { this.DisplayVideo(img); } }
当想结束录制时,则调用Close方法:
this.videoFileMaker.Close(true);
Demo源码:Oraycn.RecordDemo.rar
录制方案推荐:
(1)采集与录制最完整的Demo,五星推荐:WinForm版本、WPF版本
(2)远程录制/在服务端录制 语音、视频、桌面:MFile + OMCS
(3)录制双方的视频聊天全过程:MFile + OMCS
(5)采集麦克风和声卡,混音之后进行录制:MFile + MCapture
-----------------------------------------------------------------------------------------------------------------------------------------------
Q Q:168757008