Skip to main content
Version: 11.13.0

Continuous play

Save the current playhead position and restore it when the player loads again.

Tip: open your browser's developer console and use the player and THEOplayer variables to interact with this demo.

Saved position

Saved—
Restored from—
Current playhead0:00

This demo stores the playhead in localStorage for this source URL. It saves during playback, on pause, and when the page is closed. The position is cleared when playback ends. Local storage and cookies persist only in the same browser. For cross-device continuity, store the position on your server for the signed-in user.

const key = `theoplayer-continuous-play:${sourceUrl}`;
localStorage.setItem(key, String(player.currentTime));
Code
demo.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Continuous play</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet" />
<style>
html,
body {
margin: 0;
padding: 0;
}

theoplayer-default-ui:not(:defined) {
display: inline-block;
box-sizing: border-box;
}

theoplayer-default-ui {
width: 100%;
aspect-ratio: 16 / 9;
font-family: 'Noto Sans', sans-serif;
background: #000;
}
</style>
<script src="https://cdn.theoplayer.com/dash/theoplayer/THEOplayer.js"></script>
<script nomodule src="https://unpkg.com/@theoplayer/web-ui@2/polyfills"></script>
<script async src="https://unpkg.com/@theoplayer/web-ui@2"></script>
</head>
<body>
<!--
libraryLocation: For demonstration purposes, we use the THEOplayer CDN.
For production use, host the library yourself and update this URL and the script above.

licenseUrl: Point this to your license file, or replace it with a license property.
-->
<theoplayer-default-ui
configuration='{"libraryLocation":"https://cdn.theoplayer.com/dash/theoplayer/","licenseUrl":"../../../../theoplayer-license.txt"}'
source='{"sources":{"src":"https://cdn.theoplayer.com/video/big_buck_bunny/big_buck_bunny_metadata.m3u8","type":"application/x-mpegurl"},"poster":"https://cdn.theoplayer.com/video/big_buck_bunny/poster.jpg","metadata":{"title":"Big Buck Bunny"}}'
></theoplayer-default-ui>
<script src="../utils.js"></script>
<script>
const sourceUrl = 'https://cdn.theoplayer.com/video/big_buck_bunny/big_buck_bunny_metadata.m3u8';
const storageKey = `theoplayer-continuous-play:${sourceUrl}`;
let saved = null;
let restoredFrom = null;
let lastSavedAt = 0;
let restored = false;
let savingEnabled = true;

onPlayerReady((player) => {
function report() {
sendToParent('continuous-play', {
saved,
restoredFrom,
currentTime: player.currentTime,
});
}

function savePosition() {
if (!savingEnabled || !Number.isFinite(player.currentTime) || player.currentTime <= 0) return;
saved = player.currentTime;
localStorage.setItem(storageKey, String(saved));
lastSavedAt = Date.now();
report();
}

function restorePosition() {
if (restored) return;
restored = true;
const stored = localStorage.getItem(storageKey);
const position = stored === null ? null : Number(stored);
if (position !== null && Number.isFinite(position) && position > 0) {
saved = position;
restoredFrom = position;
player.currentTime = position;
}
report();
}

player.addEventListener('loadedmetadata', restorePosition);
player.addEventListener('durationchange', restorePosition);
player.addEventListener('timeupdate', () => {
if (savingEnabled && Date.now() - lastSavedAt >= 1000) savePosition();
else report();
});
player.addEventListener('play', () => {
savingEnabled = true;
});
player.addEventListener('pause', () => {
if (savingEnabled) savePosition();
});
player.addEventListener('ended', () => {
localStorage.removeItem(storageKey);
saved = null;
restoredFrom = null;
report();
});
window.addEventListener('pagehide', () => {
if (savingEnabled) savePosition();
});

onParentMessage('clear-saved-position', () => {
localStorage.removeItem(storageKey);
saved = null;
restoredFrom = null;
savingEnabled = false;
report();
});

if (player.readyState >= 1) restorePosition();
report();
});
</script>
</body>
</html>