移动浏览器在锁屏状态下停止播放音频,主要是因为系统为了节省电量和资源,会挂起非活跃页面的JS执行和媒体播放进程,导致普通audio标签的播放流程被中断。要实现锁屏后持续播放音频列表,需要结合特定的浏览器API绕过系统的限制。

核心实现原理
要实现锁屏持续播放,需要解决两个核心问题:一是避免系统挂起页面的播放进程,二是锁屏后仍能控制播放流程切换下一个音频。主要依赖以下两个API:
- Web Audio API:通过AudioContext创建音频上下文,以更底层的方式控制音频播放,部分浏览器对这类音频资源的后台限制更宽松
- Media Session API:用于向系统媒体控制中心注册当前播放的媒体信息,让系统认为当前是活跃的媒体播放场景,减少被挂起的概率,同时支持锁屏界面控制播放
完整实现步骤
1. 初始化音频播放环境
首先创建AudioContext实例和音频列表管理逻辑,这里需要注意AudioContext需要在用户交互后激活,避免浏览器自动播放策略的限制。
// 音频列表数据
const audioList = [
{ title: '音频1', url: 'https://ipipp.com/audio1.mp3' },
{ title: '音频2', url: 'https://ipipp.com/audio2.mp3' },
{ title: '音频3', url: 'https://ipipp.com/audio3.mp3' }
];
let currentIndex = 0;
let audioContext = null;
let sourceNode = null;
let isPlaying = false;
// 初始化AudioContext,需要绑定用户点击事件触发
function initAudioContext() {
if (!audioContext) {
audioContext = new (window.AudioContext || window.webkitAudioContext)();
}
// 如果AudioContext处于挂起状态,恢复它
if (audioContext.state === 'suspended') {
audioContext.resume();
}
}
2. 加载并播放单个音频
通过fetch获取音频资源,解码后通过AudioContext播放,播放结束后自动切换到下一个音频。
// 加载并播放指定索引的音频
async function playAudioByIndex(index) {
if (index >= audioList.length) {
currentIndex = 0;
index = 0;
}
const audioItem = audioList[index];
currentIndex = index;
try {
// 获取音频资源
const response = await fetch(audioItem.url);
const arrayBuffer = await response.arrayBuffer();
// 解码音频数据
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
// 创建音频源节点
sourceNode = audioContext.createBufferSource();
sourceNode.buffer = audioBuffer;
// 连接到音频输出
sourceNode.connect(audioContext.destination);
// 播放结束自动切下一首
sourceNode.onended = () => {
if (isPlaying) {
playAudioByIndex(currentIndex + 1);
}
};
// 开始播放
sourceNode.start();
isPlaying = true;
// 更新媒体会话信息
updateMediaSession(audioItem);
} catch (err) {
console.error('音频加载失败:', err);
// 加载失败也切下一首
if (isPlaying) {
playAudioByIndex(currentIndex + 1);
}
}
}
3. 注册Media Session信息
通过Media Session API向系统注册当前播放的媒体信息,让系统识别为正在播放的媒体,降低被挂起的概率,同时支持锁屏界面控制。
// 更新媒体会话信息
function updateMediaSession(audioItem) {
if ('mediaSession' in navigator) {
navigator.mediaSession.metadata = new MediaMetadata({
title: audioItem.title,
artist: '网页音频播放',
album: '音频列表',
// 可选封面图
artwork: [
{ src: 'https://ipipp.com/cover.jpg', sizes: '512x512', type: 'image/jpeg' }
]
});
// 注册媒体控制动作
navigator.mediaSession.setActionHandler('previoustrack', () => {
// 上一首逻辑
const prevIndex = currentIndex === 0 ? audioList.length - 1 : currentIndex - 1;
playAudioByIndex(prevIndex);
});
navigator.mediaSession.setActionHandler('nexttrack', () => {
// 下一首逻辑
playAudioByIndex(currentIndex + 1);
});
navigator.mediaSession.setActionHandler('pause', () => {
// 暂停逻辑
if (sourceNode) {
sourceNode.stop();
isPlaying = false;
navigator.mediaSession.playbackState = 'paused';
}
});
navigator.mediaSession.setActionHandler('play', () => {
// 继续播放逻辑
playAudioByIndex(currentIndex);
navigator.mediaSession.playbackState = 'playing';
});
}
}
4. 用户交互触发初始化
浏览器的自动播放策略要求音频播放必须由用户交互触发,因此需要在用户点击播放按钮时初始化AudioContext并开始播放。
// 绑定播放按钮点击事件
document.getElementById('playBtn').addEventListener('click', () => {
initAudioContext();
if (!isPlaying) {
playAudioByIndex(currentIndex);
}
});
兼容性说明
不同移动浏览器对这两个API的支持程度不同,需要做兼容处理:
| 浏览器 | Web Audio API支持 | Media Session API支持 | 锁屏播放效果 |
|---|---|---|---|
| Chrome Android | 完整支持 | 完整支持 | 锁屏后可持续播放,支持锁屏控制 |
| Safari iOS | 部分支持 | 部分支持 | 锁屏后可能中断,需配合页面后台保活逻辑 |
| Firefox Android | 完整支持 | 部分支持 | 锁屏后大概率持续播放 |
注意事项
- 音频资源需要支持跨域访问,否则fetch请求会失败,建议音频资源服务器配置CORS头部
- iOS Safari的限制更严格,可能需要页面保持最小化的后台运行权限,或者引导用户将网页添加到主屏幕后打开,提升锁屏播放的稳定性
- 不要频繁创建和销毁AudioContext实例,尽量复用同一个实例,避免资源浪费和兼容性问题
- 如果用户主动关闭了浏览器的媒体播放权限,上述方案也会失效,需要做好降级提示
以上方案是基于现有浏览器API的最优实现,随着浏览器规范的更新,后续可能有更简单的实现方式,建议定期关注相关API的更新动态。
Web_Audio_API后台播放锁屏音频Media_Session_API修改时间:2026-06-29 15:18:43