feat(chromecast): support custom subtitle broadcast

This commit is contained in:
2026-07-24 18:07:12 +02:00
parent ecc8f08ffa
commit 096ee2c41d
5 changed files with 64 additions and 17 deletions
+13 -17
View File
@@ -244,26 +244,22 @@ export class WebOmniPlayer implements OmniPlayer {
this.setOverlaySubtitle(overlay ?? null);
if (this.castStatus === "connected") {
try {
// if the cast receiver handles overlay subtitles like us, send this message.
const ctx = (
window as unknown as {
// biome-ignore lint/suspicious/noExplicitAny: cast sender SDK global
cast?: { framework?: { CastContext?: { getInstance(): any } } };
}
).cast?.framework?.CastContext?.getInstance?.();
ctx
?.getCurrentSession?.()
?.sendMessage("urn:x-cast:dev.zoriya.omni", {
subtitle: overlay?.id ?? null,
})
?.catch?.(() => {});
} catch {
// no active cast session / sender SDK not loaded
}
window.cast.framework.CastContext.getInstance()
.getCurrentSession()
?.sendMessage("urn:x-cast:dev.zoriya.omni", {
subtitle: overlay?.id ?? null,
})
.catch(() => {});
}
}
// To be used on a callback of a chromecast session, it only changes the local state
applyRemoteSubtitle(id: string | null): void {
this.setOverlaySubtitle(
id ? (this.overlaySubtitles.find((s) => s.id === id) ?? null) : null,
);
}
private setOverlaySubtitle(sub: Subtitle | null): void {
if (this.overlaySubtitle === sub) return;
this.overlaySubtitle = sub;
+38
View File
@@ -72,6 +72,44 @@ const PlayerInitializer = ({
player.showNotification = showNotification;
}, [showNotification]);
useEffect(() => {
const ctx = window.cast?.framework?.CastContext?.getInstance();
if (!window.cast?.framework || !ctx) return;
let attached: cast.framework.CastSession | null = null;
const onSessionChange = () => {
const session = ctx.getCurrentSession();
if (!session || session === attached) return;
attached = session;
session.addMessageListener(
"urn:x-cast:dev.zoriya.omni",
(_ns: string, message: string) => {
let data: unknown;
try {
data = JSON.parse(message);
} catch {
return;
}
if (data && typeof data === "object" && "subtitle" in data) {
const id = (data as { subtitle?: unknown }).subtitle;
player.applyRemoteSubtitle(typeof id === "string" ? id : null);
}
},
);
};
onSessionChange();
ctx.addEventListener(
window.cast?.framework.CastContextEventType.SESSION_STATE_CHANGED,
onSessionChange,
);
return () =>
ctx.removeEventListener(
window.cast?.framework.CastContextEventType.SESSION_STATE_CHANGED,
onSessionChange,
);
}, []);
return <PlayerCtx.Provider value={player}>{children}</PlayerCtx.Provider>;
};