本文详细介绍如何利用HTML5的getUserMedia API和Web Audio API在浏览器中实现网页录音功能。涵盖从麦克风权限获取、音频流处理、实时录音控制到数据编码保存的完整流程,并提供可直接运行的代码示例。
1. 获取用户媒体设备:getUserMedia基础
getUserMedia允许网页通过JavaScript直接访问用户的摄像头或麦克风。调用navigator.mediaDevices.getUserMedia()方法,传入包含audio和video属性的约束对象,返回一个Promise对象,成功时携带MediaStream对象。
- navigator.mediaDevices.getUserMedia({ audio: true, video: false })
- .then(function(stream) {
- // stream 即来自麦克风的音频流
- })
- .catch(function(err) {
- console.error(err.name, err.message);
- });
复制代码
注意:该API必须在HTTPS或localhost下使用,否则会抛出SecurityError。
2. 错误处理与浏览器兼容性检查
常见的错误类型包括:
- NotAllowedError:用户拒绝授权
- NotFoundError:未找到麦克风设备
- NotReadableError:设备被占用或不可读
- OverconstrainedError:约束参数无法满足
- AbortError:用户中途取消
- SecurityError:非安全上下文
- TypeError:参数格式错误
推荐使用switch语句按错误名提示用户:
- navigator.mediaDevices.getUserMedia({ audio: true })
- .catch(function(error) {
- switch(error.name) {
- case 'NotAllowedError':
- alert('请允许麦克风访问权限');
- break;
- case 'NotFoundError':
- alert('未检测到麦克风设备');
- break;
- default:
- alert('设备访问失败: ' + error.message);
- }
- });
复制代码
调用getUserMedia前建议先进行特性检测:
- function supportsGetUserMedia() {
- return !!(navigator.mediaDevices && navigator.mediaDevices.getUserMedia);
- }
- if (!supportsGetUserMedia()) {
- alert('当前浏览器不支持getUserMedia API');
- return;
- }
复制代码
3. 使用Web Audio API处理音频流
获取的MediaStream可以通过Web Audio API进行实时处理。首先创建AudioContext,然后通过createMediaStreamSource()将流转换为音频源节点:
- const audioContext = new AudioContext();
- const source = audioContext.createMediaStreamSource(stream);
- // 可直接连接到扬声器输出
- source.connect(audioContext.destination);
复制代码
若要实现录音,需要创建MediaStreamAudioDestinationNode作为音频录制目的地:
- const dest = audioContext.createMediaStreamDestination();
- source.connect(dest);
- // dest.stream 包含了经过处理的音频流
复制代码
使用AnalyserNode可以实现音频可视化:
- const analyser = audioContext.createAnalyser();
- analyser.fftSize = 2048;
- source.connect(analyser);
- const bufferLength = analyser.frequencyBinCount;
- const dataArray = new Uint8Array(bufferLength);
- function draw() {
- requestAnimationFrame(draw);
- analyser.getByteFrequencyData(dataArray);
- // 可将dataArray绘制到canvas上
- }
- draw();
复制代码
4. 设计AudioRecorder类控制录音流程
封装一个AudioRecorder类,管理录音开始、暂停、恢复、停止及数据获取:
- class AudioRecorder {
- constructor(stream) {
- this.stream = stream;
- this.audioContext = new AudioContext();
- this.source = this.audioContext.createMediaStreamSource(stream);
- this.dest = this.audioContext.createMediaStreamDestination();
- this.source.connect(this.dest);
- this.mediaRecorder = new MediaRecorder(this.dest.stream);
- this.chunks = [];
- this.recording = false;
- this.paused = false;
- this.mediaRecorder.ondataavailable = (e) => {
- if (e.data.size > 0) this.chunks.push(e.data);
- };
- }
- start() {
- if (this.recording) return;
- this.chunks = [];
- this.mediaRecorder.start();
- this.recording = true;
- }
- pause() {
- if (!this.recording || this.paused) return;
- this.mediaRecorder.pause();
- this.paused = true;
- }
- resume() {
- if (!this.paused) return;
- this.mediaRecorder.resume();
- this.paused = false;
- }
- stop() {
- return new Promise((resolve) => {
- this.mediaRecorder.onstop = () => {
- const blob = new Blob(this.chunks, { type: 'audio/webm' });
- resolve(blob);
- };
- this.mediaRecorder.stop();
- this.recording = false;
- });
- }
- }
复制代码
使用示例:
- const recorder = new AudioRecorder(stream);
- recorder.start();
- setTimeout(async () => {
- const blob = await recorder.stop();
- // blob即为录音文件
- }, 5000);
复制代码
5. 录音文件编码与保存
MediaRecorder默认输出格式为浏览器支持的编码(如webm)。若需保存为MP3,可使用第三方编码器(如lamejs),但更简单的方式是直接使用MediaRecorder的mimeType参数:
- const recorder = new MediaRecorder(stream, { mimeType: 'audio/webm;codecs=opus' });
复制代码
保存到本地时,利用URL.createObjectURL创建下载链接:
- const blob = new Blob(chunks, { type: 'audio/webm' });
- const url = URL.createObjectURL(blob);
- const a = document.createElement('a');
- a.href = url;
- a.download = 'recording.webm';
- a.click();
- URL.revokeObjectURL(url);
复制代码
如需上传云端,可使用fetch发送FormData:
- async function uploadAudio(blob, uploadUrl) {
- const formData = new FormData();
- formData.append('file', blob, 'audio.webm');
- const response = await fetch(uploadUrl, {
- method: 'POST',
- body: formData
- });
- const result = await response.json();
- return result.link;
- }
复制代码
6. 安全限制与最佳实践
- 始终在HTTPS环境下使用getUserMedia。
- 录音前请求用户授权,并在UI中给出明确提示。
- 停止录音后及时释放MediaStream,调用stream.getTracks().forEach(track => track.stop())。
- 注意移动端浏览器可能要求用户手势触发(如点击按钮)。
- 对于长时间录音,定期清理内存中的chunks,或采用分段保存。
综上所述,通过组合getUserMedia、Web Audio API和MediaRecorder,可以在纯前端实现功能完整的网页录音功能。配合适当的错误处理与性能优化,该方案可应用于在线教育、会议录音、语音笔记等场景。 |