diff options
Diffstat (limited to 'web/script')
-rw-r--r-- | web/script/player/download.ts | 3 | ||||
-rw-r--r-- | web/script/player/mod.ts | 4 | ||||
-rw-r--r-- | web/script/player/player.ts | 6 | ||||
-rw-r--r-- | web/script/player/profiles.ts | 38 | ||||
-rw-r--r-- | web/script/player/track.ts | 4 |
5 files changed, 41 insertions, 14 deletions
diff --git a/web/script/player/download.ts b/web/script/player/download.ts index 63085b8..86a899f 100644 --- a/web/script/player/download.ts +++ b/web/script/player/download.ts @@ -22,7 +22,6 @@ export class SegmentDownloader { duration: (dl_body - dl_header) / 1000, size: buf.byteLength } - console.log(m); this.measurements.push(m) this.update_bandwidth() } @@ -35,8 +34,6 @@ export class SegmentDownloader { const total_size = this.measurements.reduce((a, v) => v.size + a, 0) const total_duration = this.measurements.reduce((a, v) => v.duration + a, 0) const average = total_size / total_duration - console.log(total_size, average, this.measurements); - this.bandwidth.value = average } } diff --git a/web/script/player/mod.ts b/web/script/player/mod.ts index 9c1b060..89919e4 100644 --- a/web/script/player/mod.ts +++ b/web/script/player/mod.ts @@ -22,7 +22,7 @@ function initialize_player(el: HTMLElement, node_id: string) { el.innerHTML = "" // clear the body const player = new Player(node_id) - const show_stats = new OVar(false); + const show_stats = new OVar(true); const toggle_playing = () => player.playing.value ? player.pause() : player.play() const pri_map = (v: number) => (v / player.duration.value * 100) + "%" @@ -123,7 +123,7 @@ function mouse_idle(e: HTMLElement, timeout: number, cb: (b: boolean) => unknown function show_profile(profile: EncodingProfile): string { if (profile.audio) return `codec=${profile.audio.codec} ar=${show.metric(profile.audio.sample_rate ?? -1, "Hz")} abr=${show.metric(profile.audio.bitrate, "b/s")}` - if (profile.video) return `codec=${profile.video.codec} vw=${show.metric(profile.video.width ?? -1, "Hz")} vbr=${show.metric(profile.video.bitrate, "b/s")} preset=${profile.video.preset}` + if (profile.video) return `codec=${profile.video.codec} vw=${profile.video.width} vbr=${show.metric(profile.video.bitrate, "b/s")} preset=${profile.video.preset}` if (profile.subtitles) return `codec=${profile.subtitles.codec}` return `???` }
\ No newline at end of file diff --git a/web/script/player/player.ts b/web/script/player/player.ts index 08975b2..f3a1f6e 100644 --- a/web/script/player/player.ts +++ b/web/script/player/player.ts @@ -2,6 +2,7 @@ import { OVar, e } from "../jshelper/mod.ts"; import { JhlsMetadata, TimeRange } from "./jhls.d.ts"; import { SegmentDownloader } from "./download.ts"; import { PlayerTrack } from "./track.ts"; +import { ProfileSelector } from "./profiles.ts"; export interface BufferRange extends TimeRange { status: "buffered" | "loading" | "queued" } export class Player { @@ -9,6 +10,7 @@ export class Player { public media_source = new MediaSource(); public tracks = new OVar<PlayerTrack[]>([]); public downloader: SegmentDownloader = new SegmentDownloader(); + public profile_selector!: ProfileSelector public position = new OVar(0) public duration = new OVar(1) @@ -63,10 +65,12 @@ export class Player { const res = await fetch(`/n/${encodeURIComponent(this.node_id)}/stream?format=jhls`) if (!res.ok) return this.error.value = "Cannot download JHLS metadata" const metadata = await res.json() as JhlsMetadata - this.buffering_status.value = undefined + this.buffering_status.value = undefined this.duration.value = metadata.duration this.video.src = URL.createObjectURL(this.media_source) + this.profile_selector = new ProfileSelector(this.downloader.bandwidth, metadata) + this.media_source.addEventListener("sourceopen", async () => { this.tracks.value.push(new PlayerTrack(this, this.node_id, 0, metadata.tracks[0])) this.tracks.value.push(new PlayerTrack(this, this.node_id, 1, metadata.tracks[1])) diff --git a/web/script/player/profiles.ts b/web/script/player/profiles.ts index 3b3379a..b4de534 100644 --- a/web/script/player/profiles.ts +++ b/web/script/player/profiles.ts @@ -1,22 +1,46 @@ import { OVar } from "../jshelper/mod.ts"; import { EncodingProfile, JhlsMetadata } from "./jhls.d.ts"; -export interface EncodingProfileExt extends EncodingProfile { id: number } +export interface EncodingProfileExt extends EncodingProfile { id: number, order: number } export class ProfileSelector { profiles_video: EncodingProfileExt[] = [] profiles_audio: EncodingProfileExt[] = [] profiles_subtitles: EncodingProfileExt[] = [] + remux_bandwidth = new Map<number, { size: number, duration: number }>() constructor(private bandwidth: OVar<number>, private metadata: JhlsMetadata) { for (let id = 0; id < metadata.extra_profiles.length; id++) { const p = metadata.extra_profiles[id]; - if (p.audio) this.profiles_audio.push({ id, ...p }) - if (p.video) this.profiles_video.push({ id, ...p }) - if (p.subtitles) this.profiles_subtitles.push({ id, ...p }) + if (p.audio) this.profiles_audio.push({ id, order: 0, ...p }) + if (p.video) this.profiles_video.push({ id, order: 0, ...p }) + if (p.subtitles) this.profiles_subtitles.push({ id, order: 0, ...p }) } + this.profiles_audio.sort((a, b) => profile_bw(b) - profile_bw(a)) + this.profiles_video.sort((a, b) => profile_bw(b) - profile_bw(a)) + this.profiles_subtitles.sort((a, b) => profile_bw(b) - profile_bw(a)) + for (let i = 0; i < this.profiles_audio.length; i++) this.profiles_audio[i].order = i + for (let i = 0; i < this.profiles_video.length; i++) this.profiles_video[i].order = i + for (let i = 0; i < this.profiles_subtitles.length; i++) this.profiles_subtitles[i].order = i } - - select_optimal_profile(track: number, profile: OVar<EncodingProfileExt>) { - // TODO + profile_list_for_track(track: number): EncodingProfileExt[] { + const i = this.metadata.tracks[track].info.kind + if (i.audio) return this.profiles_audio + if (i.video) return this.profiles_video + if (i.subtitles) return this.profiles_subtitles + return [] + } + select_optimal_profile(track: number, profile: OVar<EncodingProfileExt | undefined>) { + if (this.bandwidth.value < 5000 * 1000) { + profile.value = this.profile_list_for_track(track)[0] + } else { + profile.value = undefined + } } } + +function profile_bw(p: EncodingProfile): number { + if (p.audio) return p.audio.bitrate / 8 + if (p.video) return p.video.bitrate / 8 + if (p.subtitles) return 100 + return 0 +} diff --git a/web/script/player/track.ts b/web/script/player/track.ts index 59690c3..fe4c3c1 100644 --- a/web/script/player/track.ts +++ b/web/script/player/track.ts @@ -78,7 +78,9 @@ export class PlayerTrack { async load(index: number) { this.loading.add(index) - const buf = await this.player.downloader.download(`/n/${encodeURIComponent(this.node_id)}/stream?format=hlsseg&tracks=${this.track_index}&index=${index}`) + this.player.profile_selector.select_optimal_profile(this.track_index, this.profile) + const url = `/n/${encodeURIComponent(this.node_id)}/stream?format=hlsseg&tracks=${this.track_index}&index=${index}${this.profile.value ? `profile=${this.profile.value.id}` : ""}`; + const buf = await this.player.downloader.download(url) await new Promise<void>(cb => { this.append_queue.push({ buf, ...this.metadata.segments[index], index, cb }) this.tick_append() |