mirror of
https://github.com/zoriya/v10.git
synced 2026-08-16 02:45:09 +00:00
143 lines
4.8 KiB
JavaScript
143 lines
4.8 KiB
JavaScript
import { loadScript } from "@videojs/utils/dom";
|
|
//#region src/dom/google-cast/utils.ts
|
|
var InvalidStateError = class extends Error {};
|
|
var NotSupportedError = class extends Error {};
|
|
var NotFoundError = class extends Error {};
|
|
const GOOGLE_CAST_FRAMEWORK_URL = "https://www.gstatic.com/cv/js/sender/v1/cast_sender.js?loadCastFramework=1";
|
|
const HLS_RESPONSE_HEADERS = [
|
|
"application/x-mpegURL",
|
|
"application/vnd.apple.mpegurl",
|
|
"audio/mpegurl"
|
|
];
|
|
var IterableWeakSet = class {
|
|
#refs = /* @__PURE__ */ new Set();
|
|
#seen = /* @__PURE__ */ new WeakMap();
|
|
add(value) {
|
|
if (this.#seen.has(value)) return this;
|
|
const ref = new WeakRef(value);
|
|
this.#seen.set(value, ref);
|
|
this.#refs.add(ref);
|
|
return this;
|
|
}
|
|
delete(value) {
|
|
const ref = this.#seen.get(value);
|
|
if (!ref) return false;
|
|
this.#seen.delete(value);
|
|
return this.#refs.delete(ref);
|
|
}
|
|
forEach(fn) {
|
|
for (const ref of this.#refs) {
|
|
const value = ref.deref();
|
|
if (value) fn(value);
|
|
else this.#refs.delete(ref);
|
|
}
|
|
}
|
|
};
|
|
function onCastApiAvailable(callback) {
|
|
const whenDefined = () => customElements.whenDefined("google-cast-button").then(callback);
|
|
if (!globalThis.chrome?.cast?.isAvailable) globalThis.__onGCastApiAvailable = whenDefined;
|
|
else if (typeof cast === "undefined" || !cast.framework) whenDefined();
|
|
else callback();
|
|
}
|
|
function requiresCastFramework() {
|
|
return Boolean(globalThis.chrome);
|
|
}
|
|
async function loadCastFramework() {
|
|
if (globalThis.chrome?.cast) return;
|
|
await loadScript(GOOGLE_CAST_FRAMEWORK_URL);
|
|
}
|
|
function getCastContext() {
|
|
return typeof cast === "undefined" ? void 0 : cast.framework?.CastContext.getInstance();
|
|
}
|
|
function currentSession() {
|
|
return getCastContext()?.getCurrentSession();
|
|
}
|
|
function currentMedia() {
|
|
return currentSession()?.getSessionObj().media[0] ?? void 0;
|
|
}
|
|
function editTracksInfo(request) {
|
|
return new Promise((resolve, reject) => {
|
|
currentMedia().editTracksInfo(request, resolve, reject);
|
|
});
|
|
}
|
|
function getMediaStatus(request) {
|
|
return new Promise((resolve, reject) => {
|
|
currentMedia().getStatus(request, resolve, reject);
|
|
});
|
|
}
|
|
const MEDIA_NAMESPACE = "urn:x-cast:com.google.cast.media";
|
|
let requestId = 0;
|
|
function setPlaybackRate(rate) {
|
|
const media = currentMedia();
|
|
return currentSession().sendMessage(MEDIA_NAMESPACE, {
|
|
type: "SET_PLAYBACK_RATE",
|
|
playbackRate: rate,
|
|
mediaSessionId: media?.mediaSessionId,
|
|
requestId: ++requestId
|
|
});
|
|
}
|
|
function setCastOptions(options) {
|
|
getCastContext().setOptions({
|
|
...getDefaultCastOptions(),
|
|
...options
|
|
});
|
|
}
|
|
function getDefaultCastOptions() {
|
|
return {
|
|
receiverApplicationId: "CC1AD845",
|
|
autoJoinPolicy: globalThis.chrome?.cast?.AutoJoinPolicy?.ORIGIN_SCOPED ?? "origin_scoped",
|
|
androidReceiverCompatible: false,
|
|
language: "en-US",
|
|
resumeSavedSession: true
|
|
};
|
|
}
|
|
function getFormat(segment) {
|
|
if (!segment) return void 0;
|
|
const match = segment.match(/\.([a-zA-Z0-9]+)(?:\?.*)?$/);
|
|
return match ? match[1] : null;
|
|
}
|
|
function parsePlaylistUrls(playlistContent) {
|
|
const lines = playlistContent.split("\n");
|
|
const urls = [];
|
|
for (let i = 0; i < lines.length; i++) if (lines[i].trim().startsWith("#EXT-X-STREAM-INF")) {
|
|
const nextLine = lines[i + 1] ? lines[i + 1].trim() : "";
|
|
if (nextLine && !nextLine.startsWith("#")) urls.push(nextLine);
|
|
}
|
|
return urls;
|
|
}
|
|
function parseSegment(playlistContent) {
|
|
return playlistContent.split("\n").find((line) => !line.trim().startsWith("#") && line.trim() !== "");
|
|
}
|
|
async function isHls(url) {
|
|
if (!url) return false;
|
|
if (/\.m3u8?(\?.*)?$/i.test(url)) return true;
|
|
if (url.startsWith("blob:")) return false;
|
|
try {
|
|
const contentType = (await fetch(url, { method: "HEAD" })).headers.get("Content-Type");
|
|
if (!contentType) return false;
|
|
const normalizedContentType = contentType.toLowerCase().split(";")[0].trim();
|
|
return HLS_RESPONSE_HEADERS.some((header) => normalizedContentType === header.toLowerCase());
|
|
} catch (err) {
|
|
console.error("Error while trying to get the Content-Type of the manifest", err);
|
|
return false;
|
|
}
|
|
}
|
|
async function getPlaylistSegmentFormat(url) {
|
|
try {
|
|
const mainManifestContent = await (await fetch(url)).text();
|
|
let availableChunksContent = mainManifestContent;
|
|
const playlists = parsePlaylistUrls(mainManifestContent);
|
|
if (playlists.length > 0) {
|
|
const chosenPlaylistUrl = new URL(playlists[0], url).toString();
|
|
availableChunksContent = await (await fetch(chosenPlaylistUrl)).text();
|
|
}
|
|
return getFormat(parseSegment(availableChunksContent));
|
|
} catch (err) {
|
|
console.error("Error while trying to parse the manifest playlist", err);
|
|
return;
|
|
}
|
|
}
|
|
//#endregion
|
|
export { InvalidStateError, IterableWeakSet, NotFoundError, NotSupportedError, currentMedia, currentSession, editTracksInfo, getCastContext, getMediaStatus, getPlaylistSegmentFormat, isHls, loadCastFramework, onCastApiAvailable, requiresCastFramework, setCastOptions, setPlaybackRate };
|
|
|
|
//# sourceMappingURL=utils.js.map
|