利用 GetUserMedia 和 MediaRecorder API 玩转音频录制、播放和下载

开发 前端
GetUserMedia​ 和 MediaRecorder 为网页端带来了强大的媒体处理能力。通过它们,现在我们可以方便地在网页中实现录音、音频效果处理以及实时语音通话等功能了。

在这个数字化的时代,网页端的音频处理能力已经成为一个非常热门的需求。本文将详细介绍如何利用 getUserMedia 和 MediaRecorder 这两个强大的 API,实现网页端音频的录制、处理和播放等功能。

让我们开始这个音频处理的旅程吧!

1、getUserMedia 和 MediaRecorder API 简介

getUserMedia 和 MediaRecorder 是 HTML5 中两个非常重要的 API,用于访问设备媒体输入流并对其进行操作。

getUserMedia

getUserMedia 允许网页端访问用户设备的媒体输入设备,比如摄像头和麦克风。通过该 API,在获得用户授权后,我们可以获取这些媒体流的数据,并用于各种网页应用场景中。

典型的使用方式如下:

// 请求获取音频流
navigator.mediaDevices.getUserMedia({
  audio: true
})
.then(stream => {
  // 在此处理音频流
})

getUserMedia 接受一个 constraints 对象作为参数,通过设置配置来请求获取指定的媒体类型,常见的配置有:

  • audio: Boolean 值,是否获取音频输入。
  • video: Boolean 值,是否获取视频输入。
  • 以及更详细的各种音视频参数设置。

MediaRecorder

MediaRecorder API 可以获取由 getUserMedia 生成的媒体流,并对其进行编码和封装,输出可供播放和传输的媒体文件。

典型的用法如下:

// 获取媒体流
const stream = await navigator.mediaDevices.getUserMedia({ audio: true })

// 创建 MediaRecorder 实例 
const mediaRecorder = new MediaRecorder(stream);

// 注册数据可用事件,以获取编码后的媒体数据块
mediaRecorder.ondataavailable = event => {
  audioChunks.push(event.data);
}

// 开始录制
mediaRecorder.start();

// 录制完成后停止
mediaRecorder.stop(); 

// 将录制的数据组装成 Blob
const blob = new Blob(audioChunks, {
  type: 'audio/mp3' 
});

简单来说,getUserMedia 获取输入流,MediaRecorder 对流进行编码和处理,两者结合就可以实现强大的音视频处理能力。

2、获取和处理音频流

了解了基本 API 使用方法后,我们来看看如何获取和处理音频流。

获取音频流

首先需要调用 getUserMedia 来获取音频流,典型的配置是:

const stream = await navigator.mediaDevices.getUserMedia({
  audio: {
    channelCount: 2,  
    sampleRate: 44100,
    sampleSize: 16,
    echoCancellation: true 
  }
});

我们可以指定声道数、采样率、采样大小等参数来获取音频流。

选择录音设备

使用 navigator.mediaDevices.enumerateDevices() 可以获得所有可用的媒体设备列表,这样我们就可以提供设备选择功能给用户,而不仅仅是默认设备。

举例来说,如果我们想要让用户选择要使用的录音设备:

// 1. 获取录音设备列表
const audioDevices = await navigator.mediaDevices.enumerateDevices();

const mics = audioDevices.filter(d => d.kind === 'audioinput');

// 2. 提供设备选择 UI 供用户选择
const selectedMic = mics[0]; 

// 3. 根据选择配置进行获取流
const constraints = {
  audio: {
    deviceId: selectedMic.deviceId
  }  
};

const stream = await navigator.mediaDevices.getUserMedia(constraints);

这样我们就可以获得用户选择的设备录音了。

处理音频流

获得原始音频流后,我们可以利用 Web Audio API 对其进行处理。

例如添加回声效果:

// 创建音频环境
const audioContext = new AudioContext();

// 创建流源节点
const source = audioContext.createMediaStreamSource(stream);

// 创建回声效果节点
const echo = audioContext.createConvolver();

// 连接处理链
source.connect(echo);
echo.connect(audioContext.destination);

// 加载回声冲击响应并应用
const impulseResponse = await fetch('impulse.wav');
const buffer = await impulseResponse.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(buffer);

echo.buffer = audioBuffer;

通过这样的音频处理链,我们就可以在录音时添加回声、混响等音效了。

3、实现音频的录制和播放

接下来看看如何利用这些 API 实现音频的录制和播放。

录制音频

点击开始录音后,我们进行以下步骤:

  • 调用 getUserMedia 获取音频流。
  • 创建 MediaRecorder 实例,传入音频流。
  • 注册数据可用回调,以获取编码后的音频数据块。
  • 调用 recorder.start() 开始录制。
  • 录制完成后调用 recorder.stop()。
let recorder;
let audioChunks = [];

