谷歌浏览器配置媒体会话API控制锁屏播放

作者:技术拾光时间:2026-06-06 20:38:01浏览:205

用户手势触发后立即调用媒体会话API,设置元数据(包含标题、艺术家、封面图需使用HTTPS),注册播放、暂停、上一曲、下一曲以及可选的跳转动作,并通过设置播放位置状态与请求动画帧来同步进度,否则锁屏不显示或不同步。

要在谷歌浏览器中让网页音乐在锁屏界面显示标题、艺术家和控制按钮,并响应播放/暂停/上一首/下一首操作,关键就在于,这一切必须在用户的手势触发后立刻执行,否则系统会静默忽略全部配置。

谷歌浏览器配置媒体会话API控制锁屏播放

确认浏览器支持并绑定媒体元素

先确认浏览器是否支持。打开开发者工具控制台,输入 if ('mediaSession' in navigator) { console.log('支持') },看到“支持”返回就对了。这个API在Chrome 57+就已默认启用,但需留意检查 chrome://flags/#disable-media-session 这个实验性标志是否被取消勾选,否则配置了也无效。

接下来找到页面里已有的 或 元素。例如写个 const audio = document.querySelector('#bgm')。这里有一个硬性前提:必须使用真实加载完成、并且已经调用过play()方法的媒体元素。用 new Audio() 创建但未播放的实例,或尚未加载完成的元素,都不行。

动作要快,在用户点击播放按钮的事件处理函数中,立刻执行后续所有步骤。这是整套配置的硬性前提——脱离用户手势调用setActionHandler,浏览器会直接丢弃,不会给机会。

设置锁屏显示的元数据

然后为锁屏界面准备显示内容。调用 navigator.mediaSession.metadata = new MediaMetadata({,将标题、艺术家、专辑等字段填入。注意,全部必须是纯字符串,不支持HTML标签或换行符。

封面图容易踩坑。artwork字段必须传一个图片数组,且图片地址必须是 HTTPS协议。本地file://或http地址会导致封面完全不显示,Android系统会降级为默认图标。建议至少包含一张≥512×512像素的图片,格式如下:

{ src: 'https://example.com/cover-512.jpg', sizes: '512x512', type: 'image/jpeg' }

设置完成后,锁屏界面不会立刻刷新。需要触发一次播放状态变化,或等待系统轮询——但轮询延迟完全不可控。最稳妥的做法是:紧跟在 audio.play() 调用之后,立刻赋值元数据。

注册系统级播放控制动作

播放控制分两种情况。先说基础控制,全平台兼容:

依次注册四个动作:播放、暂停、上一曲、下一曲。
navigator.mediaSession.setActionHandler('play', () => audio.play().catch(e => console.warn(e)));
navigator.mediaSession.setActionHandler('pause', () => audio.pause());
navigator.mediaSession.setActionHandler('previoustrack', () => { audio.currentTime = Math.max(0, audio.currentTime - 15); audio.play(); });
navigator.mediaSession.setActionHandler('nexttrack', () => { audio.currentTime = Math.min(audio.duration, audio.currentTime + 15); audio.play(); });

如果用户使用安卓Chrome 117及以上版本,还能支持进阶跳转控制。检测到 navigator.userAgent.includes('Chrome/117') && /Android/.test(navigator.userAgent) 时,额外注册一个seekto动作:

navigator.mediaSession.setActionHandler('seekto', event => { audio.currentTime = event.seekTime; });

但需注意,这个handler触发后,必须立刻调用 navigator.mediaSession.setPositionState() 同步进度,否则锁屏上的进度条纹丝不动,用户会以为功能坏了。

主动同步播放进度到锁屏界面

这一步很多人容易忽略。锁屏上的进度条并不会自动跟随音频播放,需要手动同步。

第一步:监听音频的loadedmetadata事件。在回调中首次调用 navigator.mediaSession.setPositionState(),传入三个参数:{ duration: audio.duration, position: 0, playbackRate: 1.0 },这样就有一个初始状态。

第二步:用 requestAnimationFrame 循环更新进度——这比setInterval精确得多。定义一个函数:

function updatePosition() { if (!audio.paused) { navigator.mediaSession.setPositionState({ duration: audio.duration || 0, position: audio.currentTime, playbackRate: audio.playbackRate }); } requestAnimationFrame(updatePosition); }

然后在 audio.addEventListener('play', updatePosition) 中启动这个循环。音频播放时,进度就会持续同步到锁屏界面。

第三步:每次播放状态变更(播放或暂停)之后,手动触发一次:
navigator.mediaSession.playbackState = audio.paused 'paused' : 'playing'

这一步如果漏掉,锁屏上的按钮状态就会不同步。比如实际正在播放,但锁屏上显示的是暂停图标,用户点一下反而打断播放,体验会被完全破坏。