实现语音视频录制(demo源码)

        在很多语音视频软件系统中,经常有将实时的音频或视频录制为文件保存到磁盘的需求,比如,视频监控系统中录制监控到的视频、视频会议系统中录制整个会议的过程、语音通话系统中录制完整的对话内容、等等。  

  MFile组件(Oraycn.MFile.dll)是傲瑞实用组件之一,它可以将原始的语音数据和视频数据按照指定的格式进行编码,并将它们写入到视频文件(如.mp4)中。 


一.MFile 简介

 

      MFile组件内部的核心技术包括以下4点:

(1)音频数据编码。

(2)视频数据编码。

(3)将编码后的数据按文件格式的要求写入到文件容器中。

(4)保证音频视频播放的同步。

  MFile支持主流的视频格式:MPEG4、H264、H263、FLV、MPEG2、WMV 等。

  MFile支持主流的音频格式:MP3、AAC、AC3、FLAC、ATRAC3、APE、SPEEX、G729 等。

  使用MFile有三种模式可供选择:生成音频文件(如.mp3)、生成无声的视频文件(如.h264)、生成普通视频的文件(如.mp4)。生成的这些文件,可以直接使用我们常见的播放器进行播放。

 

 二.MFile 结构

 

        对于使用者而言,MFile组件中的主要类的结构图如下所示:

     

        其中,AudioFileMaker用于生成音频文件、SilenceVideoFileMaker用于生成无声的视频文件、而VideoFileMaker用于生成既有声音又有图像的普通视频文件。这三个类都从基类BaseMaker继承,它们的使用方式也是一致的。接下来,我们仅仅详细讲解VideoFileMaker类的使用,SilenceVideoFileMaker 和 AudioFileMaker的使用方法可以类推之。

 

三.VideoFileMaker类

 

        下面是VideoFileMaker类的public方法的签名: 

    public class VideoFileMaker :IDisposable
    {
        /// <summary>
        /// 初始化视频文件。
          /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="videoCodec">视频编码格式</param>
        /// <param name="videoWidth">视频宽度</param>
        /// <param name="videoHeight">视频高度</param>
        /// <param name="videoFrameRate">帧频</param>
        /// <param name="audioCodec">音频编码格式</param>
        /// <param name="audioSampleRate">音频采样率。【注:采样位数必须为16位】</param>
        /// <param name="audioChannelCount">声道数</param>
        /// <param name="autoSyncToAudio">如果是实时录制,则可传入true,以音频为基准进行同步。</param>
        void Initialize(string filePath, VideoCodecType videoCodec, int videoWidth, int videoHeight, int videoFrameRate, AudioCodecType audioCodec, 
                        int audioSampleRate, int audioChannelCount, bool autoSyncToAudio);
        
        /// <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方法传入了生成视频文件时所需要的所有参数。请特别注意autoSyncToAudio参数,该参数用于自动将视频帧同步到音频。对于实时录制而言,当调用AddAudioFrame方法时,会根据所有音频帧的时长进行累加,记录当前这一音频帧的时间戳,然后,把这个时间戳赋值给同时调用AddVideoFrame方法的视频帧,如此达到音频视频同步的效果。

      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的数据。

(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 

 

  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值