web前端video视频音频相关

一、使用

代码仅作一个参考,并没有管逻辑哈,bug 就忽略掉吧

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<style>
    video{
        width: 50%;
        height: 50%;
        margin: 50px auto;
        background-color: rgba(255, 232, 198, 0.53);
        display: block;
    }
</style>
<script type="text/javascript" src="../../JS/jquery-3.4.1.js"></script>
<body>
    <input type="file" multiple accept="">
    <hr>
    <div>
        <video id="video">

        </video>
    </div>
    <button onclick="openCamera()">打开Camera</button>
    <button onclick="stopRecording()">停止recording</button>
    <button onclick="saveRecording()">保存recording</button>

    <hr>
    <div class="record-wrap">
        <h5>预览区域</h5>
        <div class="video-list" id="videoWrap">
            暂无视频
        </div>
        <p class="tips">点击视频即可下载<b class="batch-download" id="batchDownloadVideos">批量下载</b></p>
    </div>
</body>
</html>
<script>
    var videoWrap = document.getElementById('videoWrap'); // 视频预览
        var video = document.getElementById("video");
        var setting = {
            audio:{
                sampleRate:"32000HZ",
                sampleSize: 16,
                volume: 0.3,
                echoCancellation: true,
                autoGainControl : false,
                noiseSuppression : true,
                latency : 3,
                channelCount : 2
            },
            // audio:true,
            video:{
                facingMode:'user', // 'user'前置摄像头 ‘environment’代表后置摄像头。笔记本只有前置,这个不确定行不行
                width : 400,
                height : 250,
                noiseSuppression : true,
                frameRate :{
                    ideal : 10,
                    max :15
                }
            }
        }
        var options ={      // 这个配置我还用到,可以忽略,
            audioBitsPerSecond : 128000,
            videoBitsPerSecond : 2500000,
            mimeType : 'video/ogg'
        }
        function openCamera() {
            if(navigator.mediaDevices){
                navigator.mediaDevices.getUserMedia(setting).then(success).catch(error)
            }else if(navigator.webkitGetUserMedia){
                //webkit核心浏览器
                navigator.webkitGetUserMedia({video : {width: 1000, height: 1000},audio:true},success, error)
            }else if(navigator.mozGetUserMedia){
                //firfox浏览器
                navigator.mozGetUserMedia({video : {width: 1000, height: 1000},audio:true}, success, error);
            }else if(navigator.getUserMedia){
                //旧版API
                navigator.getUserMedia({video : {width: 1000, height: 1000},audio:true}, success, error);
            }
        }

        function success(stream) {
            video.srcObject = stream;
            video.play();    // 播放
            startRecording(stream) // 录屏
        }
        function error(error) {
            console.log(`访问用户媒体设备失败${error.name}, ${error.message}`)
            // alert(`访问用户媒体设备失败${error.name}, ${error.message}`)
        }

        var chunks = [];
        var mediaRecorder = {};
        function startRecording(stream) {
            alert("录制视频")
            mediaRecorder = new MediaRecorder(stream);

            //为了收集录制的数据,需要监听 ondataavailable 事件
            chunks = [];
            mediaRecorder.ondataavailable = function(e){
                console.log(e.data);
                // chunks.push(e.data)
                chunks = e.data
            }
            // 开始录制
            mediaRecorder.start();
            console.log("媒体流的状态: "+mediaRecorder.state)

        }

        function stopRecording() {
            mediaRecorder.stop();
        }

        function saveRecording() {

            let videoTag = document.createElement('video');
            videoTag.width = video.width / 3;
            videoTag.height = video.height / 3;
            videoTag.controls = true;
            // chunk 为Blob对象
            creatFileObj(chunks,"aa.mp4");
            let src = window.URL.createObjectURL(chunks);
            chunks = '';
            mediaRecorder = null;
            videoTag.src = src;		// 注意这里不要弄到当前实时画面的 video 对象中,因为实时的 video 中是有流的
            videoWrap.appendChild(videoTag);

        }

        function creatFileObj(blob,fileName) {
            var file = new File([blob],"aa.mp4");  // 将 blob 转为 file 对象,
            for(var key in file){
                console.log(key + ' ===> '+file[key])
            }
        }
