HLS for ios

This commit is contained in:
mrjvs 2023-11-29 17:27:17 +01:00
parent 9f7330fc5b
commit b9f4e7f412
4 changed files with 46 additions and 7 deletions

View file

@ -17,6 +17,7 @@ import {
canFullscreen,
canFullscreenAnyElement,
canPictureInPicture,
canPlayHlsNatively,
canWebkitFullscreen,
canWebkitPictureInPicture,
} from "@/utils/detectFeatures";
@ -69,6 +70,10 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
}
function setupQualityForHls() {
if (videoElement && canPlayHlsNatively(videoElement)) {
return; // nothing to change
}
if (!hls) return;
if (!automaticQuality) {
const qualities = hlsLevelsToQualities(hls.levels);
@ -95,8 +100,13 @@ export function makeVideoElementDisplayInterface(): DisplayInterface {
function setupSource(vid: HTMLVideoElement, src: LoadableSource) {
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) {
hls = new Hls({
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)
);
videoElement.addEventListener("loadedmetadata", () => {
if (
source?.type === "hls" &&
videoElement &&
canPlayHlsNatively(videoElement)
) {
emit("qualities", ["unknown"]);
emit("changedquality", "unknown");
}
emit("duration", videoElement?.duration ?? 0);
});
videoElement.addEventListener("progress", () => {

View 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;
}

View file

@ -13,6 +13,7 @@ import { generateQuickSearchMediaUrl } from "@/backend/metadata/tmdb";
import { useOnlineListener } from "@/hooks/usePing";
import { AboutPage } from "@/pages/About";
import { AdminPage } from "@/pages/admin/AdminPage";
import VideoTesterView from "@/pages/developer/VideoTesterView";
import { DmcaPage } from "@/pages/Dmca";
import { NotFoundPage } from "@/pages/errors/NotFoundPage";
import { HomePage } from "@/pages/HomePage";
@ -106,15 +107,12 @@ function App() {
path="/dev"
component={lazy(() => import("@/pages/DeveloperPage"))}
/>
<Route
exact
path="/dev/video"
component={lazy(() => import("@/pages/developer/VideoTesterView"))}
/>
<Route path="/dev/video">
<VideoTesterView />
</Route>
{/* developer routes that can abuse workers are disabled in production */}
{process.env.NODE_ENV === "development" ? (
<Route
exact
path="/dev/test"
component={lazy(() => import("@/pages/developer/TestView"))}
/>

View file

@ -46,3 +46,7 @@ export function canPictureInPicture(): boolean {
export function canWebkitPictureInPicture(): boolean {
return "webkitSupportsPresentationMode" in document.createElement("video");
}
export function canPlayHlsNatively(video: HTMLVideoElement): boolean {
return !!video.canPlayType("application/vnd.apple.mpegurl");
}