Media API 是浏览器原生支持的音视频接口集合,核心为 HTMLMediaElement(audio/video 元素),辅以 MediaSession、MediaRecorder 等;控制须基于已加载的元素实例,play() 需用户手势触发,currentTime、volume 等属性需注意兼容性与行为细节。

Media API 不是独立的 JavaScript API,而是指浏览器原生支持的一组与音视频播放相关的接口集合,核心是 HTMLMediaElement(即 和 元素),加上 MediaSession、MediaRecorder、AudioContext 等辅助接口。直接操作 DOM 元素是最常用、最可靠的起点。
如何用 JS 控制
所有控制都基于元素实例,不是调用某个全局函数。必须确保元素已加载完成(loadedmetadata 或 canplay 事件后操作更安全)。
-
play()和pause()是最基础的启停方法,但现代浏览器要求用户手势触发(如 click、touchend),否则会抛出NotAllowedError -
currentTime可读写,单位为秒,设值后需监听seeking和seeked判断是否就位 -
volume范围是 0–1,设为 0 不等于静音(muted才真正禁音);部分浏览器在 iOS 上会忽略volume设置 -
preload属性影响预加载行为:"none"、"metadata"、"auto",但最终由浏览器决定,不可强求
const video = document.querySelector('video');
video.addEventListener('canplay', () => {
video.currentTime = 12.5;
video.play().catch(e => console.warn('Autoplay blocked:', e));
});
为什么 play() 经常失败?常见拦截场景
这是开发者最容易卡住的地方:不是代码写错,而是策略限制。Chrome、Safari、Firefox 均默认阻止无用户交互的自动播放。
- 页面刚加载就调
play()→ 必然失败,错误信息通常是DOMException: play() failed because the user didn't interact with the document first - 在
setTimeout或fetch回调里调用 → 仍视为无交互上下文,无效 - 正确做法:绑定到用户事件处理器中,例如
button.addEventListener('click', () => video.play()) - iOS Safari 更严格:即使有交互,
autoplay+muted也仅对有效,仍需手动触发
MediaSession API:让播放器融入系统级控制
它不控制播放逻辑本身,而是向操作系统/浏览器暴露元数据和操作能力,比如锁屏界面显示封面、耳机按键控制播放暂停。
立即学习“Java免费学习笔记(深入)”;
- 必须先启用:检查
'mediaSession' in navigator - 设置元数据用
navigator.mediaSession.metadata = new MediaMetadata({ ... }),字段包括title、artist、album、artwork(数组,每项含src、sizes、type) - 响应系统指令需显式定义
actionHandlers,例如:navigator.mediaSession.setActionHandler('play', () => video.play()) - 注意:只有媒体正在播放(
video.paused === false)时,系统才可能显示控件;且部分 Android 厂商定制系统可能不支持
if ('mediaSession' in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: 'Ocean Waves',
artist: 'Ambient Sounds',
artwork: [{ src: '/cover.jpg', sizes: '512x512', type: 'image/jpeg' }]
});
navigator.mediaSession.setActionHandler('pause', () => video.pause());
}
容易被忽略的关键点
很多问题出在生命周期判断和兼容性处理上,而不是功能本身。
-
duration在未加载元数据前是NaN,不能直接用于进度条计算 -
ended事件只在自然播完时触发,pause()或网络中断不会触发它 -
error事件对象的target.error.code才是真实错误码(如MediaError.MEDIA_ERR_NETWORK),target.error.message通常为空或不可靠 - 不要依赖
canplaythrough表示“一定能播完”——它只是浏览器预测缓冲足够,实际仍可能因网络波动卡顿

