• 2.6、实战案例(三)


    文章导读:本节实现视频的录制和保存功能。推荐阅读方式:实操。

      为了更好的讲解代码,我们还是把软件界面展示出来,如下图2.6.1。

    图 2.6.1 (软件界面截图)

       本节内容,我们来完成该软件的最后一个功能:视频的录制和保存。先说下视频的录制,在webrtc中如何实现视频的录制呢?主要依赖一个类——MediaRecorder,该类是一个全局类,使用的时候可以直接实例化,实例化时需要传入两个参数,第一个参数是流对象,即通过getUserMedia获取的流对象;第二个参数是录制的视频格式以及编码方式,示例代码如下。

    let recordOption = {
        mimeType:"video/webm;codecs=vp8"
    }
    if(!MediaRecorder.isTypeSupported(recordOption.mimeType)){
        throw new Error("录制时不支持该格式"+recordOption.mimeType);
    }
    let recordObject = new MediaRecorder(mediaStream,recordOption)

     如上的代码,mediaStream是一个流对象,即本软件中cameraManager对象的mediaStream属性(记不住的同学自觉翻前几节文章来look look);recordOption则录制时的配置对象,其中mimeType属性描述录制视频的格式以及编码,其中“video/webm”表示录制的类型是视频,格式是webm;codecs=vp8表示采用vp8的编解码规范。recordObject是MediaRecorder实例化后的对象,当然,仅创建了对象还不会立即录制,还得手动调用启动录制,代码如下。

    recordObject.start(10)

     start方法还传进了一个参数10,表示每片数据时长为10毫秒,即一段完整的视频由多个“10毫秒”长的片段组成的。在录制的过程中,我们如何存储数据?这里就要提到recordObject对象中的一个回调方法——ondataavailable,每隔一段的时间就触发一次,每触发一次就说明完成了一片数据的采集,这里的start方法我们传入参数10,就表示每10毫秒ondataavailable会被触发一次。代码如下。

    recordObject.ondataavailable = (e)=>{
        if(e && e.data && e.data.size){
            // 这里把数据片缓存起来
        }
    }

    停止录制的方法也很简单,直接调用其stop方法,代码如下。

    recordObject.stop();

    以上就是视频录制的核心功能方法,现在我们将其集成到软件中。从业务的角度来看,录制功能可以看做是单独业务,于是这里创建一个对象来管理录制业务——recordManager。该对象有两个方法,两个属性。两个方法:开始录制startRecord、结束录制stopRecord。两个属性:数据缓存对象buffer(用于临时存储二进制视频数据)、recordObject对象存放MediaRecorder的实例化后的对象。代码结构如下。

    // 录制管理对象
    const recordManager = {
        // 二进制数据的数组
        buffer:[],
    
        //录制实例
        recordObject:null,
        
        // 开始录制
        startRecord(){
            
        },
        
        // 停止录制
        stopRecord(){
            
        }
        
    }

     先来实现第一个方法——startRecord。分析下其运行过程:首先清空缓存,防止上一次录制时残留一些垃圾数据影响本次录制;其次实例化一个MediaRecorder对象,同时设置其数据回调函数;最后启动录制,并且更新系统状态为“录制中”。代码如下。

    // 开始录制
        startRecord(){
            this.buffer = [];//清空数据
            if(!cameraManager.mediaStream){
                throw new Error("录制失败,mediaStream读取失败");
            }
            let recordOption = {
                mimeType:"video/webm;codecs=vp8"
            }
            if(!MediaRecorder.isTypeSupported(recordOption.mimeType)){
                throw new Error("录制时不支持该格式"+recordOption.mimeType);
            }
            this.recordObject = new MediaRecorder(cameraManager.mediaStream,recordOption)
            // 录制时数据回调
            this.recordObject.ondataavailable = (e)=>{
                if(e && e.data && e.data.size){
                    this.buffer.push(e.data);
                }
            }
            this.recordObject.start(10)
            statusManager.startedRecord()//更改系统状态
        },

    如上代码所示, 在实例化MediaRecorder对象之前,考虑到当前环境对指定的格式——“video/webm;codecs=vp8”的支持情况,所以调用了isTypeSupported方法判断。this.recordObject.ondataavailable 是完成一个数据片录制的回调,我们可以在这个回调函数中缓存数据。至此,开始录制功能完成,接下来实现停止录制功能。

      分析下停止录制功能的运行流程:首先停止录制;其次创建下载对象,并且下载数据到本地;最后,清空缓存,并还原系统的状态为“摄像头已打开”。实现的代码如下。

    // 停止录制
        stopRecord(){
            if(!this.recordObject){
                return;
            }
            this.recordObject.stop();
            let blob = new Blob(this.buffer,{type:"video/webm"});
            let url = URL.createObjectURL(blob);
            let a = document.createElement("a");
            a.href = url;
            a.download = "record.webm"
            a.click();
            this.buffer = [];
            statusManager.openedCamera();
        }

    至此,开始录制和停止录制的功能编写完毕,这两个方法都需要在eventManager(事件管理对象)中通过监听“开始录制”、“结束录制”两个按钮来调用,这里就不在演示,接下来展示recordManager的完整代码。

    // 录制管理对象
    const recordManager = {
        // 二进制数据的数组
        buffer:[],
    
        //录音实例
        recordObject:null,
        
        // 开始录制
        startRecord(){
            this.buffer = [];//清空数据
            if(!cameraManager.mediaStream){
                throw new Error("录制失败,mediaStream读取失败");
            }
            let recordOption = {
                mimeType:"video/webm;codecs=vp8"
            }
            if(!MediaRecorder.isTypeSupported(recordOption.mimeType)){
                throw new Error("录制时不支持该格式"+recordOption.mimeType);
            }
            this.recordObject = new MediaRecorder(cameraManager.mediaStream,recordOption)
            // 录制时数据回调
            this.recordObject.ondataavailable = (e)=>{
                if(e && e.data && e.data.size){
                    this.buffer.push(e.data);
                }
            }
            this.recordObject.start(10)
            statusManager.startedRecord()//更改系统状态
        },
        
        // 停止录制
        stopRecord(){
            if(!this.recordObject){
                return;
            }
            this.recordObject.stop();
            let blob = new Blob(this.buffer,{type:"video/webm"});
            let url = URL.createObjectURL(blob);
            let a = document.createElement("a");
            a.href = url;
            a.download = "record.webm"
            a.click();
            this.buffer = [];
            statusManager.openedCamera();
        }
        
    }

     最后。总结下:第一、本节的新内容 :MediaRecorder类的运用(实例化、start和stop的调用以及数据回调函数ondataavailable的使用);第二、下载数据时用到了Blob类,该类是JS中用来处理二进制大文件的,如果你对此不熟悉,建议查阅些资料。下载数据的逻辑是通过创建一个a元素并且模拟点击来实现的。

      到这里,本软件的所有功能已经实现完毕了,为了给大家更多的练习的机会,有些功能我并没有实现或者说没有细化,比如音频参数的配置,我只是简单的配置否启用,实际上音频的采集时还是有一些可配置的参数,所以下节补充音视频采集的相关内容以及桌面录制的相关内容,并布置本章的实战练习任务。

  • 相关阅读:
    数据库备份脚本
    redismyadmin安装(支持redis4 集群模式)
    elasticsearch ik安装
    centos7.2 +cloudstack 4.11 +KVM +ceph 安装配置(网卡带聚合)
    cloudstack4.11+KVM+4网卡bond5+briage 交换机不作配置
    web service:AxisFault faultCode: {http://schemas.xmlsoap.org/soap/envelope/}Server.userException
    根据WSDL生成客户端代码(XFire)
    Apache axis2 + Eclipse 开发 WebService
    The processing instruction target matching "[xX][mM][lL]" is not allowed.
    使用dom4j解析xml文件,并封装为javabean对象
  • 原文地址:https://www.cnblogs.com/rajan/p/12482078.html
Copyright © 2020-2023  润新知