</script>


二、参数

facingMode : 'user’前置摄像头 ‘environment’代表后置摄像头。我的笔记本只有一个摄像头,使用 'user’还是 ‘environment’都能打开
sampleRate : 指定采样率 。音频采样率是指录音设备在一秒钟内对声音信号的采样次数,采样的频率越高声音的还原就越真是自然。在当今主流的采集卡上,采样频率一般共分为 11025HZ、22050HZ、24000HZ、48000HZ。
sampleSize : 每个采样点大小位数。可以理解为采集卡处理声音的解析度,这个值越大,解析度就越高,录制和回放的声音就越真实。本质上声音是一种能量波,具有波的特性,所以光是具有频率信息是不够的,我们还必须获得该频率的能量值并量化,用于表示信号强度。而我们的计算机采用的是二进制,量化电平数为 2 的整数次幂。如对一个波进行了8次采样,但我们只是用了 2 bit 的采样大小(即 00 、01 、10 、11 ),结果我们只能保留 4 个采样点的值而舍弃另外4个
volume : 从 0(静音)到 1(最大)取值 。 在音频中就是声音大小
echoCancellation : 是否使用回声消除来尝试去除通过麦克风回传到扬声器的音频
autoGainControl : 是否要修改麦克风的输入音量
noiseSuppression : 是否尝试去除音频信号中的背景噪声
latency : 以秒为单位,控制开始处理声音和下一步可以使用数据之间的时间 (音频编解码器的延时有所不同,这个时间需要设置长一些,原因见备注②)
channelCount : 规定了单声道的时候为 1 ,立体声的时候为 2

width/height : 指定分辨率
frameRate : 帧率,在受限带宽传输时,低帧率可能更适宜

备注:
① 数据量(字节/秒) = 采样率(Hz) * 采样大小(bit) * 声道数 / 8 (除以8是将 bit 转为 byte)
② latency 意思是潜伏,比如,在第四个时钟才使用的数据,但该数据已在时钟 一输出,为此,采用某种方法,如 D触发器级联等,使该数据在1、2、3时钟器件淹没(输出端看不到),即潜伏
delay 是指数据应在时钟 1 输出,但却在时钟 2 输出,这就是延时,延时有线延时,门级延时等,大多数情况是不期望的
③ ideal ,当一个请求包含一个 ideal (应用最理想的)值时,这个值有着更高的权重,意味着浏览器会先尝试找到最接近指定的理想值的设定或者摄像头(如果设备拥有不止一个摄像头)

sampleRate和sampleSize
delay和latency的区别

三、知识

MediaStream

MediaStream : 是一个媒体内容的流。一个流包含几个轨道,比如视频和音频轨道
属性:
MediaStream.active: 只读
布尔型。如果这个流处于活动,状态值为 true, 反之为 false

MediaStream.ended : 只读
布尔型。如果 ended 事件在这个对象上触发了,也就是说这个流已经被完全读取,值为 true, 如果这个流还没有到达这个流的尾部,值为false

MediaStream.id: 只读
这是一个包含36个字符的 DOMString,用来作为这个对象的唯一标识符

事件处理:
MediaStream.onaddtrack:
这是 addtrack 事件在这个对象上触发时调用的事件处理器[EventHandler],这时一个 MediaStreamTrack 对象被添加到这个流
MediaStream.onended:
这是当流终止 [ended] 时触发的事件
MediaStream.onremovetrack:
这是 removetrack 事件在这个对象上触发时调用的事件处理器 [EventHandler],这时一个对象从流上移除

方法:
MediaStream.addTrack()
存储传入参数 MediaStreamTrack 的一个副本。如果这个轨道已经被添加到了这个媒体流,什么也不会发生;如果目标轨道为"完成"状态(也就是已经到尾部了), 一个 INVALID_STATE_RAISE 异常会产生。

