我正在构建一个媒体控制器应用程序来控制在远程进程中运行的媒体播放器,并尝试使用 MediaSession API 来促进媒体密钥控制。几乎无声的音频元素用于建立媒体会话,并在几秒钟后无限期暂停。
这在 Firefox 中运行良好,但在基于 Chrome 的浏览器(桌面和移动)中,播放/暂停按钮不会改变状态并最终在几秒钟后停止工作。下一个/上一个曲目按钮按预期工作。
我需要做什么才能使播放/暂停媒体会话控件在基于 Chrome 的浏览器中工作?
React 应用程序重现问题:
import "./styles.css";
import React from "react";
export default function App() {
return (
<div className="App">
<h1>MediaSession demo</h1>
<Player />
</div>
);
}
function Player() {
const playctl = usePlayer();
if (playctl.state === "stopped") {
return <button onClick={playctl.playPause}>Begin</button>;
}
return (
<>
<p>Use media session notification to control player state.</p>
<MediaSession playctl={playctl} />
<p>Player state: {playctl.state}</p>
<p>Track: {playctl.track}</p>
</>
);
}
function usePlayer() {
const [state, setState] = React.useState("stopped");
const [track, setTrack] = React.useState(1);
let playing = state === "playing";
return {
playPause: () => {
playing = !playing;
setState(playing ? "playing" : "paused");
},
nextTrack: () => {
setTrack(track < 5 ? track + 1 : 1);
},
prevTrack: () => {
setTrack(track > 1 ? track - 1 : 5);
},
state,
nextState: playing ? "Pause" : "Play",
playing,
track
};
}
const MediaSession = ({ playctl }) => {
const controls = useMediaControls();
React.useEffect(() => controls.update(playctl), [controls, playctl]);
return controls.audio;
};
function useMediaControls() {
const audiofile = require("./near-silence.mp3");
const hasSession = window.navigator && "mediaSession" in window.navigator;
const ref = React.useRef();
let shouldShow = true;
function showControls(audio) {
shouldShow = false;
audio.volume = 0.00001; // very low volume level
audio.play();
audio.currentTime = 0;
// pause before track ends so controls remain visible
setTimeout(() => audio.pause(), 5000);
}
function updateSession(playctl) {
const session = window.navigator.mediaSession;
session.playbackState = playctl.playing ? "playing" : "paused";
session.setActionHandler("pause", playctl.playPause);
session.setActionHandler("play", playctl.playPause);
session.setActionHandler("nexttrack", playctl.nextTrack);
session.setActionHandler("previoustrack", playctl.prevTrack);
}
function createApi() {
return {
audio: hasSession && <audio ref={ref} src={audiofile} />,
update: (playctl) => {
if (hasSession) {
const audio = ref.current;
shouldShow && audio && showControls(audio);
updateSession(playctl);
}
}
};
}
return React.useState(createApi)[0];
}