JavaScript实现页面中录音功能的方法


Posted in Javascript onJune 04, 2019

前言

页面中实现录音需要使用浏览器提供的 Media​Recorder API,所以前提是需要浏览器支持 MediaStream Recording 相关的功能。

以下代码默认工作在 Chrome 环境中。

准备页面

首先准备一个页面,其中内容很简单,一个录音按钮,一个用于播放的 <audio> 标签。

<!DOCTYPE html>
<html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <meta http-equiv="X-UA-Compatible" content="ie=edge">
 <title>audio record</title>
</head>
<body>
 <div class="app">
  <button class="record-btn">record</button>
  <audio controls class="audio-player"></audio>
 </div>
 <script src="./recorder.js"></script>
</body>
</html>

获取录音权限

因为录音需要使用设备的话筒,所以第一步应该是向用户索要录音的权限。这是通过 Media​Devices​.get​User​Media()
来完成的,其用法为:

var promise = navigator.mediaDevices.getUserMedia(constraints);

其中 constraints 为需要获取的权限列表,这里只需要指定音频 audio 即可。

其返回是个 Promise,因为用户何时进行授权是不确定的。通过在 Promise 的回调中进行授权成功或失败的处理。

在使用前需要判断浏览器是否已经支持相应的 API,此时得到如下的代码:

if (navigator.mediaDevices.getUserMedia) {
 const constraints = { audio: true };
 navigator.mediaDevices.getUserMedia(constraints).then(
 stream => {
  console.log("授权成功!");
 },
 () => {
  console.error("授权失败!");
 }
 );
} else {
 console.error("浏览器不支持 getUserMedia");
}

其中成功回调里得到的入参 stream 为 MediaStream 对象。

此时运行后可看到浏览器展示出了让用户授权使用麦克风的提示。

JavaScript实现页面中录音功能的方法

向用户索要麦克风使用权限

创建录音实例

将上一步获取到的 MediaStream 传入 Media​Recorder 的构造器创建一个录音器的实例。

var mediaRecorder = new MediaRecorder(stream);

启动录音

通过监听页面中录音按钮的点击来启动录音。

const recordBtn = document.querySelector(".record-btn");
const mediaRecorder = new MediaRecorder(stream);
recordBtn.onclick = () => {
 mediaRecorder.start();
 console.log("录音中...");
};

MediaRecorder 实例上有个 state 状态,可用来判断录音器当前的活动状态,总共有三种值:

  • inactive:处于休息状态,要么是没开始,要么是开始后已经停止。
  • recording:录音中
  • paused:已经开始,但被暂停了,不是停止也没有被恢复。

所以通过这个状态,我们可以实现再次点击按钮时,结束录音。

recordBtn.onclick = () => {
 if (mediaRecorder.state === "recording") {
  mediaRecorder.stop();
  recordBtn.textContent = "record";
  console.log("录音结束");
 } else {
  mediaRecorder.start();
  console.log("录音中...");
  recordBtn.textContent = "stop";
 }
 console.log("录音器状态:", mediaRecorder.state);
};

音频数据的获取

上面按钮处理来自用户的交互,只负责启动或停止录音。音频的数据还是从 Media​Recorder 实例上通过监听其相应的事件来完成的。

当录音开始时,会触发其 MediaRecorder.ondataavailable 事件,从该事件回调的入参为 BlobEvent,从它身上取到 event.data 便是我们需要的音频数据。因为数据是一段一段产生的,所以需要暂存到一个数组中。

const chunks = [];
mediaRecorder.ondataavailable = function(e) {
 chunks.push(e.data);
};

目前为止完成的代码应该是这样的:

 recorder.js

JavaScript实现页面中录音功能的方法

录音状态的查看

录音结束及音频的播放

通过监听 MediaRecorder.onstop 事件,将收集好的音频数据创建成Blob 对象,然后 通过 URL.createObjectURL 创建成 HTML 中 <audio> 标签可使用的资源链接。

mediaRecorder.onstop = e => {
 var blob = new Blob(chunks, { type: "audio/ogg; codecs=opus" });
 chunks = [];
 var audioURL = window.URL.createObjectURL(blob);
 audio.src = audioURL;
};

其中,在使用完收到到的音频数据后,将 chunks 置空方便下次录音时使用。

目前为止完成的代码应该是这样的:

 recorder.js

运行

完成上面步骤后,实现了一个简单的录音功能,可通过此地址在线体验。完整的代码可在仓库 wayou/audio-recorder 中获取到。