MediaStream.clone()
返回这个 MediaStream 对象的克隆版本。返回的版本会有一个新的 ID。
返回给定 ID 的轨道。如果没有参数或则没有指定 ID 的轨道,将返回 null. 如果有几个轨道有同一个 ID,将返回第一个

MediaStream.getTracks()
返回流中所有的 MediaStreamTrack 列表

MediaStream.getAudioTracks()
返回流中 kind 属性为 “audio” 的 MediaStreamTrack 列表。顺序是不确定的,不同浏览器间会有不同,每次调用也有可能不同

MediaStream.getTrackById()
返回给定 ID 的轨道。如果没有参数或则没有指定的轨道,将返回 null. 如果有几个轨道有同一个 ID,将返回第一个。

MediaStream.getVideoTracks()
返回流中 kind 属性为"video"的 MediaStreamTrack 列表。顺序是不确定的,不同浏览器间会有不同,每次调用也有可能不同。

MediaStream.removeTrack()
移除作为参数传入的 MediaStreamTrack 。如果这个轨道不在 MediaStream 对象中什么也不会发生; 如果目标轨道为"完成"状态,一个 INVALID_STATE_RAISE 异常会发生

File 对象

构造函数
File() 返回一个新构建的文件对象
属性
File.lastModified 只读
返回当前 File 对象所引用文件最后修改时间,自 UNIX 时间起始值(1970年1月1日00:00:00 UTC)以来的毫秒数

File.lastModifiedDate 只读
返回当前 File 对象所引用文件最后修改的 Date 对象

File.name 只读
返回当前 File 对象所引用文件的名字

File.size 只读
返回文件的大小

File.webkitRelativePath 只读
返回 File 相关的 path 或 URL

File.type 只读
返回文件的多用途互联网扩展协议(MIME Type)

File 接口没有定义任何方法,但是它从 Blob 接口继承了一下方法
Blob.slice([start[,end[,contentType]]])

Blob 对象

Blob 对象表示一个不可变、原始数据类对象。它的数据可以按文本或二进制的格式进行读取,也可以转成 ReadableStream 来用于数据操作。

Blob 表示的不一定是 JavaScript 原生格式的数据。 File 接口基于 Blob , 继承了 blob 的功能并将其扩展使其支持用户系统上的文件。

要从其它非 blob对象和数据构造一个 Blob, 请使用 Blob() 构造函数。要创建一个 blob 数据的子集 blob, 请使用 slice() 方法。要获取用户文件系统上的文件对应的 Blob 对象,请参阅 File 文档

备注:
① slice() 方法原本接收 length 作为第二个参数,以表示复制到新 Blob 对象的字节数。如果设置的参数使 ( start+length ) 超出了源 Blob 对象的大小,则返回从开始到结尾的所有数据
② slice() 方法在某些浏览器和版本上带有浏览器引擎前缀: 比如 Firefox 12 以及更早版本的 blob.mozSlice() 和 Safari 中的 blob.webkitSlice().没有浏览器引擎前缀的老版本 slice() 方法有不同的语义,并且已过时。 Firefox 30 取消了对 blob.mozSlice() 的支持

构造函数
Blob(blobParts[,options] )
返回一个新创建的 Blob 对象,其内容由参数中给定的数组串联组成

属性
Blob.size 只读
Blob 对象中所包含数据的大小(字节)

Blob.type 只读
一个字符串,表明该 Blob 对象所包含数据的 MIME 类型。如果类型未知,则该值为空字符串

方法
Blob.slice([start[,end[,contentType]]])
返回一个新的 Blob 对象,包含了源 Blob 对象中指定范围内的数据

Blob.stream()
返回一个能读取 blob 内容的 ReadableStream

Blob.text()
返回一个 promise 且包含 blob 所有内容的 UTF-8格式的 USVString

Blob.arrayBuffer()
返回一个 promise 且包含 blob 所有内容的二进制格式的 ArrayBuffer

