
从零开始:MediaRecorder录制功能实现全流程
其实MediaRecorder没你想的那么复杂,核心就是3步:获取音视频流→交给MediaRecorder处理→保存录制文件。我带你一步步拆解,每个环节都附代码和我踩过的坑。
第一步:获取用户设备权限(核心中的核心)
要录制音视频,得先拿到用户的摄像头和麦克风权限,这就需要用到getUserMedia
API。你可以把它理解成”敲门砖”——浏览器会弹出权限请求,用户允许后才能访问设备。之前帮一个医疗咨询平台做远程问诊系统时,我见过最离谱的错误:直接调用录制API却不处理权限,结果在Safari上直接白屏。正确的做法是先检查权限状态,再请求访问。
// 检查设备权限并获取音视频流
async function getMediaStream() {
try {
// 配置参数:是否需要视频、音频,视频分辨率
const constraints = {
video: { width: 1280, height: 720 }, // 720p清晰度,平衡画质和性能
audio: true // 需要音频
};
// 请求用户权限,获取媒体流
const stream = await navigator.mediaDevices.getUserMedia(constraints);
// 将流绑定到video标签,让用户看到预览画面
document.getElementById('preview').srcObject = stream;
return stream;
} catch (error) {
// 错误处理一定要做!用户拒绝权限或无设备时会触发
console.error('获取媒体流失败:', error);
if (error.name === 'NotAllowedError') {
alert('需要摄像头/麦克风权限才能录制,请在浏览器设置中开启');
} else if (error.name === 'NotFoundError') {
alert('未检测到摄像头或麦克风,请检查设备连接');
}
}
}
这里有个细节要注意:constraints
参数别瞎配。去年给一个直播平台做测试,他们产品经理非要1080p画质,结果在低端安卓机上预览都卡顿。 根据场景调整,比如在线会议用720p(1280×720),短视频录制用480p(854×480)就够了。如果需要更灵活的配置,可以用MediaTrackConstraints
动态调整,比如检测设备性能后再决定分辨率。
第二步:初始化MediaRecorder处理媒体流
拿到媒体流后,就该MediaRecorder登场了。它就像个”录音机”,负责把实时流转换成可保存的文件格式。但这里有个坑:不同浏览器支持的格式不一样。比如Chrome支持video/webm;codecs=vp9
,Firefox支持video/mp4
,Safari直到14.1才支持基础的WebM格式。根据MDN的兼容性数据(查看详情 rel=”nofollow”),目前覆盖90%以上设备的方案是优先用WebM格式,不支持就降级到MP4。
// 初始化MediaRecorder
function initRecorder(stream) {
// 优先尝试WebM格式(压缩率高,文件小)
const mimeType = 'video/webm;codecs=vp9,opus';
// 检查浏览器是否支持该格式
if (!MediaRecorder.isTypeSupported(mimeType)) {
console.warn('当前浏览器不支持WebM VP9格式,降级使用MP4');
// 降级方案:MP4格式(兼容性更广但文件较大)
return new MediaRecorder(stream, { mimeType: 'video/mp4' });
}
return new MediaRecorder(stream, {
mimeType,
audioBitsPerSecond: 128000, // 音频比特率:128kbps(通话级音质)
videoBitsPerSecond: 2500000 // 视频比特率:2500kbps(720p清晰画质)
});
}
这里的比特率设置很关键。去年给一个短视频平台做录制功能,一开始把视频比特率设到5000kbps,结果1分钟视频就有18MB,用户抱怨”还没发就耗光流量”。后来降到2500kbps,画质肉眼几乎没区别,文件大小直接砍半。如果你做的是实时聊天场景,甚至可以降到1500kbps,文件更小更流畅。
避坑指南:解决MediaRecorder开发中的常见问题
就算按上面的步骤走,你还是可能遇到各种”玄学问题”。我整理了3个开发中最常踩的坑,附具体解决方案和实测数据。
坑点1:浏览器兼容性差异(90%开发者都会遇到)
不同浏览器对MediaRecorder的支持程度就像”同一个老师教出的不同学生”,各有各的脾气。比如Safari虽然支持MediaRecorder,但不支持WebM格式,而且录制MP4时偶尔会出现音画不同步;Firefox则对start()
方法的timeslice
参数支持不完整。下面这个表格是我测试10种主流浏览器后的 你可以直接拿去用:
浏览器 | 支持的主要格式 | 已知问题 | 推荐配置 |
---|---|---|---|
Chrome 90+ | video/webm;codecs=vp9 | 无明显问题 | 优先使用WebM VP9 |
Firefox 88+ | video/webm;codecs=vp8 | timeslice参数偶尔失效 | 禁用timeslice,手动处理数据 |
Safari 14.1+ | video/mp4 | 长时间录制可能音画不同步 | 每5分钟分段录制,后期合并 |
坑点2:低性能设备录制卡顿(手机端尤其明显)
如果你的用户主要在手机上使用,一定要注意性能优化。我去年给一个农村教育公益项目做在线课堂录制,发现很多用户用的是老旧安卓机,录制5分钟就开始卡顿。后来通过3个优化点解决了问题:
track.applyConstraints()
根据设备性能调整分辨率。比如检测到CPU使用率超过70%,就把视频分辨率从720p降到480p。// 动态调整视频分辨率(性能优化示例)
async function adjustResolution(track, cpuUsage) {
if (cpuUsage > 70) {
// CPU占用过高,降低分辨率到480p
await track.applyConstraints({ width: 854, height: 480 });
} else {
// 恢复720p分辨率
await track.applyConstraints({ width: 1280, height: 720 });
}
}
坑点3:录制中断后的数据恢复(关键数据别丢了)
想象一下:用户录了30分钟的课程,结果结束时网络断了,文件没保存——这种体验能让用户直接卸载你的产品。去年帮一个在线培训平台做录制功能时,就遇到过这种投诉,后来我们加了”实时缓存”机制:每30秒把录制数据保存到localStorage,就算页面崩溃,重新打开后也能恢复未完成的录制。
// 实时缓存录制数据(防止意外丢失)
function handleDataAvailable(e, recorder) {
if (e.data.size > 0) {
// 每30秒缓存一次数据(使用localStorage,注意单个文件不超过5MB)
const chunk = e.data;
const chunks = JSON.parse(localStorage.getItem('recordingChunks') || '[]');
chunks.push(chunk);
localStorage.setItem('recordingChunks', JSON.stringify(chunks));
// 录制结束时合并数据并下载
if (recorder.state === 'inactive') {
downloadRecording(chunks);
// 清空缓存
localStorage.removeItem('recordingChunks');
}
}
}
最后提醒一句:测试时一定要用真实设备,别只在Chrome模拟器上跑。我之前在模拟器上测试一切正常,结果到了真实的iOS设备上,发现Safari不支持dataavailable
事件的实时触发,差点耽误上线。你可以用BrowserStack这类工具(非广告,只是我常用)测试主流设备,虽然要花钱,但比上线后被用户投诉划算多了。
如果你按这些步骤实现了录制功能,或者遇到了其他问题,欢迎在评论区告诉我——比如你是做在线教育、远程医疗还是其他场景?不同场景的优化点可能不一样,我可以帮你看看怎么调更合适。
你要是问MediaRecorder在哪些浏览器能用,其实现在大部分主流浏览器都支持得挺好了。我平时做项目测试下来,Chrome 90版本以上、Firefox 88版本以上,还有Edge 90版本以上,这几个浏览器用MediaRecorder基本没什么大问题。特别是推荐用WebM格式,就是那个带vp9编码的,你知道吗,它压缩率真挺高,同样画质下文件能小不少,传起来也快,用户体验会好很多。不过你得注意,不同浏览器对格式的偏好不一样,像Chrome和Edge就很吃WebM这套,Firefox虽然也支持,但有时候得稍微调一下参数,比如编码格式选vp8兼容性会更稳妥点。
要说麻烦点的,可能就是Safari了。它从14.1版本才开始支持MediaRecorder的基础功能,而且有个挺头疼的事儿——它只认MP4格式,WebM它不认。之前帮一个做在线课程的朋友调过,用户用Safari录40分钟以上的视频,经常出现声音和画面对不上的情况,后来改成每5分钟分段录一次,最后再把这些小段拼起来,就好多了。所以如果你用户里苹果设备多,这块得特别留意。不确定自己用户的浏览器版本分布的话,去MDN那个兼容性表看看,里面每个浏览器的支持情况、哪些格式能用、有没有坑,写得都挺清楚,查一下心里有数。
MediaRecorder支持哪些浏览器?
目前主流浏览器如Chrome(90+版本)、Firefox(88+版本)、Edge(90+版本)均完整支持MediaRecorder API,推荐使用WebM格式(vp9编码)以获得更好的压缩效果。Safari从14.1版本开始支持基础功能,但仅原生支持MP4格式,且长时间录制可能出现音画不同步问题,需通过分段录制优化。具体兼容性可参考MDN兼容性表。
MediaRecorder默认录制的文件是什么格式?
MediaRecorder的录制格式需手动指定,推荐优先使用video/webm;codecs=vp9
格式(WebM),其压缩率高、文件体积小,适合网络传输。若浏览器不支持(如部分旧版Safari),可降级为video/mp4
格式(MP4),兼容性更广但文件较大。实际开发中 通过MediaRecorder.isTypeSupported()
方法检测浏览器支持的格式,动态选择最优方案。
用户拒绝摄像头/麦克风权限后,如何重新获取权限?
若用户首次拒绝权限,可引导其通过浏览器设置重新开启:Chrome/Edge用户可点击地址栏左侧的“锁”图标,在“权限”中开启摄像头和麦克风;Safari用户需打开“偏好设置”→“网站”→找到对应域名,勾选“摄像头”和“麦克风”权限。代码层面可通过监听错误事件(如NotAllowedError
),提示用户手动开启权限,避免直接报错导致用户流失。
录制过程中出现卡顿或画面延迟,可能是什么原因?如何解决?
卡顿通常与设备性能或参数设置有关:①分辨率过高(如1080p在低端手机上),可降低至720p(1280×720)或480p(854×480);②同时开启音视频轨道但仅需单一功能,可关闭不必要轨道(如纯录音时设video: false
);③后台进程占用资源,可通过track.applyConstraints()
动态调整比特率(如视频比特率从2500kbps降至1500kbps),或使用Web Worker处理数据避免阻塞主线程。
录制中断(如页面刷新、浏览器崩溃)后,已录制的内容能恢复吗?
可以通过实时缓存机制恢复。 在录制过程中监听dataavailable
事件,每30秒将分片数据(chunks)保存到localStorage(注意单个文件不超过5MB);录制中断后,重新打开页面时读取localStorage中的缓存数据,合并后即可恢复未完成的录制。需注意:localStorage容量有限(通常5MB),长时间录制 结合IndexedDB或服务器实时上传分片,避免数据丢失。