mirror of
https://github.com/movie-web/movie-web.git
synced 2024-11-13 13:35:08 +01:00
HLS for ios
This commit is contained in:
parent
9f7330fc5b
commit
b9f4e7f412
@ -17,6 +17,7 @@ import {
|
|||||||
canFullscreen,
|
canFullscreen,
|
||||||
canFullscreenAnyElement,
|
canFullscreenAnyElement,
|
||||||
canPictureInPicture,
|
canPictureInPicture,
|
||||||
|
canPlayHlsNatively,
|
||||||
canWebkitFullscreen,
|
canWebkitFullscreen,
|
||||||
canWebkitPictureInPicture,
|
canWebkitPictureInPicture,
|
||||||
} from "@/utils/detectFeatures";
|
} from "@/utils/detectFeatures";
|
||||||
@ -69,6 +70,10 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function setupQualityForHls() {
|
function setupQualityForHls() {
|
||||||
|
if (videoElement && canPlayHlsNatively(videoElement)) {
|
||||||
|
return; // nothing to change
|
||||||
|
}
|
||||||
|
|
||||||
if (!hls) return;
|
if (!hls) return;
|
||||||
if (!automaticQuality) {
|
if (!automaticQuality) {
|
||||||
const qualities = hlsLevelsToQualities(hls.levels);
|
const qualities = hlsLevelsToQualities(hls.levels);
|
||||||
@ -95,8 +100,13 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
|
|||||||
|
|
||||||
function setupSource(vid: HTMLVideoElement, src: LoadableSource) {
|
function setupSource(vid: HTMLVideoElement, src: LoadableSource) {
|
||||||
if (src.type === "hls") {
|
if (src.type === "hls") {
|
||||||
if (!Hls.isSupported()) throw new Error("HLS not supported");
|
if (canPlayHlsNatively(vid)) {
|
||||||
|
vid.src = src.url;
|
||||||
|
vid.currentTime = startAt;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Hls.isSupported()) throw new Error("HLS not supported");
|
||||||
if (!hls) {
|
if (!hls) {
|
||||||
hls = new Hls({
|
hls = new Hls({
|
||||||
maxBufferSize: 500 * 1000 * 1000, // 500 mb of buffering, should load more fragments at once
|
maxBufferSize: 500 * 1000 * 1000, // 500 mb of buffering, should load more fragments at once
|
||||||
@ -178,6 +188,14 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
|
|||||||
emit("time", videoElement?.currentTime ?? 0)
|
emit("time", videoElement?.currentTime ?? 0)
|
||||||
);
|
);
|
||||||
videoElement.addEventListener("loadedmetadata", () => {
|
videoElement.addEventListener("loadedmetadata", () => {
|
||||||
|
if (
|
||||||
|
source?.type === "hls" &&
|
||||||
|
videoElement &&
|
||||||
|
canPlayHlsNatively(videoElement)
|
||||||
|
) {
|
||||||
|
emit("qualities", ["unknown"]);
|
||||||
|
emit("changedquality", "unknown");
|
||||||
|
}
|
||||||
emit("duration", videoElement?.duration ?? 0);
|
emit("duration", videoElement?.duration ?? 0);
|
||||||
});
|
});
|
||||||
videoElement.addEventListener("progress", () => {
|
videoElement.addEventListener("progress", () => {
|
||||||
|
19
src/components/player/utils/videoTracks.ts
Normal file
19
src/components/player/utils/videoTracks.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
export interface VideoTrack {
|
||||||
|
selected: boolean;
|
||||||
|
id: string;
|
||||||
|
kind: string;
|
||||||
|
label: string;
|
||||||
|
language: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type VideoTrackList = Array<VideoTrack> & {
|
||||||
|
selectedIndex: number;
|
||||||
|
getTrackById(id: string): VideoTrack | null;
|
||||||
|
addEventListener(type: "change", listener: (ev: Event) => any): void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function getVideoTracks(video: HTMLVideoElement): VideoTrackList | null {
|
||||||
|
const videoAsAny = video as any;
|
||||||
|
if (!videoAsAny.videoTracks) return null;
|
||||||
|
return videoAsAny.videoTracks;
|
||||||
|
}
|
@ -13,6 +13,7 @@ import { generateQuickSearchMediaUrl } from "@/backend/metadata/tmdb";
|
|||||||
import { useOnlineListener } from "@/hooks/usePing";
|
import { useOnlineListener } from "@/hooks/usePing";
|
||||||
import { AboutPage } from "@/pages/About";
|
import { AboutPage } from "@/pages/About";
|
||||||
import { AdminPage } from "@/pages/admin/AdminPage";
|
import { AdminPage } from "@/pages/admin/AdminPage";
|
||||||
|
import VideoTesterView from "@/pages/developer/VideoTesterView";
|
||||||
import { DmcaPage } from "@/pages/Dmca";
|
import { DmcaPage } from "@/pages/Dmca";
|
||||||
import { NotFoundPage } from "@/pages/errors/NotFoundPage";
|
import { NotFoundPage } from "@/pages/errors/NotFoundPage";
|
||||||
import { HomePage } from "@/pages/HomePage";
|
import { HomePage } from "@/pages/HomePage";
|
||||||
@ -106,15 +107,12 @@ function App() {
|
|||||||
path="/dev"
|
path="/dev"
|
||||||
component={lazy(() => import("@/pages/DeveloperPage"))}
|
component={lazy(() => import("@/pages/DeveloperPage"))}
|
||||||
/>
|
/>
|
||||||
<Route
|
<Route path="/dev/video">
|
||||||
exact
|
<VideoTesterView />
|
||||||
path="/dev/video"
|
</Route>
|
||||||
component={lazy(() => import("@/pages/developer/VideoTesterView"))}
|
|
||||||
/>
|
|
||||||
{/* developer routes that can abuse workers are disabled in production */}
|
{/* developer routes that can abuse workers are disabled in production */}
|
||||||
{process.env.NODE_ENV === "development" ? (
|
{process.env.NODE_ENV === "development" ? (
|
||||||
<Route
|
<Route
|
||||||
exact
|
|
||||||
path="/dev/test"
|
path="/dev/test"
|
||||||
component={lazy(() => import("@/pages/developer/TestView"))}
|
component={lazy(() => import("@/pages/developer/TestView"))}
|
||||||
/>
|
/>
|
||||||
|
@ -46,3 +46,7 @@ export function canPictureInPicture(): boolean {
|
|||||||
export function canWebkitPictureInPicture(): boolean {
|
export function canWebkitPictureInPicture(): boolean {
|
||||||
return "webkitSupportsPresentationMode" in document.createElement("video");
|
return "webkitSupportsPresentationMode" in document.createElement("video");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function canPlayHlsNatively(video: HTMLVideoElement): boolean {
|
||||||
|
return !!video.canPlayType("application/vnd.apple.mpegurl");
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user