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 无废话系列教程(二) jquery实战篇上
Jun 23 Javascript
解读JavaScript中 For, While与递归的用法
May 07 Javascript
jquery实现下拉菜单的二级联动利用json对象从DB取值显示联动
Mar 27 Javascript
jQuery 复合选择器应用的几个例子
Sep 11 Javascript
javascript实现的多个层切换效果通用函数实例
Jul 06 Javascript
JavaScript阻止回车提交表单的方法
Dec 30 Javascript
jquery动态切换背景图片的简单实现方法
May 14 Javascript
React-Native中禁用Navigator手势返回的示例代码
Sep 09 Javascript
vue写一个组件
Apr 09 Javascript
详解vue-cli中模拟数据的两种方法
Jul 03 Javascript
vue实现点击选中,其他的不选中方法
Sep 05 Javascript
vue 本地环境跨域请求proxyTable的方法
Sep 19 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
3.从实例开始
2006/10/09 PHP
解析php session_set_save_handler 函数的用法(mysql)
2013/06/29 PHP
php实现下载限制速度示例分享
2014/02/13 PHP
thinkphp文件处理类Dir.class.php的用法分析
2014/12/08 PHP
php自动给网址加上链接的方法
2015/06/02 PHP
PHP实现根据时间戳获取周几的方法
2016/02/26 PHP
php基于CodeIgniter实现图片上传、剪切功能
2016/05/14 PHP
浅析php如何实现App常用的秒发功能
2016/08/03 PHP
微信公众平台开发教程③ PHP实现微信公众号支付功能图文详解
2019/04/10 PHP
PHP命名空间(namespace)原理与用法详解
2019/12/11 PHP
JavaScript 创建对象
2009/07/17 Javascript
ext 代码生成器
2009/08/07 Javascript
jQuery的12招常用技巧分享
2011/08/08 Javascript
JavaScript避免内存泄露及内存管理技巧
2014/09/05 Javascript
jQuery 获取多选框的值及多选框中文的函数
2016/05/16 Javascript
关于微信上网页图片点击全屏放大效果
2016/12/19 Javascript
jQuery - AJAX load() 实例用法详解
2019/08/27 jQuery
vue中axios的二次封装实例讲解
2019/10/14 Javascript
Javascript模块化机制实现原理详解
2020/04/02 Javascript
JavaScript中的this妙用实例分析
2020/05/09 Javascript
[01:03:31]DOTA2上海特级锦标赛B组资格赛#1 Alliance VS Fnatic第二局
2016/02/26 DOTA
python self,cls,decorator的理解
2009/07/13 Python
Python 查看list中是否含有某元素的方法
2018/06/27 Python
Python父目录、子目录的相互调用方法
2019/02/16 Python
Python/Django后端使用PIL Image生成头像缩略图
2019/04/30 Python
PyCharm 解决找不到新打开项目的窗口问题
2021/01/15 Python
Python实现王者荣耀自动刷金币的完整步骤
2021/01/22 Python
中国领先的专业家电网购平台:国美在线
2016/12/25 全球购物
法警的竞聘演讲稿
2014/01/02 职场文书
《手指教学》反思
2014/02/14 职场文书
售后求职信范文
2014/03/15 职场文书
借名购房协议书范本
2014/10/06 职场文书
钓鱼岛事件感想
2015/08/11 职场文书
2016年优秀少先队辅导员事迹材料
2016/02/26 职场文书
用 Python 元类的特性实现 ORM 框架
2021/05/19 Python
B站评分公认最好看的动漫,你的名字评分9.9,第六备受喜欢
2022/03/18 日漫