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 相关文章推荐
IE和Firefox的Javascript兼容性总结[推荐收藏]
Oct 19 Javascript
Extjs NumberField后面加单位实现思路
Jul 30 Javascript
js为数字添加逗号并格式化数字的代码
Aug 23 Javascript
使用js实现关闭js弹出层的窗口
Feb 10 Javascript
一个JavaScript处理textarea中的字符成每一行实例
Sep 22 Javascript
javascript中$(function() {});写与不写有哪些区别
Aug 10 Javascript
jQuery实现的fixedMenu下拉菜单效果代码
Aug 24 Javascript
谈谈JavaScript中function多重理解
Aug 28 Javascript
Extjs实现下拉菜单效果
Apr 01 Javascript
node.js中cluster的使用教程
Jun 09 Javascript
javascript闭包的使用之按钮切换功能
Aug 30 Javascript
小程序实现背景音乐播放和暂停
Jun 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
《PHP边学边教》(02.Apache+PHP环境配置――下篇)
2006/12/13 PHP
php中get_object_vars()方法用法实例
2015/02/08 PHP
CodeMirror2 IE7/IE8 下面未知运行时错误的解决方法
2012/03/29 Javascript
Jquery选择子控件&quot;大于号&quot;和&quot; &quot;区别介绍及使用示例
2013/06/25 Javascript
jQuery使用attr()方法同时设置多个属性值用法实例
2015/03/26 Javascript
Jquery时间轴特效(三种不同类型)
2015/11/02 Javascript
Javascript基础_标记文字的实现方法
2016/06/14 Javascript
基于vue2.0实现的级联选择器
2017/06/09 Javascript
JS自动生成动态HTML验证码页面
2017/06/14 Javascript
Angular指令之restict匹配模式的详解
2017/07/27 Javascript
浅析Vue实例以及生命周期
2018/08/14 Javascript
微信小程序使用npm支持踩坑
2018/11/07 Javascript
详解js中let与var声明变量的区别
2020/04/05 Javascript
es6中reduce的基本使用方法
2019/09/10 Javascript
关于ES6尾调用优化的使用
2020/09/11 Javascript
[01:03:47]VP vs NewBee Supermajor 胜者组 BO3 第一场 6.5
2018/06/06 DOTA
python 写的一个爬虫程序源码
2016/02/28 Python
python僵尸进程产生的原因
2017/07/21 Python
python3 kmp 字符串匹配的方法
2018/07/07 Python
Python http接口自动化测试框架实现方法示例
2018/12/06 Python
Pycharm远程调试原理及具体配置详解
2019/08/08 Python
python 数据生成excel导出(xlwt,wlsxwrite)代码实例
2019/08/23 Python
详解使用python3.7配置开发钉钉群自定义机器人(2020年新版攻略)
2020/04/01 Python
canvas像素点操作之视频绿幕抠图
2018/09/11 HTML / CSS
SneakerStudio英国:最佳运动鞋商店
2019/05/22 全球购物
介绍一下SOA和SOA的基本特征
2016/02/24 面试题
毕业生应聘幼儿园的自荐信
2013/11/20 职场文书
中专生的个人自我评价
2013/12/11 职场文书
家具厂厂长岗位职责
2014/01/01 职场文书
在校大学生自我评价范文
2014/09/12 职场文书
党员自我评议对照检查材料
2014/09/27 职场文书
爱的教育读书笔记
2015/06/26 职场文书
学习经验交流会演讲稿
2015/11/02 职场文书
三好学生评选事迹材料(2016精选版)
2016/02/25 职场文书
mysql5.7的安装及Navicate长久免费使用的实现过程
2021/11/17 MySQL
Go语言怎么使用变长参数函数
2022/07/15 Golang