浏览器通过原生JS实现录音功能

  • 一. AudioContext介绍
  • 二. getUserMedia介绍
  • 三. MediaRecorder介绍
  • 四. 录音执行流程
  • 五. 主要代码简述
  • 六. Vue样式
  • 七. Vue完整代码
  • 八. 常见问题

一. AudioContext介绍

  • AudioContext接口表示由链接在一起的音频模块构建的音频处理图,每个模块由一个AudioNode表示。音频上下文控制它包含的节点的创建和音频处理或解码的执行。在做任何其他操作之前,您需要创建一个AudioContext对象,因为所有事情都是在上下文中发生的。建议创建一个AudioContext对象并复用它,而不是每次初始化一个新的AudioContext对象,并且可以对多个不同的音频源和管道同时使用一个AudioContext对象。详情
  • AudioContext 兼容写法
if (!window.AudioContext) {window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;
}

二. getUserMedia介绍

  • Navigator.getUserMedia()方法提醒用户需要使用音频(0或者1)和(0或者1)视频输入设备,比如相机,屏幕共享,或者麦克风。如果用户给予许可,successCallback回调就会被调用,MediaStream对象作为回调函数的参数。如果用户拒绝许可或者没有媒体可用,errorCallback就会被调用,类似的,PermissionDeniedError 或者NotFoundError对象作为它的参数。注意,有可能以上两个回调函数都不被调用,因为不要求用户一定作出选择(允许或者拒绝)。详情
  • Navigator.getUserMedia 兼容写法
