推荐答案
// www.javascriptcn.com code example
// 1. 获取媒体设备 (麦克风和摄像头)
async function getMediaStream() {
try {
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: true, // 或 video: { facingMode: 'user' } 前置摄像头, 或 video: { facingMode: 'environment' } 后置摄像头
});
return stream;
} catch (err) {
console.error("获取媒体设备失败:", err);
throw err;
}
}
// 2. 创建 MediaRecorder 对象
function createMediaRecorder(stream, mimeType) {
const options = { mimeType }; // 可选:指定 mimeType,例如 'video/webm;codecs=vp9' 或 'audio/webm'
try {
const recorder = new MediaRecorder(stream, options);
return recorder;
} catch (err){
console.error("创建MediaRecorder失败", err);
throw err;
}
}
// 3. 录制数据处理
function handleDataAvailable(event, chunks) {
if (event.data && event.data.size > 0) {
chunks.push(event.data);
}
}
// 4. 停止录制
function stopRecording(recorder, chunks, mediaType) {
return new Promise((resolve) => {
recorder.onstop = () => {
const blob = new Blob(chunks, { type: `${mediaType}/webm` }); // 可根据需要修改mimeType
const url = URL.createObjectURL(blob);
resolve({ blob, url });
chunks.length = 0; // 清空 chunks
};
recorder.stop();
});
}
// 5. 开始录制
async function startRecording(mediaType) {
try {
const stream = await getMediaStream();
const mimeType = mediaType === 'video' ? 'video/webm;codecs=vp9' : 'audio/webm';
const recorder = createMediaRecorder(stream, mimeType);
const chunks = [];
recorder.ondataavailable = (event) => handleDataAvailable(event, chunks);
recorder.start();
return {recorder, stream, chunks};
} catch(err){
console.error("录制失败:", err)
}
}
// 示例使用:
async function recordAndProcess(mediaType) {
const { recorder, stream, chunks } = await startRecording(mediaType);
// 假设 5 秒后停止录制
setTimeout(async () => {
const result = await stopRecording(recorder, chunks, mediaType);
stream.getTracks().forEach(track => track.stop()); // 停止媒体流
console.log(`录制完成,blob数据:`, result.blob);
console.log(`录制完成,url数据:`, result.url);
if (mediaType === 'video') {
const videoElement = document.createElement('video');
videoElement.src = result.url;
videoElement.controls = true;
document.body.appendChild(videoElement);
} else {
const audioElement = document.createElement('audio');
audioElement.src = result.url;
audioElement.controls = true;
document.body.appendChild(audioElement);
}
}, 5000);
}
// 录制视频
//recordAndProcess('video');
// 录制音频
//recordAndProcess('audio');
本题详细解读
1. MediaRecorder API 简介
MediaRecorder API 允许 Web 应用程序捕获来自媒体设备(如麦克风和摄像头)的音频和视频数据,并将它们编码为可存储或传输的格式。它是 HTML5 提供的一个强大的 API,主要用于实现浏览器端的媒体录制功能。
2. 主要步骤
使用 MediaRecorder API 进行音频和视频录制,主要包括以下步骤:
- 获取媒体流 (
getUserMedia): 使用navigator.mediaDevices.getUserMedia()获取用户授权并返回一个包含媒体流的MediaStream对象。 - 创建
MediaRecorder对象: 使用new MediaRecorder(stream, options)创建MediaRecorder实例,其中stream是第一步获取的媒体流,options可选,用于配置录制参数 (如mimeType)。 - 监听
dataavailable事件:MediaRecorder会周期性触发dataavailable事件,每次事件都会返回录制好的数据块(chunk)。我们需要将这些数据块收集起来。 - 开始录制 (
start()): 调用MediaRecorder.start()方法开始录制。 - 停止录制 (
stop()): 调用MediaRecorder.stop()方法停止录制。停止后会触发stop事件。 - 处理录制的数据: 在
stop事件处理程序中,将收集的数据块组合成一个Blob对象,然后可以生成可用于下载或播放的 URL 。 - 停止媒体流: 在完成录制后,应该停止媒体流,释放资源。
3. 代码详解
getMediaStream()函数:- 使用
navigator.mediaDevices.getUserMedia()获取媒体流,请求音频和视频权限。 audio: true允许访问麦克风,video: true允许访问摄像头。facingMode可以设置前后摄像头。- 使用
async/await处理 Promise,简化异步代码。 - 如果权限获取失败,则抛出错误。
- 使用
createMediaRecorder()函数:- 创建
MediaRecorder实例,传入媒体流和 mimeType。 mimeType可选,用于指定编码格式。- 如果创建失败,则抛出错误。
- 创建
handleDataAvailable()函数:- 监听
dataavailable事件,将录制的数据块(event.data)添加到chunks数组中。
- 监听
stopRecording()函数:- 监听
stop事件,在stop事件中,将chunks数组中的数据组合成一个Blob对象。 - 使用
URL.createObjectURL()创建 blob 的 URL,以便播放或下载。 - 使用
Promise包装异步操作,方便后续使用。 - 清空chunks数组。
- 监听
startRecording()函数:- 使用
getMediaStream获取媒体流。 - 使用
createMediaRecorder创建MediaRecorder实例。 - 设置
ondataavailable事件处理函数。 - 使用
recorder.start()方法开始录制。 - 返回
recorder,stream,chunks.
- 使用
recordAndProcess()函数:- 调用
startRecording开始录制。 - 设置定时器,在 5 秒后停止录制。
- 停止媒体流。
- 根据录制的媒体类型,创建
audio或者video标签,并添加到页面中。
- 调用
4. 重要注意事项
- 用户权限:
getUserMedia()需要用户授权才能访问麦克风和摄像头。 - MIME 类型: 选择合适的
mimeType非常重要,不同的浏览器支持的编码格式可能不同。 - 错误处理: 需要处理
getUserMedia和MediaRecorder创建过程中可能出现的错误。 - 资源释放: 录制完成后需要停止媒体流,释放资源。
- 浏览器兼容性:
MediaRecorderAPI 的浏览器支持情况需要关注。 - 安全性: 需要通过 HTTPS 访问,才能使用
getUserMedia和MediaRecorderAPI。