备注
① USVString 对应 unicode 标量值的所有可能集合。在 JavaScript 中返回时, USVString 映射到 String .它通常仅用于执行文本处理的 API,需要一串 unicode 标量值才能进行操作。
File对象参考
Blob对象参考
USVString
API原文

MediaRecorder 对象

MediaRecorder 是 MediaStream Recording API 提供的用来进行媒体轻松录制的接口,他需要通过调用 MediaRecorder() 构造方法进行实例化。

构造函数
MediaRecorder() 构造函数会创建一个指定的 MediaStream 进行录制, 支持的配置项包括设置容器的 MIME 类型(例如“video/webm” 或者"video/mp4") 和音频及视频的码率或者同用一个码率

配置项
MediaRecorder.mimeType 只读
返回 MediaRecorder 对象创建时选择器选择的录制容器的 MIME type

MediaRecorder.state 只读
返回录制对象 MediaRecorder 的当前状态(闲置中,录制中或则暂停)(inactive recording or paused )

MediaRecorder.stream 只读
返回录制器对象 MediaRecorder 创建时构造函数传入的 stream 对象

MediaRecorder.ignoreMutedMedia
用以指定 MediaRecorder 是否录制无声的输入源,如果这个属性是 false ,录制器对象 MediaRecorder 会录制无声的音频或者黑屏的视频,默认值是 false

MediaRecorder.videoBitsPerSecond 只读
返回视频采用的编码比率,它可能和构造函数的设置比率不同。(if it was privided)

MediaRecorder.audioBitsPerSecond 只读
返回音频采用的编码比率,它可能和构造函数中设置的比率不同。(if it was privaded)

方法
MediaRecorder.isTypeSupported()
返回一个 Boolean 值,来表示设置的 MIME type 是否被当前用户的设备支持

MediaRecorder.pause()
暂停媒体录制

MediaRecorder.requestData()
请求一个从开始到当前接收到的,存储为 Blob 类型的录制内容。(或者是返回上一次调用 requestData() 方法之后到现在的内容)。调用这个方法后,录制将会继续进行,但是会创建一个新的 Blob 对象

MediaRecorder,resume()
继续录制之前被暂停的录制动作

MediaRecorder.start()
开始录制媒体,这个方法调用时可以通过给 timeslice 参数设置一个毫秒值,如果设置这个毫秒值,那么录制的媒体会按照你设置的值进行分割成一个个单独的区块,而不是以默认的方式录制一个非常大的整块内容

MediaRecorder.stop()
停止录制,同时触发 dataavailable 事件,返回一个存储 Blob 内容的录制数据,之后不再记录

静态方法
静态方法,判断给定的 MIME 类型是否支持。返回 Boolean 类型的值

事件处理
MediaRecorder.ondataavailable
调用它用来处理 dataavailable 事件,该事件可用于获取录制的媒体资源( 在事件的 data 属性中会提供一个可用的 Blob 对象)

MediaRecorder.onerror
调用事件处理程序来处理记录错误事件,包括报告媒体记录所引起的错误。这些是致命错误,将停止记录

MediaRecorder.onpause
用来处理 pause 事件,该事件在媒体暂停录制时触发(MediaRecorder.pause())

MediaRecorder.onresume
用来处理 resume 事件,该事件在暂停后恢复录制视频时触发(MediaRecorder.resume())

MediaRecorder.onstart
用来处理 start 事件,该事件在媒体开始录制时触发( MediaRecorder.start)

MediaRecorder.onstop
用来处理 stop 事件,该事件会在媒体录制结束时、媒体流(MediaStream)结束时、或者调用 MediaRecorder.stop() 方法后触发

事件
使用 addEventListener() 或通过将事件侦听器分配给此接口的属性来侦听这些事件。

error
发生错误时触发: 例如,因为不允许录制或尝试使用不支持的编解码器进行录制。也可通过 onerror 获得

四、注意事项

① 在调用 getUserMedia 方法时,必须有一个参数对视频或音频进行设置,不然的话会报错,错误案例以及错误如下:
在这里插入图片描述
MediaStream

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值