Playback happens in the iframe. Your application receives structured messages through window.postMessage.
Connect once, listen safely
The existing VELARIUM_EMBED_INIT and VELARIUM_EMBED_READY handshake names remain stable for compatibility. Ready messages contain no playback data; sending INIT lets the player verify its parent before sharing progress.
PARENT WINDOW · JAVASCRIPT
// Run after the iframe is mounted.
const frame = document.getElementById("velarium-player");
const playerOrigin = "https://velarium.cc";
function connect() {
frame.contentWindow?.postMessage(
{ type: "VELARIUM_EMBED_INIT" }, playerOrigin
);
}
function onMessage(message) {
if (message.origin !== playerOrigin) return;
if (message.source !== frame.contentWindow) return;
const payload = message.data;
if (!payload || typeof payload !== "object") return;
if (payload.type === "VELARIUM_EMBED_READY") connect();
if (payload.type === "PLAYER_EVENT") {
const data = payload.data;
if (!data || typeof data.event !== "string" ||
!Number.isFinite(data.currentTime) ||
!Number.isFinite(data.duration)) return;
console.log(data.event, data.currentTime, data.duration);
}
if (payload.type === "MEDIA_DATA" && payload.data &&
typeof payload.data === "object") {
// Storage can be unavailable in privacy mode.
try {
localStorage.setItem("velarium-progress",
JSON.stringify(payload.data));
} catch { /* Keep playback working without storage. */ }
}
}
window.addEventListener("message", onMessage);
frame.addEventListener("load", connect);
connect();
// On unmount:
// window.removeEventListener("message", onMessage);
// frame.removeEventListener("load", connect);PLAYER_EVENT
Each message describes playback at the time it was emitted. Subscribe to the events your application needs.
playpauseseekedendedtimeupdateEXAMPLE PAYLOAD · TV
{
"type": "PLAYER_EVENT",
"data": {
"event": "pause",
"currentTime": 93.4,
"duration": 2680,
"tmdbId": 94997,
"mediaType": "tv",
"season": 1,
"episode": 1
}
}season and episode apply to TV. Use the resolved tmdbId even when the original URL uses an IMDb ID.
MEDIA_DATA
A progress snapshot keyed by TMDB ID. watched and duration use seconds; last_updated uses Unix milliseconds. TV records also include per-episode progress.
EXAMPLE PROGRESS SNAPSHOT
{
"type": "MEDIA_DATA",
"data": {
"94997": {
"id": 94997,
"type": "tv",
"title": "Example series",
"poster_path": "/poster.jpg",
"backdrop_path": "/backdrop.jpg",
"progress": {
"watched": 93.4,
"duration": 2680
},
"last_season_watched": 1,
"last_episode_watched": 1,
"show_progress": {
"s1e1": {
"progress": {
"watched": 93.4,
"duration": 2680
}
}
},
"last_updated": 1789257600000
}
}
}Save progress locally or in your own backend. Local storage is device-specific and may be blocked. Throttle frequent updates before writing to a server, validate incoming data, and never trust messages from unrelated windows.