mirror of
https://github.com/zoriya/react-native-omni.git
synced 2026-08-05 13:46:59 +00:00
feat(cast): use native tracks for subtitles
This commit is contained in:
@@ -127,9 +127,6 @@ export const useEvent = <Event extends keyof OmniEvents>(
|
||||
return undefined;
|
||||
}, [event, player]);
|
||||
|
||||
// ASS/PGS (overlay) subtitle selection is not a videojs text-track change, so
|
||||
// re-fire subtitleChange when the overlay subtitle changes too — consumers
|
||||
// only need useEvent("subtitleChange").
|
||||
useEffect(() => {
|
||||
if (event !== "subtitleChange") return;
|
||||
return player.subscribeOverlaySubtitle(() => {
|
||||
|
||||
+10
-26
@@ -217,47 +217,31 @@ export class WebOmniPlayer implements OmniPlayer {
|
||||
|
||||
get subtitles(): Track[] {
|
||||
const textTracks = selectTextTrack(this._store.state)?.textTrackList ?? [];
|
||||
const native = textTracks
|
||||
return textTracks
|
||||
.filter((x) => x.kind === "subtitles" || x.kind === "captions")
|
||||
.map((track) => ({
|
||||
id: track.id!,
|
||||
label: track.label,
|
||||
language: track.language,
|
||||
selected: track.mode === "showing",
|
||||
selected:
|
||||
track.mode === "showing" || this.overlaySubtitle?.id === track.id,
|
||||
}));
|
||||
const overlay = this.overlaySubtitles.map((sub) => ({
|
||||
id: sub.id,
|
||||
label: sub.label,
|
||||
language: sub.language,
|
||||
selected: this.overlaySubtitle?.id === sub.id,
|
||||
}));
|
||||
return [...native, ...overlay];
|
||||
}
|
||||
|
||||
selectSubtitle(subtitle?: Track): void {
|
||||
const tracks = selectTextTrack(this._store.state);
|
||||
const overlay = subtitle
|
||||
? this.overlaySubtitles.find((s) => s.id === subtitle.id)
|
||||
: undefined;
|
||||
|
||||
const tracks = selectTextTrack(this._store.state);
|
||||
if (this.castStatus === "connected") {
|
||||
tracks?.selectSubtitlesTrack(subtitle ? subtitle.id : "off");
|
||||
this.setOverlaySubtitle(null);
|
||||
return;
|
||||
}
|
||||
|
||||
tracks?.selectSubtitlesTrack(overlay || !subtitle ? "off" : subtitle.id);
|
||||
this.setOverlaySubtitle(overlay ?? null);
|
||||
|
||||
if (this.castStatus === "connected") {
|
||||
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 {
|
||||
|
||||
@@ -75,36 +75,6 @@ const PlayerInitializer = ({
|
||||
player.showNotification = showNotification;
|
||||
}, [showNotification]);
|
||||
|
||||
useEffect(() => {
|
||||
let media: chrome.cast.media.Media | null = null;
|
||||
|
||||
const onMediaUpdate = () => {
|
||||
const data = media?.customData as { subtitle?: unknown } | undefined;
|
||||
player.applyRemoteSubtitle(
|
||||
typeof data?.subtitle === "string" ? data.subtitle : null,
|
||||
);
|
||||
};
|
||||
|
||||
const syncMedia = () => {
|
||||
const next =
|
||||
window.cast.framework.CastContext.getInstance()
|
||||
.getCurrentSession()
|
||||
?.getMediaSession() ?? null;
|
||||
if (next === media) return;
|
||||
media?.removeUpdateListener(onMediaUpdate);
|
||||
media = next;
|
||||
media?.addUpdateListener(onMediaUpdate);
|
||||
onMediaUpdate();
|
||||
};
|
||||
|
||||
const unsubscribe = store.subscribe(syncMedia);
|
||||
syncMedia();
|
||||
return () => {
|
||||
unsubscribe();
|
||||
media?.removeUpdateListener(onMediaUpdate);
|
||||
};
|
||||
}, [store]);
|
||||
|
||||
return <PlayerCtx.Provider value={player}>{children}</PlayerCtx.Provider>;
|
||||
};
|
||||
|
||||
|
||||
+11
-17
@@ -10,11 +10,7 @@ import {
|
||||
useSyncExternalStore,
|
||||
} from "react";
|
||||
import { usePlayerState } from "./events";
|
||||
import {
|
||||
getSubtitleFormat,
|
||||
isCustomSubtitle,
|
||||
type WebOmniPlayer,
|
||||
} from "./player.web";
|
||||
import { getSubtitleFormat, type WebOmniPlayer } from "./player.web";
|
||||
import { usePlayer, VideoPlayer } from "./provider.web";
|
||||
import type { SubtitleAssets } from "./types/subtitles";
|
||||
import type { OmniViewProps } from "./types/view";
|
||||
@@ -165,18 +161,16 @@ export const OmniView = ({
|
||||
crossOrigin="anonymous"
|
||||
style={{ width: "100%", height: "100%", objectFit: "contain" }}
|
||||
>
|
||||
{(player.source?.subtitles ?? [])
|
||||
.filter((subtitle) => !isCustomSubtitle(subtitle))
|
||||
.map((subtitle) => (
|
||||
<track
|
||||
key={subtitle.id}
|
||||
id={subtitle.id}
|
||||
kind="subtitles"
|
||||
src={subtitle.link}
|
||||
srcLang={subtitle.language}
|
||||
label={subtitle.label ?? subtitle.language ?? subtitle.id}
|
||||
/>
|
||||
))}
|
||||
{(player.source?.subtitles ?? []).map((subtitle) => (
|
||||
<track
|
||||
key={subtitle.id}
|
||||
id={subtitle.id}
|
||||
kind="subtitles"
|
||||
src={subtitle.link}
|
||||
srcLang={subtitle.language}
|
||||
label={subtitle.label ?? subtitle.language ?? subtitle.id}
|
||||
/>
|
||||
))}
|
||||
</Tech>
|
||||
)}
|
||||
{castStatus !== "connected" && castStatus !== "connecting" && (
|
||||
|
||||
Reference in New Issue
Block a user