diff options
author | metamuffin <metamuffin@disroot.org> | 2023-10-02 20:07:09 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-10-02 20:07:09 +0200 |
commit | f783143b4adf22be662db1af2ca00b34a868cf72 (patch) | |
tree | 180ea44b0f7e7052231643da6e929b1be5f8def1 /web/script/player/player.ts | |
parent | e25beb3e0c2531b09d8efd70e858396dcc631dd2 (diff) | |
download | jellything-f783143b4adf22be662db1af2ca00b34a868cf72.tar jellything-f783143b4adf22be662db1af2ca00b34a868cf72.tar.bz2 jellything-f783143b4adf22be662db1af2ca00b34a868cf72.tar.zst |
player: split files
Diffstat (limited to 'web/script/player/player.ts')
-rw-r--r-- | web/script/player/player.ts | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/web/script/player/player.ts b/web/script/player/player.ts new file mode 100644 index 0000000..5c38dc8 --- /dev/null +++ b/web/script/player/player.ts @@ -0,0 +1,98 @@ +import { OVar, e } from "../jshelper/mod.ts"; +import { JhlsMetadata, TimeRange } from "./jhls.d.ts"; +import { PlayerTrack } from "./track.ts"; + +export interface BufferRange extends TimeRange { status: "buffered" | "loading" | "queued" } +export class Player { + public video = e("video") + private media_source = new MediaSource(); + public tracks = new OVar<PlayerTrack[]>([]); + + public position = new OVar(0) + public duration = new OVar(1) + public playing = new OVar(false) + public canplay = new OVar(false) + public buffering_status = new OVar<string | undefined>(undefined) + public error = new OVar<string | undefined>(undefined) + + constructor(private node_id: string) { + this.video.onloadedmetadata = () => { } + this.video.ondurationchange = () => { } + this.video.ontimeupdate = () => { + this.position.value = this.video.currentTime + this.update() // TODO maybe not here + } + this.video.onplay = () => { + console.log("play"); + this.buffering_status.value = "Resuming playback..."; + } + this.video.onwaiting = () => { + console.log("waiting"); + this.buffering_status.value = "Buffering..."; + this.canplay.value = false; + } + this.video.onplaying = () => { + console.log("playing"); + this.playing.value = true; + this.buffering_status.value = undefined; + } + this.video.onpause = () => { + console.log("pause"); + this.playing.value = false + } + this.video.oncanplay = () => { + console.log("canplay"); + this.buffering_status.value = undefined + this.canplay.value = true + } + this.video.onseeking = () => { + console.log("seeking"); + this.buffering_status.value = "Seeking..." + } + this.video.onseeked = () => { + console.log("seeked"); + this.buffering_status.value = undefined + } + this.fetch_meta() + } + + async fetch_meta() { + this.buffering_status.value = "Loading JHLS metadata..." + 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.duration.value = metadata.duration + this.video.src = URL.createObjectURL(this.media_source) + this.media_source.addEventListener("sourceopen", async () => { + this.tracks.value.push(new PlayerTrack(this.media_source, this.node_id, 0, metadata.tracks[0])) + this.tracks.value.push(new PlayerTrack(this.media_source, this.node_id, 1, metadata.tracks[1])) + this.tracks.change() + this.buffering_status.value = "Fetching initial segments..." + this.update() + await this.canplay.wait_for(true) + this.buffering_status.value = undefined + }) + } + async update(newt?: number) { + await Promise.all(this.tracks.value.map(t => t.update(newt ?? this.video.currentTime))) + } + + play() { + this.video.play() + } + pause() { + this.video.pause() + } + frame_forward() { + //@ts-ignore trust me bro + this.video["seekToNextFrame"]() + } + async seek(p: number) { + this.buffering_status.value = "Buffering at target..." + await this.update(p) + this.video.currentTime = p + } +} + |