aboutsummaryrefslogtreecommitdiff
path: root/web/script/player/mediacaps.ts
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-04-15 13:54:52 +0200
committermetamuffin <metamuffin@disroot.org>2025-04-15 13:54:52 +0200
commitc59abb792391e2f7540a80bb8d989021fe0a5b80 (patch)
tree33688772e3822b38441f86a08c0c595ea1ef14b0 /web/script/player/mediacaps.ts
parent3b147cb1dfcbd5c7218e0accd5784d992d5ae21c (diff)
downloadjellything-c59abb792391e2f7540a80bb8d989021fe0a5b80.tar
jellything-c59abb792391e2f7540a80bb8d989021fe0a5b80.tar.bz2
jellything-c59abb792391e2f7540a80bb8d989021fe0a5b80.tar.zst
refactor jsp, part 1
Diffstat (limited to 'web/script/player/mediacaps.ts')
-rw-r--r--web/script/player/mediacaps.ts96
1 files changed, 29 insertions, 67 deletions
diff --git a/web/script/player/mediacaps.ts b/web/script/player/mediacaps.ts
index e44b92b..037a84b 100644
--- a/web/script/player/mediacaps.ts
+++ b/web/script/player/mediacaps.ts
@@ -4,85 +4,58 @@
Copyright (C) 2025 metamuffin <metamuffin.org>
*/
/// <reference lib="dom" />
-import { EncodingProfile, SourceTrack, SourceTrackKind } from "./jhls.d.ts";
+
+import { FormatInfo, StreamContainer } from "./types_stream.ts";
const cache = new Map<string, boolean>()
// TODO this testing method makes the assumption, that if the codec is supported on its own, it can be
// TODO arbitrarly combined with others that are supported. in reality this is true but the spec does not gurantee it.
-export async function test_media_capability(track: SourceTrack): Promise<boolean> {
- const cache_key = `${get_track_kind(track.kind)};${track.codec}`
+export async function test_media_capability(format: FormatInfo, container: StreamContainer): Promise<boolean> {
+ const cache_key = JSON.stringify(format) + container
const cached = cache.get(cache_key);
if (cached !== undefined) return cached
- const r = await test_media_capability_inner(track)
- console.log(`${r ? "positive" : "negative"} media capability test finished for codec=${track.codec}`);
+ const r = await test_media_capability_inner(format, container)
+ console.log(`${r ? "positive" : "negative"} media capability test finished for codec=${format.codec}`);
cache.set(cache_key, r)
return r
}
-async function test_media_capability_inner(track: SourceTrack) {
- if (track.kind == "subtitles") {
+async function test_media_capability_inner(format: FormatInfo, container: StreamContainer) {
+ if (format.codec.startsWith("S_") || format.codec.startsWith("V_") || format.codec.startsWith("D_")) {
// TODO do we need to check this?
- return track.codec == "V_TEXT/WEBVTT" || track.codec == "D_WEBVTT/SUBTITLES"
+ return format.codec == "V_TEXT/WEBVTT" || format.codec == "D_WEBVTT/SUBTITLES"
}
let res;
- const codec = MASTROSKA_CODEC_MAP[track.codec]
- if (!codec) return console.warn(`unknown codec: ${track.codec}`), false
- if ("audio" in track.kind) {
+ if (format.codec.startsWith("A_")) {
res = await navigator.mediaCapabilities.decodingInfo({
type: "media-source",
audio: {
- contentType: `audio/webm; codecs=${codec}`,
- samplerate: track.kind.audio.sample_rate,
- channels: "" + track.kind.audio.channels,
- bitrate: 128 * 1000,
+ contentType: track_to_content_type(format, container),
+ samplerate: format.samplerate,
+ channels: "" + format.channels,
+ bitrate: format.bitrate,
}
})
}
- if ("video" in track.kind) {
+ if (format.codec.startsWith("V_")) {
res = await navigator.mediaCapabilities.decodingInfo({
type: "media-source",
video: {
- contentType: `video/webm; codecs=${codec}`,
- framerate: track.kind.video.fps || 30,
- width: track.kind.video.width,
- height: track.kind.video.height,
- bitrate: 5 * 1000 * 1000 // TODO we dont know this but we should in the future
+ contentType: track_to_content_type(format, container),
+ framerate: 30, // TODO get average framerate from server
+ width: format.width ?? 1920,
+ height: format.height ?? 1080,
+ bitrate: format.bitrate
}
})
}
+ console.log(format, res);
return res?.supported ?? false
}
-export function track_to_content_type(track: SourceTrack): string | undefined {
- if (track.kind == "subtitles") return "video/webm"
- const codec = MASTROSKA_CODEC_MAP[track.codec]
- if (!codec) return
- return `${get_track_kind(track.kind)}/webm; codecs="${codec}"`
-}
-export function profile_to_partial_track(profile: EncodingProfile): SourceTrack {
- if (profile.audio) {
- return {
- codec: FFMPEG_ENCODER_CODEC_MAP[profile.audio.codec],
- kind: { audio: { bit_depth: 16, channels: 2, sample_rate: 48000 } },
- name: "test audio",
- language: "en"
- }
- } else if (profile.video) {
- return {
- codec: FFMPEG_ENCODER_CODEC_MAP[profile.video.codec],
- kind: { video: { fps: 30, height: 1080, width: 1090 } },
- language: "en",
- name: "test video"
- }
- } else if (profile.subtitles) {
- return {
- codec: FFMPEG_ENCODER_CODEC_MAP[profile.subtitles.codec],
- kind: "subtitles",
- language: "en",
- name: "test subtitle"
- }
- } else throw new Error("unreachable");
+export function track_to_content_type(format: FormatInfo, container: StreamContainer): string {
+ return `${CONTAINER_TO_MIME_TYPE[container]}; codecs="${MASTROSKA_CODEC_MAP[format.codec]}"`
}
const MASTROSKA_CODEC_MAP: { [key: string]: string } = {
@@ -96,21 +69,10 @@ const MASTROSKA_CODEC_MAP: { [key: string]: string } = {
"S_TEXT/WEBVTT": "webvtt",
"D_WEBVTT/SUBTITLES": "webvtt",
}
-
-const FFMPEG_ENCODER_CODEC_MAP: { [key: string]: string } = {
- "libsvtav1": "V_AV1",
- "libvpx": "V_VP8",
- "libvpx-vp9": "V_VP9",
- "opus": "A_OPUS",
- "libopus": "A_OPUS",
-}
-
-export type TrackKind = "audio" | "video" | "subtitles"
-export function get_track_kind(track: SourceTrackKind): TrackKind {
- // TODO why different encodings for "subtitles"?
- if (track == "subtitles") return "subtitles"
- if ("subtitles" in track) return "subtitles"
- if ("audio" in track) return "audio"
- if ("video" in track) return "video"
- throw new Error("invalid track");
+const CONTAINER_TO_MIME_TYPE: { [key in StreamContainer]: string } = {
+ webvtt: "text/webvtt",
+ webm: "video/webm",
+ matroska: "video/x-matroska",
+ mpeg4: "video/mp4",
+ jvtt: "application/jellything-vtt+json"
}