相关资源

  • Media​Recorder
  • MediaRecorder.onstop
  • URL.createObjectURL

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对三水点靠木的支持。

Javascript 相关文章推荐
jQuery与其它库冲突的解决方法
Jun 25 Javascript
IE中jquery.form中ajax提交没反应解决方法分享
Sep 11 Javascript
JavaScript判断访问的来源是手机还是电脑,用的哪种浏览器
Dec 12 Javascript
jquery得到iframe src属性值的方法
Sep 25 Javascript
JavaScript中判断函数、变量是否存在
Jun 10 Javascript
jQuery实现仿新浪微博浮动的消息提示框(可智能定位)
Oct 10 Javascript
jqGrid中文文档之选项设置
Dec 02 Javascript
jQuery实现右下角可缩放大小的层完整实例
Jun 20 Javascript
详解利用Angular实现多团队模块化SPA开发框架
Nov 27 Javascript
React Native开发封装Toast与加载Loading组件示例
Sep 08 Javascript
vue + element-ui的分页问题实现
Dec 17 Javascript
VUE+node(express)实现前后端分离
Oct 13 Javascript
vue elementUI 表单校验功能之数组多层嵌套
Jun 04 #Javascript
小程序根据手机机型设置自定义底部导航距离
Jun 04 #Javascript
js回文数的4种判断方法示例
Jun 04 #Javascript
Vue对象赋值视图不更新问题及解决方法
Jun 03 #Javascript
在 Vue 应用中使用 Netlify 表单功能的方法详解
Jun 03 #Javascript
JavaScript之数组扁平化详解
Jun 03 #Javascript
JavaScript从原型到原型链深入理解
Jun 03 #Javascript
You might like
SONY SRF-40W电路分析
2021/03/02 无线电
解析php中获取url与物理路径的总结
2013/06/21 PHP
帝国cms目录结构分享
2015/07/06 PHP
thinkphp在php7环境下提示Cannot use ‘String’ as class name as it is reserved的解决方法
2016/09/30 PHP
PHP定义字符串的四种方式详解
2018/02/06 PHP
优化 JavaScript 代码的方法小结
2009/07/16 Javascript
JS弹出层单纯的绝对定位居中示例代码
2014/02/18 Javascript
jQuery的css()方法用法实例
2014/12/24 Javascript
JQuery分屏指示器图片轮换效果实例
2015/05/21 Javascript
jQuery实现批量判断表单中文本框非空的方法(2种方法)
2015/12/09 Javascript
javaScript中的原型解析【推荐】
2016/05/05 Javascript
JavaScript中关于for循环删除数组元素内容时出现的问题
2016/11/21 Javascript
JS简单获取当前年月日星期的方法示例
2017/02/07 Javascript
使用InstantClick.js让页面提前加载200ms
2017/09/12 Javascript
聊聊Vue.js的template编译的问题
2017/10/09 Javascript
webuploader实现上传图片到服务器功能
2018/08/16 Javascript
Element-UI中Upload上传文件前端缓存处理示例
2019/02/21 Javascript
纯 JS 实现放大缩小拖拽功能(完整代码)
2019/11/25 Javascript
react-native 实现购物车滑动删除效果的示例代码
2021/01/15 Javascript
使用Python下载Bing图片(代码)
2013/11/07 Python
Ubuntu 14.04+Django 1.7.1+Nginx+uwsgi部署教程
2014/11/18 Python
Python实现曲线点抽稀算法的示例
2017/10/12 Python
Python中pandas dataframe删除一行或一列:drop函数详解
2018/07/03 Python
python日志logging模块使用方法分析
2019/05/23 Python
浅谈python多进程共享变量Value的使用tips
2019/07/16 Python
Python字典底层实现原理详解
2019/12/18 Python
什么是Python变量作用域
2020/06/03 Python
CSS3解决移动页面上点击链接触发色块的问题
2016/06/03 HTML / CSS
美国家喻户晓的保健品品牌:Vitamin World(维他命世界)
2016/08/19 全球购物
护理自荐信范文
2013/10/05 职场文书
师范大学音乐表演专业求职信
2013/10/23 职场文书
简历中个人求职的自我评价模板
2013/11/29 职场文书
文化产业实施方案
2014/06/07 职场文书
信访工作汇报材料
2014/10/27 职场文书
Python-typing: 类型标注与支持 Any类型详解
2021/05/10 Python
国产动画《万圣街》日语配音版制作决定!
2022/03/20 国漫