起因
作为一名前端开发,我有在网页上听歌的习惯,那天我如常边听我的每日推荐边写代码,突然一首非常攒劲带感 的音乐成功引起了我的注意,我想去调大我耳机的声音,就点了下右下角任务栏的声音,我发现弹出来的面板上面竟然有播放控件 、歌曲名字 、作者 和专辑封面的信息。

好奇
突然让我思考一个问题:
操作系统是怎么知道我在网页上听的是什么歌呢?
在我一通探索下,发现了 MediaSession 这个 API
。
Media Session API
是一个 Web API
Media Session API
允许网页为媒体播放提供自定义行为,并与设备的原生媒体控制界面(如通知栏、锁屏、键盘媒体键、耳机按钮等)交互。主要功能包括: 元数据共享:通过 MediaMetadata
对象,网页可以向浏览器和操作系统提供当前播放媒体的标题、艺术家、专辑、封面等信息,这些信息会显示在设备的媒体控制界面上。
-
自定义控制行为:通过
setActionHandler
方法,开发者可以为播放、暂停、快进、快退、上一曲、下一曲等操作设置回调函数,响应用户通过设备媒体控制触发的动作。 -
播放状态同步:通过
playbackState
属性,网页可以声明媒体的播放状态(playing
、paused
或none
),确保设备界面与网页状态一致。 -
位置状态更新:通过
setPositionState
方法,网页可以更新媒体的当前播放位置、总时长和播放速度,供设备界面显示进度条等信息。 -
视频会议支持:支持视频会议相关的操作,如开关麦克风、摄像头或挂断通话(
togglemicrophone
、togglecamera
、hangup
)。 -
画中画模式支持:在画中画(
Picture-in-Picture
)模式下,可以为幻灯片导航等场景提供自定义控制(如previousslide、nextslide
)。
Media Session API
广泛应用于音频播放器、视频播放器、播客应用、流媒体网站等场景,让用户可以通过设备的原生界面或硬件控制媒体播放。
navigator.mediaSession 的作用
navigator.mediaSession
是访问 Media Session API
的入口点,它是一个只读属性,返回一个 MediaSession
对象。开发者通过这个对象配置媒体元数据、设置动作处理程序等。
这些功能都怎么用呢?
设置媒体元数据
在播放歌曲的网页打开控制台,看看 navigator.mediaSession
的内容你就大概了解了:
js
navigator.mediaSession.metadata = new MediaMetadata({
title: '歌曲名称',
artist: '作者',
album: '专辑名称',
artwork: [
{ src: 'https://xxx.image.com/96x96', sizes: '96x96', type: 'image/png' },
{ src: 'https://xxx.image.com/128x128', sizes: '128x128', type: 'image/png' },
{ src: 'https://xxx.image.com/512x512', sizes: '512x512', type: 'image/png' }
]
});
需要注意的:
artwork
是一个MediaImage
对象的数组,建议提供多种尺寸的图片(如 96x96、128x128、512x512)以适配不同设备。- 如果未设置
artwork
,浏览器可能使用页面的<link rel="icon">
作为默认图片
设置动作处理程序
通过 setActionHandler
方法为媒体控制动作设置回调函数,支持的动作包括:
-
play
:播放 -
pause
:暂停 -
stop
:停止 -
seekbackward
:后退(默认 10 秒) -
seekforward
:前进(默认 10 秒) -
seekto
:跳转到指定时间 -
previoustrack
:上一曲 -
nexttrack
:下一曲 -
skipad
:跳过广告 -
togglemicrophone
:开关麦克风 -
togglecamera
:开关摄像头 -
hangup
:挂断通话 -
previousslide / nextslide
:幻灯片导航(画中画模式)
给一个为播放和暂停设置动作处理程序,并同步播放状态的例子:
js
const audio = document.querySelector('#player');
audio.src = 'song.mp3';
if ('mediaSession' in navigator) {
// 设置播放动作
navigator.mediaSession.setActionHandler('play', async () => {
await audio.play();
navigator.mediaSession.playbackState = 'playing';
});
// 设置暂停动作
navigator.mediaSession.setActionHandler('pause', () => {
audio.pause();
navigator.mediaSession.playbackState = 'paused';
});
// 监听音频元素状态变化
audio.addEventListener('play', () => {
navigator.mediaSession.playbackState = 'playing';
});
audio.addEventListener('pause', () => {
navigator.mediaSession.playbackState = 'paused';
});
}
注意:
-
使用
try-catch
检测动作是否支持,因为某些动作(如stop、seekto
)可能在部分浏览器中不可用 -
要移除动作处理程序,可将回调设为
null:navigator.mediaSession.setActionHandler('play', null)
。 -
动作处理程序会持久存在,直到页面卸载或手动移除。
更新播放位置
通过 setPositionState
方法更新媒体的播放位置、时长和速度,适用于显示进度条或时间信息:
js
function updatePositionState() {
if ('setPositionState' in navigator.mediaSession) {
navigator.mediaSession.setPositionState({
duration: audio.duration, // 媒体总时长(秒)
playbackRate: audio.playbackRate, // 播放速度
position: audio.currentTime // 当前位置(秒)
});
}
}
// 在时间更新或动作触发时调用
audio.addEventListener('timeupdate', updatePositionState);
// 示例:处理快退动作
navigator.mediaSession.setActionHandler('seekbackward', (details) => {
const skipTime = details.seekOffset || 10; // 默认后退 10 秒
audio.currentTime = Math.max(audio.currentTime - skipTime, 0);
updatePositionState();
});
注意:
duration
必须为正数,直播流可用Infinity
表示无固定时长。- 在媒体加载完成前,
audio.duration
可能为NaN
,需进行检查。
处理播放列表导航
支持 previoustrack
和 nexttrack
动作,用于切换播放列表中的曲目。
js
const playlist = ['song1.mp3', 'song2.mp3', 'song3.mp3'];
let index = 0;
function playAudio() {
audio.src = playlist[index];
audio.play().then(() => {
navigator.mediaSession.metadata = new MediaMetadata({
title: `Song ${index + 1}`,
artist: 'Artist Name',
album: 'Album Name',
artwork: [{ src: 'cover.jpg', sizes: '512x512', type: 'image/jpeg' }]
});
updatePositionState();
});
}
navigator.mediaSession.setActionHandler('previoustrack', () => {
index = (index - 1 + playlist.length) % playlist.length;
playAudio();
});
navigator.mediaSession.setActionHandler('nexttrack', () => {
index = (index + 1) % playlist.length;
playAudio();
});
视频会议场景
为视频会议设置麦克风和摄像头控制。
js
let isMicrophoneActive = false;
navigator.mediaSession.setActionHandler('togglemicrophone', () => {
isMicrophoneActive = !isMicrophoneActive;
// 切换麦克风状态的逻辑
navigator.mediaSession.setMicrophoneActive(isMicrophoneActive);
});
视频会议动作(如 togglemicrophone
)目前支持有限,主要在 Chrome 92+
桌面版中可用
画中画模式支持
在画中画模式下,为幻灯片导航设置动作
js
navigator.mediaSession.setActionHandler('previousslide', () => {
// 切换到上一页幻灯片
});
navigator.mediaSession.setActionHandler('nextslide', () => {
// 切换到下一页幻灯片
});
最后总结
MediaSession
通过 navigator.mediaSession
提供,允许网页与设备的媒体控制界面交互,支持元数据共享、自定义动作和状态同步。歌也听了,API
也学到了,要是觉得歌有意思或者这个API
有用,就给点个关注点个赞吧,彦祖、亦菲们~。我是 Senar
,是不是分享点有用没用的前端开发知识,我们下期再见~