Available in Chrome 111+ | View on GitHub | Browse Samples
The Media Session API lets you handle presenting slides actions such as previous and next slides from a Picture-in-Picture window.
let slideNumber = 1;
togglePipButton.addEventListener("click", async () => {
try {
if (video !== document.pictureInPictureElement)
await video.requestPictureInPicture();
else await document.exitPictureInPicture();
} catch (error) {
log(`> Argh! ${error}`);
}
});
try {
navigator.mediaSession.setActionHandler("previousslide", () => {
log('> User clicked "Previous Slide" icon.');
if (slideNumber > 1) slideNumber--;
updateSlide();
});
} catch (error) {
log('Warning! The "previousslide" media session action is not supported.');
}
try {
navigator.mediaSession.setActionHandler("nextslide", () => {
log('> User clicked "Next Slide" icon.');
slideNumber++;
updateSlide();
});
} catch (error) {
log('Warning! The "nextslide" media session action is not supported.');
}
/* Picture-in-Picture canvas */
const canvas = document.querySelector("canvas");
canvas.width = 1024;
canvas.height = 512;
updateSlide();
const video = document.createElement("video");
video.srcObject = canvas.captureStream();
video.muted = true;
video.play();
/* Utils */
function updateSlide() {
const ctx = canvas.getContext("2d");
ctx.fillStyle = "grey";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = "white";
ctx.font = "100px Google Sans,arial,sans-serif";
ctx.textAlign = "center";
ctx.textBaseline = "middle";
ctx.fillText(`slide ${slideNumber}`, canvas.width / 2, canvas.height / 2, canvas.width);
}