// 开始录音 handler
const startRecording = async () => {

  const stream = await navigator.mediaDevices.getUserMedia({
    audio: true
  });

  recorder = new MediaRecorder(stream);

  recorder.ondataavailable = event => {
    audioChunks.push(event.data);
  };

  recorder.start();

} 

// 停止录音 handler
const stopRecording = () => {
  if(recorder.state === "recording") {
    recorder.stop();
  }
}

播放音频

录音完成后,我们可以将音频数据组装成一个 Blob 对象,然后赋值给一个 <audio> 元素的 src 属性进行播放:

// 录音停止后
const blob = new Blob(audioChunks, { type: 'audio/ogg' }); 

const audioURL = URL.createObjectURL(blob);

const player = document.querySelector('audio');
player.src = audioURL;

// 调用播放
player.play();

这样就可以播放刚刚录制的音频了。

后续也可以添加下载功能等。

4、音频效果的处理

利用 Web Audio API,我们可以添加各种音频效果,进行音频处理。

例如添加回声效果:

const audioContext = new AudioContext();

// 原始音频节点
const source = audioContext.createMediaStreamSource(stream);

// 回声效果节点
const echo = audioContext.createConvolver();

// 连接处理链
source.connect(echo);
echo.connect(audioContext.destination);

// 加载冲击响应作为回声效果
const impulseResponse = await fetch('impulse.wav');
const arrayBuffer = await impulseResponse.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);

echo.buffer = audioBuffer;

这样在录制时音频流就会经过回声效果处理了。

此外,我们还可以添加混响、滤波、均衡器、压缩等多种音频效果,使得网页端也能处理出专业级的音频作品。

5、实时语音通话的应用

利用 getUserMedia 和 WebRTC 技术,我们还可以在网页端实现实时的点对点语音通话。

简述流程如下:

  • 通过 getUserMedia 获取本地音视频流。
  • 创建 RTCPeerConnection 实例。
  • 将本地流添加到连接上。
  • 交换 ICE 候选信息,建立连接。
  • 当检测到连接后,渲染远端用户的音视频流。

这样就可以实现类似 Skype 的网页端语音通话功能了。

// 1. 获取本地流
const localStream = await navigator.mediaDevices.getUserMedia({
  audio: true,
  video: true
});

// 2. 创建连接对象
const pc = new RTCPeerConnection();

// 3. 添加本地流
localStream.getTracks().forEach(track => pc.addTrack(track, localStream)); 

// 4. 交换 ICE 等信令,处理 ONADDSTREAM 等事件

// ...

// 5. 收到远端流,渲染到页面
pc.ontrack = event => {
  remoteVideo.srcObject = event.streams[0];
}

获取本地输入流后,经过编码和传输就可以实现语音聊天了。

6、兼容性和 Latency 问题

尽管 getUserMedia 和 MediaRecorder 在现代浏览器中已经得到了较好的支持,但由于不同厂商和版本实现存在差异,在实际应用中还是需要注意一些兼容性问题:

  • 检测 API 支持情况,提供降级方案。
  • 注意不同浏览器对 Codec、采样率等参数支持的差异。
  • 封装浏览器差异,提供统一的 API。

此外,录音和播放也存在一定的延迟问题。我们需要针对 Latency 进行优化,比如使用更小的 buffer 大小,压缩数据包大小等方法。

7、结语:开启音频创作的新纪元

getUserMedia 和 MediaRecorder 为网页端带来了强大的媒体处理能力。通过它们,现在我们可以方便地在网页中实现录音、音频效果处理以及实时语音通话等功能了。

当然,在使用时也需要注意浏览器兼容性,以及保障用户隐私等问题。了解这些 API 的工作原理,可以让我们开发出更加优秀的音频类 Web 应用。

责任编辑:姜华 来源: 宇宙一码平川
相关推荐

2012-06-04 13:44:08

2019-01-23 10:00:35

Windows 10录制屏幕音频

2011-12-22 09:54:40

PhoneGap APMedia

2024-04-23 08:24:05

音频Android播放

2024-01-01 09:08:52

API签名验签

2021-12-19 07:22:51

WebRTC分享屏幕前端开发

2021-07-09 09:24:41

鸿蒙HarmonyOS应用

2022-12-25 17:49:55

Ubuntu媒体音频Linux

2015-01-23 09:38:31

2011-08-08 18:19:09

iPhone音频播放

2011-07-27 09:50:31

iPhone AVAudioPla 音频

2011-08-02 16:58:15

iPhone AVAudioPla 音频播放

2011-09-05 18:08:01

MTK音频播放器

2018-03-26 09:17:53

LinuxTlog会话录制

2022-11-24 13:06:32

LinuxAudacity

2018-11-06 09:00:00

2011-07-18 15:32:14

iPhone 录音 播放

2023-09-08 09:10:33

SpringBoot微服务架构

2017-03-20 14:51:33

2014-05-12 10:57:41

TermRecord终端会话
点赞
收藏

51CTO技术栈公众号