// 老版浏览器可能根本没有实现mediaDevices, 为其设置一个空对象
if (!navigator.mediaDevices) {navigator.mediaDevices = {};
}
if (!navigator.mediaDevices.getUserMedia) {navigator.mediaDevices.getUserMedia = function (constraints) {let getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;// 浏览器不支持if (!getUserMedia) {return Promise.reject(new Error('您的浏览器暂不支持 getUserMedia !'));}// 包装老版 getUserMediareturn new Promise((resolve, reject) => getUserMedia.call(navigator, constraints, resolve, reject));}
}

三. MediaRecorder介绍

  • MediaDevices 接口提供访问连接媒体输入的设备,如照相机和麦克风,以及屏幕共享等。它可以使你取得任何硬件资源的媒体数据。详情

四. 录音执行流程

#mermaid-svg-ER5rPSrtqI19j8YK .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-ER5rPSrtqI19j8YK .label text{fill:#333}#mermaid-svg-ER5rPSrtqI19j8YK .node rect,#mermaid-svg-ER5rPSrtqI19j8YK .node circle,#mermaid-svg-ER5rPSrtqI19j8YK .node ellipse,#mermaid-svg-ER5rPSrtqI19j8YK .node polygon,#mermaid-svg-ER5rPSrtqI19j8YK .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-ER5rPSrtqI19j8YK .node .label{text-align:center;fill:#333}#mermaid-svg-ER5rPSrtqI19j8YK .node.clickable{cursor:pointer}#mermaid-svg-ER5rPSrtqI19j8YK .arrowheadPath{fill:#333}#mermaid-svg-ER5rPSrtqI19j8YK .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-ER5rPSrtqI19j8YK .flowchart-link{stroke:#333;fill:none}#mermaid-svg-ER5rPSrtqI19j8YK .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-ER5rPSrtqI19j8YK .edgeLabel rect{opacity:0.9}#mermaid-svg-ER5rPSrtqI19j8YK .edgeLabel span{color:#333}#mermaid-svg-ER5rPSrtqI19j8YK .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-ER5rPSrtqI19j8YK .cluster text{fill:#333}#mermaid-svg-ER5rPSrtqI19j8YK div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-ER5rPSrtqI19j8YK .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-ER5rPSrtqI19j8YK text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-ER5rPSrtqI19j8YK .actor-line{stroke:grey}#mermaid-svg-ER5rPSrtqI19j8YK .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-ER5rPSrtqI19j8YK .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-ER5rPSrtqI19j8YK #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-ER5rPSrtqI19j8YK .sequenceNumber{fill:#fff}#mermaid-svg-ER5rPSrtqI19j8YK #sequencenumber{fill:#333}#mermaid-svg-ER5rPSrtqI19j8YK #crosshead path{fill:#333;stroke:#333}#mermaid-svg-ER5rPSrtqI19j8YK .messageText{fill:#333;stroke:#333}#mermaid-svg-ER5rPSrtqI19j8YK .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-ER5rPSrtqI19j8YK .labelText,#mermaid-svg-ER5rPSrtqI19j8YK .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-ER5rPSrtqI19j8YK .loopText,#mermaid-svg-ER5rPSrtqI19j8YK .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-ER5rPSrtqI19j8YK .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-ER5rPSrtqI19j8YK .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-ER5rPSrtqI19j8YK .noteText,#mermaid-svg-ER5rPSrtqI19j8YK .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-ER5rPSrtqI19j8YK .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-ER5rPSrtqI19j8YK .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-ER5rPSrtqI19j8YK .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-ER5rPSrtqI19j8YK .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ER5rPSrtqI19j8YK .section{stroke:none;opacity:0.2}#mermaid-svg-ER5rPSrtqI19j8YK .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-ER5rPSrtqI19j8YK .section2{fill:#fff400}#mermaid-svg-ER5rPSrtqI19j8YK .section1,#mermaid-svg-ER5rPSrtqI19j8YK .section3{fill:#fff;opacity:0.2}#mermaid-svg-ER5rPSrtqI19j8YK .sectionTitle0{fill:#333}#mermaid-svg-ER5rPSrtqI19j8YK .sectionTitle1{fill:#333}#mermaid-svg-ER5rPSrtqI19j8YK .sectionTitle2{fill:#333}#mermaid-svg-ER5rPSrtqI19j8YK .sectionTitle3{fill:#333}#mermaid-svg-ER5rPSrtqI19j8YK .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ER5rPSrtqI19j8YK .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-ER5rPSrtqI19j8YK .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ER5rPSrtqI19j8YK .grid path{stroke-width:0}#mermaid-svg-ER5rPSrtqI19j8YK .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-ER5rPSrtqI19j8YK .task{stroke-width:2}#mermaid-svg-ER5rPSrtqI19j8YK .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ER5rPSrtqI19j8YK .taskText:not([font-size]){font-size:11px}#mermaid-svg-ER5rPSrtqI19j8YK .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ER5rPSrtqI19j8YK .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-ER5rPSrtqI19j8YK .task.clickable{cursor:pointer}#mermaid-svg-ER5rPSrtqI19j8YK .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-ER5rPSrtqI19j8YK .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-ER5rPSrtqI19j8YK .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-ER5rPSrtqI19j8YK .taskText0,#mermaid-svg-ER5rPSrtqI19j8YK .taskText1,#mermaid-svg-ER5rPSrtqI19j8YK .taskText2,#mermaid-svg-ER5rPSrtqI19j8YK .taskText3{fill:#fff}#mermaid-svg-ER5rPSrtqI19j8YK .task0,#mermaid-svg-ER5rPSrtqI19j8YK .task1,#mermaid-svg-ER5rPSrtqI19j8YK .task2,#mermaid-svg-ER5rPSrtqI19j8YK .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-ER5rPSrtqI19j8YK .taskTextOutside0,#mermaid-svg-ER5rPSrtqI19j8YK .taskTextOutside2{fill:#000}#mermaid-svg-ER5rPSrtqI19j8YK .taskTextOutside1,#mermaid-svg-ER5rPSrtqI19j8YK .taskTextOutside3{fill:#000}#mermaid-svg-ER5rPSrtqI19j8YK .active0,#mermaid-svg-ER5rPSrtqI19j8YK .active1,#mermaid-svg-ER5rPSrtqI19j8YK .active2,#mermaid-svg-ER5rPSrtqI19j8YK .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-ER5rPSrtqI19j8YK .activeText0,#mermaid-svg-ER5rPSrtqI19j8YK .activeText1,#mermaid-svg-ER5rPSrtqI19j8YK .activeText2,#mermaid-svg-ER5rPSrtqI19j8YK .activeText3{fill:#000 !important}#mermaid-svg-ER5rPSrtqI19j8YK .done0,#mermaid-svg-ER5rPSrtqI19j8YK .done1,#mermaid-svg-ER5rPSrtqI19j8YK .done2,#mermaid-svg-ER5rPSrtqI19j8YK .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-ER5rPSrtqI19j8YK .doneText0,#mermaid-svg-ER5rPSrtqI19j8YK .doneText1,#mermaid-svg-ER5rPSrtqI19j8YK .doneText2,#mermaid-svg-ER5rPSrtqI19j8YK .doneText3{fill:#000 !important}#mermaid-svg-ER5rPSrtqI19j8YK .crit0,#mermaid-svg-ER5rPSrtqI19j8YK .crit1,#mermaid-svg-ER5rPSrtqI19j8YK .crit2,#mermaid-svg-ER5rPSrtqI19j8YK .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-ER5rPSrtqI19j8YK .activeCrit0,#mermaid-svg-ER5rPSrtqI19j8YK .activeCrit1,#mermaid-svg-ER5rPSrtqI19j8YK .activeCrit2,#mermaid-svg-ER5rPSrtqI19j8YK .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-ER5rPSrtqI19j8YK .doneCrit0,#mermaid-svg-ER5rPSrtqI19j8YK .doneCrit1,#mermaid-svg-ER5rPSrtqI19j8YK .doneCrit2,#mermaid-svg-ER5rPSrtqI19j8YK .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-ER5rPSrtqI19j8YK .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-ER5rPSrtqI19j8YK .milestoneText{font-style:italic}#mermaid-svg-ER5rPSrtqI19j8YK .doneCritText0,#mermaid-svg-ER5rPSrtqI19j8YK .doneCritText1,#mermaid-svg-ER5rPSrtqI19j8YK .doneCritText2,#mermaid-svg-ER5rPSrtqI19j8YK .doneCritText3{fill:#000 !important}#mermaid-svg-ER5rPSrtqI19j8YK .activeCritText0,#mermaid-svg-ER5rPSrtqI19j8YK .activeCritText1,#mermaid-svg-ER5rPSrtqI19j8YK .activeCritText2,#mermaid-svg-ER5rPSrtqI19j8YK .activeCritText3{fill:#000 !important}#mermaid-svg-ER5rPSrtqI19j8YK .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ER5rPSrtqI19j8YK g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-ER5rPSrtqI19j8YK g.classGroup text .title{font-weight:bolder}#mermaid-svg-ER5rPSrtqI19j8YK g.clickable{cursor:pointer}#mermaid-svg-ER5rPSrtqI19j8YK g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-ER5rPSrtqI19j8YK g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-ER5rPSrtqI19j8YK .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-ER5rPSrtqI19j8YK .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-ER5rPSrtqI19j8YK .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-ER5rPSrtqI19j8YK .dashed-line{stroke-dasharray:3}#mermaid-svg-ER5rPSrtqI19j8YK #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ER5rPSrtqI19j8YK #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ER5rPSrtqI19j8YK #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-ER5rPSrtqI19j8YK #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-ER5rPSrtqI19j8YK #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ER5rPSrtqI19j8YK #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ER5rPSrtqI19j8YK #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ER5rPSrtqI19j8YK #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-ER5rPSrtqI19j8YK .commit-id,#mermaid-svg-ER5rPSrtqI19j8YK .commit-msg,#mermaid-svg-ER5rPSrtqI19j8YK .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ER5rPSrtqI19j8YK .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ER5rPSrtqI19j8YK .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ER5rPSrtqI19j8YK g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ER5rPSrtqI19j8YK g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-ER5rPSrtqI19j8YK g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-ER5rPSrtqI19j8YK g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-ER5rPSrtqI19j8YK g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-ER5rPSrtqI19j8YK g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-ER5rPSrtqI19j8YK .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-ER5rPSrtqI19j8YK .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-ER5rPSrtqI19j8YK .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-ER5rPSrtqI19j8YK .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-ER5rPSrtqI19j8YK .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-ER5rPSrtqI19j8YK .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-ER5rPSrtqI19j8YK .edgeLabel text{fill:#333}#mermaid-svg-ER5rPSrtqI19j8YK .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-ER5rPSrtqI19j8YK .node circle.state-start{fill:black;stroke:black}#mermaid-svg-ER5rPSrtqI19j8YK .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-ER5rPSrtqI19j8YK #statediagram-barbEnd{fill:#9370db}#mermaid-svg-ER5rPSrtqI19j8YK .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-ER5rPSrtqI19j8YK .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-ER5rPSrtqI19j8YK .statediagram-state .divider{stroke:#9370db}#mermaid-svg-ER5rPSrtqI19j8YK .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-ER5rPSrtqI19j8YK .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-ER5rPSrtqI19j8YK .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-ER5rPSrtqI19j8YK .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-ER5rPSrtqI19j8YK .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-ER5rPSrtqI19j8YK .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-ER5rPSrtqI19j8YK .note-edge{stroke-dasharray:5}#mermaid-svg-ER5rPSrtqI19j8YK .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-ER5rPSrtqI19j8YK .error-icon{fill:#522}#mermaid-svg-ER5rPSrtqI19j8YK .error-text{fill:#522;stroke:#522}#mermaid-svg-ER5rPSrtqI19j8YK .edge-thickness-normal{stroke-width:2px}#mermaid-svg-ER5rPSrtqI19j8YK .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-ER5rPSrtqI19j8YK .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-ER5rPSrtqI19j8YK .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-ER5rPSrtqI19j8YK .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-ER5rPSrtqI19j8YK .marker{fill:#333}#mermaid-svg-ER5rPSrtqI19j8YK .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;} #mermaid-svg-ER5rPSrtqI19j8YK {color: rgba(0, 0, 0, 0.75);font: ;}

打开
打开失败
打开成功
创建一个新的音视频对象
创建音视频源
将音视频源 链接 到新音视频对象 中
创建媒体录制接口对象
录制
录制结束
getUserMedia获取音频输入设备
打开设备
打印日志
AudioContext获取实例
audioContext.createMediaStreamDestination
audioContext.createMediaStreamSource_stream_
new MediaRecorder_destination.stream_
开始录制
创建本地音视频文件URL.createObjectURL_blob_

五. 主要代码简述

methods: {start() {// 停止之前的录制内容this.$mediaRecorder && this.$mediaRecorder.stop();if (!window.AudioContext) {window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;}// 参考 https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/getUserMedia// 老版浏览器可能根本没有实现mediaDevices, 为其设置一个空对象if (!navigator.mediaDevices) {navigator.mediaDevices = {};}if (!navigator.mediaDevices.getUserMedia) {navigator.mediaDevices.getUserMedia = function (constraints) {let getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;// 浏览器不支持if (!getUserMedia) {return Promise.reject(new Error('您的浏览器暂不支持 getUserMedia !'));}// 包装老版 getUserMediareturn new Promise((resolve, reject) => getUserMedia.call(navigator, constraints, resolve, reject));}}// 参数// let constraints = {audio: true, video: true}; // 请求不带任何参数的音频和视频let constraints = {audio: true};  // 请求音频let mediaStream = navigator.mediaDevices.getUserMedia(constraints);mediaStream.then((stream) => {console.info("打开成功!")let audioContext = new AudioContext();// 创建一个新的音视频对象let destination = audioContext.createMediaStreamDestination();// 创建音视频源let mediaStreamSource = audioContext.createMediaStreamSource(stream);// 将音视频源 链接 到新音视频对象 中mediaStreamSource.connect(destination);// 参考 https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/MediaRecorder// 媒体录制接口let mediaRecorder = new MediaRecorder(destination.stream, {audioBitsPerSecond: 16000});let chunks = [];// 有可用数据流时触发,e.data即需要的音视频数据mediaRecorder.ondataavailable = (e) => chunks.push(e.data);// 间视频录制结束时触发mediaRecorder.onstop = () => {// 通过Blob数据块, 合成完整的Blob块数据let blob = new Blob(chunks, {'type': 'audio/mpeg'});// 通过Blob合建对象URL本地地址let url = URL.createObjectURL(blob);// 绑定到 audio 元素上this.$refs.recordPlayer.src = url;};// 將 mediaRecorder 对象扔到全局this中, 用于其他方法调用this.$mediaRecorder = mediaRecorder;// 录制开始mediaRecorder.start();}, () => {console.log("打开失败!");});},stop() {// 返回录制的二进制数据, 调用这个方法后会生成一个新的Blob对象this.$mediaRecorder.requestData();// 停止录制this.$mediaRecorder.stop();},
},

六. Vue样式

七. Vue完整代码

<template><div style="height: 100%; width: 100%;"><div><audio ref="recordPlayer" controls src=""/><div></div><ButtonGroup><Button size="small" @click="start">开始</Button><Button size="small" @click="stop">结束</Button></ButtonGroup></div></div>
</template><script>export default {name: "home",mounted() {},methods: {start() {// 停止之前的录制内容this.$mediaRecorder && this.$mediaRecorder.stop();if (!window.AudioContext) {window.AudioContext = window.AudioContext || window.webkitAudioContext || window.mozAudioContext || window.msAudioContext;}// 参考 https://developer.mozilla.org/zh-CN/docs/Web/API/MediaDevices/getUserMedia// 老版浏览器可能根本没有实现mediaDevices, 为其设置一个空对象if (!navigator.mediaDevices) {navigator.mediaDevices = {};}if (!navigator.mediaDevices.getUserMedia) {navigator.mediaDevices.getUserMedia = function (constraints) {let getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia;// 浏览器不支持if (!getUserMedia) {return Promise.reject(new Error('您的浏览器暂不支持 getUserMedia !'));}// 包装老版 getUserMediareturn new Promise((resolve, reject) => getUserMedia.call(navigator, constraints, resolve, reject));}}// 参数// let constraints = {audio: true, video: true}; // 请求不带任何参数的音频和视频let constraints = {audio: true};  // 请求音频let mediaStream = navigator.mediaDevices.getUserMedia(constraints);mediaStream.then((stream) => {console.info("打开成功!")let audioContext = new AudioContext();// 创建一个新的音视频对象let destination = audioContext.createMediaStreamDestination();// 创建音视频源let mediaStreamSource = audioContext.createMediaStreamSource(stream);// 将音视频源 链接 到新音视频对象 中mediaStreamSource.connect(destination);// 参考 https://developer.mozilla.org/en-US/docs/Web/API/MediaRecorder/MediaRecorder// 媒体录制接口let mediaRecorder = new MediaRecorder(destination.stream, {audioBitsPerSecond: 16000});let chunks = [];// 有可用数据流时触发,e.data即需要的音视频数据mediaRecorder.ondataavailable = (e) => chunks.push(e.data);// 间视频录制结束时触发mediaRecorder.onstop = () => {// 通过Blob数据块, 合成完整的Blob块数据let blob = new Blob(chunks, {'type': 'audio/mpeg'});// 通过Blob合建对象URL本地地址let url = URL.createObjectURL(blob);// 绑定到 audio 元素上this.$refs.recordPlayer.src = url;};// 將 mediaRecorder 对象扔到全局this中, 用于其他方法调用this.$mediaRecorder = mediaRecorder;// 录制开始mediaRecorder.start();}, () => {console.log("打开失败!");});},stop() {// 返回录制的二进制数据, 调用这个方法后会生成一个新的Blob对象this.$mediaRecorder.requestData();// 停止录制this.$mediaRecorder.stop();},},}
</script><style scoped>
</style>

八. 常见问题

页面开始录音时, Console提示 Cannot read property ‘getUserMedia’ of undefined .
该问题可以通过以下几个方式解决:

  1. 访问localhost, 或127.0.0.1地址解决.
  2. Vue或其他引擎启用Https访问.
  3. 修改浏览器Insecure origins treated as secure配置, 谷歌浏览器地址栏打开chrome://flags/#unsafely-treat-insecure-origin-as-secure, 找到Insecure origins treated as secure, 启用该配置, 然后填写自己的IP地址, 包括Port, 最后Relaunch.

浏览器通过原生JS实现录音功能相关推荐

  1. 原生JS与Jquery删除iframe并释放内存(IE)

    当项目以tab页签方式打开多个iframe窗口时,关闭tab页签同时也需要关闭iframe并释放内存资源,主要是针对IE浏览器. 原生js /** * 销毁iframe,释放iframe所占用的内存. ...

  2. [完美]原生JS获取浏览器版本判断--支持Edge,IE,Chrome,Firefox,Opera,Safari,以及各种使用Chrome和IE混合内核的浏览器...

    [完美]原生JS获取浏览器版本判断--支持Edge,IE,Chrome,Firefox,Opera,Safari,以及各种使用Chrome和IE混合内核的浏览器 原文:[完美]原生JS获取浏览器版本判 ...

  3. html5图片剪切板,原生js实现基于base64数据复制图片到剪切板,可以粘贴出图片,模拟浏览器复制功能。...

    原生js实现基于base64数据复制图片到剪切板,可以粘贴出图片,模拟浏览器复制功能.前言: 初次发帖排版略丑,见谅.之前我们这边有个需求就是说,前端通过canvas截图然后, 点击一个按钮实现复制截 ...

  4. js html颜色代码,原生js编写的浏览器安全色网页拾色器色盘 生成颜色代码

    原生js编写的浏览器安全色网页拾色器 by js.alixixi.com #abc-colorPicker .colorPick-close,#filter-colorPicker .colorPic ...

  5. 已解决:H5移动端网页实现录音功能,js实现录音功能,包括安卓webview接口也可以使用

    遇到一个需求,需要做一个手机网页录音的功能,嵌入到webview中去,用安卓原生录音倒是可以,但是想着尽量去安卓化开发,就想着用纯的js前端代码去实现录音功能. 在 Web 应用程序中,JavaScr ...

  6. 原生js循环展示dom_【前端面试】用一道题讲 js 的事件循环队列

    昨天去面了滴滴,一口气面了三面,考了 promise 和事件循环.之前的猿辅导也考察了这些,几乎所有的大厂中厂都一定会考原生 js 的事件循环队列. 今天,我把昨天考察的原题拿出来分析一下. setT ...

  7. 蓝鸥原生JS:js的历史及JavaScript的优缺点

    蓝鸥原生JS:js的历史及JavaScript的优缺点 蓝鸥零基础学习HTML5-html+css基础 http://11824614.blog.51cto.com/11814614/1852769 ...

  8. 用原生 js jquery 实现知乎收起答案功能

    Update 2016.12.7 已封装为插件 原生 js 插件$ npm install foldcontent-zhihu@">=3.0.12" --save Usage ...

  9. 移动端实现文字轮播_使用原生JS实现移动端图片轮播效果(一)

    PC端上实现图片轮播效果非常简单,只要通过使用click事件就可以非常简单的实现效果,但是在移动端上,就要通过核心的touch事件来实现.话不多说,现在我们就开始移动端轮播效果的实现. 首先就是原生J ...

最新文章

  1. java怎么建立内部类_语法 - 是否可以在Java静态中创建匿名内部类?
  2. 这不关我的事,别烦我!
  3. Windows下安装配置Maven
  4. 设计模式的七大设计原则:其六:迪米特法则
  5. .Net Discovery系列之三 深入理解.Net垃圾收集机制(上)
  6. 动图处理_终于找到了,最全的废气处理动图
  7. 量化研究: Julia还是Matlab?
  8. js调用摄像头拍照,js调用摄像头在线拍照,js调用电脑摄像头拍照
  9. html实训大作业《基于HTML+CSS+JavaScript红色文化传媒网站(20页)》
  10. 小学计算机英语,小学英语流利读电脑版
  11. 二倍图三倍图什么意思_iOS开发中的二倍图、三倍图
  12. JavaScript 更新Dom节点
  13. 新胖子公式(java)
  14. 欧拉函数与积性函数(互质数)
  15. 数据防泄漏具备哪些特性?
  16. 定了!AI视觉泰斗朱松纯教授归国就任北大人工智能研究院院长
  17. QuickBooks2020中文版
  18. 测量学—数字测图原理与方法
  19. 该产品与此版 VMware Workstation 不兼容,因此无法使用
  20. CMake Warning at cmake/OpenCVGenSetupVars.cmake:54 (message):

热门文章

  1. DFRobot行业AI开发者大赛--LattePandaDelta
  2. 如何将某一文件添加到信任列表?
  3. opencv+mnist识别手写数字串
  4. 十五、Fluent湿空气模拟-组分输运模型
  5. 计算机基础教学质量分析报告,张丹菲信息技术质量分析报告1
  6. 有哪些主流智能音箱品牌值得买?小米、华为、苹果、百度
  7. 原生Android打造一个炫酷的底部导航栏
  8. 酷语言COOLang
  9. STM32驱动_cc2420
  10. 海康威视SDK控制台程序consoleDemo获取视频通道参数