You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JavaScript Media Session API问题:暂停功能正常,播放恢复按钮无法切换状态

修复Media Session播放按钮状态不切换的问题

我帮你排查了代码里的问题,核心原因在于audioCtx.resume()是异步操作,你之前同步设置playbackState的时机不对,导致浏览器的Media Session控件没有及时感知到播放状态的变化。另外,我们还需要补充一些边界情况的处理,比如避免未初始化时的错误调用。

修改后的完整代码

if ('mediaSession' in navigator) {
	let audioCtx, oscillator, gainNode;
	
	// 修复播放操作:等待resume完成后再更新状态
	navigator.mediaSession.setActionHandler('play', async () => {
		if (!audioCtx) return; // 避免未初始化时的错误调用
		await audioCtx.resume(); // 等待异步恢复操作完成
		navigator.mediaSession.playbackState = 'playing';
	});
	
	navigator.mediaSession.setActionHandler('pause', () => {
		if (!audioCtx) return;
		audioCtx.suspend();
		navigator.mediaSession.playbackState = 'paused';
	});
	
	if ('setPositionState' in navigator.mediaSession) {
		navigator.mediaSession.setPositionState({
			duration: 20,
			position: 0,
		});
	}
	
	const button = document.getElementById('button');
	button.onclick = async () => {
		if (!audioCtx) {
			audioCtx = new AudioContext();
			oscillator = audioCtx.createOscillator();
			gainNode = audioCtx.createGain();
			oscillator.connect(gainNode);
			gainNode.connect(audioCtx.destination);
			oscillator.frequency.value = 440;
			gainNode.gain.value = 0.1;
			oscillator.start();
			await audioCtx.resume();
			navigator.mediaSession.playbackState = 'playing';
		}
	};
}

关键修改点解释

  • 异步等待audioCtx.resume():AudioContext.resume()返回一个Promise,只有当这个Promise完成后,音频上下文才真正恢复到运行状态。之前同步设置playbackState会导致Media Session在音频实际恢复前就收到状态更新,可能被浏览器忽略或覆盖。
  • 添加边界检查:在play和pause的处理函数中加入if (!audioCtx) return,避免用户还没点击初始化按钮就操作播放控件时出现控制台错误。
  • 严格状态同步:确保每次播放/暂停操作都严格对应playbackState的更新,让浏览器的Media Session控件能准确反映当前音频的真实状态。

额外测试注意事项

  • 每个浏览器标签页只有一个全局的Media Session控件,测试时尽量避免在同一个页面运行多个音频相关代码片段,防止状态互相干扰。
  • 如果使用Stack Snippets测试,记得点击「保存并插入到帖子中」后再运行,避免模态框内的运行异常。

内容的提问来源于stack exchange,提问作者root

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 06:38:33