diff options
author | metamuffin <metamuffin@disroot.org> | 2024-04-29 20:12:56 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2024-04-29 20:14:26 +0200 |
commit | 4f926ff6baff0621e3fa0cb5873b082f9ef963b2 (patch) | |
tree | 00554f842a7e8c67ca7a5344f6eaabefcdec5bcb /client-web/source/resource/track.ts | |
parent | ec1f16b65aa731b868ab7343f9fe539aaae9202a (diff) | |
download | keks-meet-4f926ff6baff0621e3fa0cb5873b082f9ef963b2.tar keks-meet-4f926ff6baff0621e3fa0cb5873b082f9ef963b2.tar.bz2 keks-meet-4f926ff6baff0621e3fa0cb5873b082f9ef963b2.tar.zst |
stream previews on requestv1.1.0
Diffstat (limited to 'client-web/source/resource/track.ts')
-rw-r--r-- | client-web/source/resource/track.ts | 70 |
1 files changed, 51 insertions, 19 deletions
diff --git a/client-web/source/resource/track.ts b/client-web/source/resource/track.ts index 75208d0..56c2b30 100644 --- a/client-web/source/resource/track.ts +++ b/client-web/source/resource/track.ts @@ -10,12 +10,16 @@ import { PO } from "../locale/mod.ts"; import { log } from "../logger.ts"; import { on_pref_changed, PREFS } from "../preferences/mod.ts"; import { get_rnnoise_node } from "../rnnoise.ts"; -import { Room } from "../room.ts"; import { LocalResource, ResourceHandlerDecl } from "./mod.ts"; export const resource_track: ResourceHandlerDecl = { kind: "track", - new_remote: (info, _user, enable) => { + new_remote: (info, user, enable) => { + const can_preview = info.track_kind == "video" + let preview_enabled = can_preview + if (preview_enabled) user.send_to({ preview_request: { id: info.id } }) + + let preview_request_timeout: number | undefined; const enable_label = PO.enable(`"${info.label ?? info.kind}"`) const enable_button = e("button", { class: "center", @@ -30,7 +34,12 @@ export const resource_track: ResourceHandlerDecl = { info, el: e("div", { class: [`media-${info.track_kind}`] }, enable_button), on_statechange() { }, - on_preview(preview) { + on_preview_response(preview, expire) { + if (!preview_enabled) return + preview_request_timeout = setTimeout(() => { + user.request_preview(this) + }, Math.max(expire, 500)) + if (this.el.querySelector("audio, video")) return let pi = this.el.querySelector(".preview") as HTMLImageElement if (!pi) { @@ -42,12 +51,19 @@ export const resource_track: ResourceHandlerDecl = { pi.src = preview }, on_enable(stream, disable) { + preview_enabled = false; + clearTimeout(preview_request_timeout); + this.el.removeChild(enable_button) if (!(stream instanceof MediaStream)) return console.warn("expected mediastream"); this.el.append(e("button", { icon: "close", class: ["topleft", "abort"], onclick: (self) => { + if (can_preview) { + preview_enabled = true; + user.request_preview(this) + } disable() this.el.appendChild(enable_button) self.disabled = true @@ -64,17 +80,18 @@ export const resource_track: ResourceHandlerDecl = { export function new_local_track(info: ProvideInfo, stream: MediaStream, ...extra_controls: HTMLElement[]): LocalResource { let destroy: () => void; - let room: Room; - const el = e("div", { class: `media-${stream.getVideoTracks().length > 0 ? "video" : "audio"}` }, e("button", { icon: "stop", class: ["abort", "topleft"], onclick: () => destroy() }, PO.stop_sharing), ...extra_controls ); + let preview: string | undefined; + let preview_on_ready: (() => void)[] | undefined = [] + let last_preview_ts: number = Date.now(); const generate_previews = (video: HTMLVideoElement) => { const canvas = document.createElement("canvas") const context = canvas.getContext("2d")! - setInterval(() => { + const update_preview = () => { const res = PREFS.preview_resolution canvas.width = res canvas.height = res * video.videoHeight / video.videoWidth @@ -86,18 +103,31 @@ export function new_local_track(info: ProvideInfo, stream: MediaStream, ...extra if (!blob) return log({ error: true, scope: "media" }, "Failed to encode stream preview"); const reader = new FileReader(); reader.addEventListener("load", ev => { - const data_url = ev.target!.result as string; - room.signaling.send_relay({ preview: { id: info.id, data: data_url } }) + preview = ev.target!.result as string; + preview_on_ready?.forEach(f => f()) + preview_on_ready = undefined + last_preview_ts = Date.now() }) reader.readAsDataURL(blob) }, "image/webp", PREFS.preview_encoding_quality * 0.01) - }, 1000 * PREFS.preview_rate) + }; + setTimeout(update_preview, 1000) + const interval = setInterval(update_preview, 1000 * PREFS.preview_rate) + return () => clearInterval(interval) } create_track_display(el, stream, true, generate_previews) return { - set_room(r) { room = r }, set_destroy(cb) { destroy = cb }, + async on_preview_request(_user) { + await new Promise<void>(done => { + if (preview_on_ready) { + log("media", "preview delayed") + preview_on_ready.push(done) + } else done() + }) + return { data: preview, expire: (1000 * PREFS.preview_rate) - (Date.now() - last_preview_ts) + 500 }; + }, info, el, destroy() { @@ -110,7 +140,7 @@ export function new_local_track(info: ProvideInfo, stream: MediaStream, ...extra } } -function create_track_display(target: HTMLElement, stream: MediaStream, local: boolean, preview_callback?: (v: HTMLVideoElement) => void): HTMLElement { +function create_track_display(target: HTMLElement, stream: MediaStream, local: boolean, preview_callback?: (v: HTMLVideoElement) => (() => void)): HTMLElement { const is_video = stream.getVideoTracks().length > 0 const is_audio = stream.getAudioTracks().length > 0 @@ -137,15 +167,17 @@ function create_track_display(target: HTMLElement, stream: MediaStream, local: b else target.classList.remove("audio-active") } }) - let fullscreen + let fullscreen: HTMLButtonElement | undefined; if (is_video) { - fullscreen = e("button", { icon: "fullscreen", class: ["topright", "fullscreen"], - onclick() { - if (document.fullscreenElement && document.fullscreenElement !== null) - document.exitFullscreen() - else - media_el.requestFullscreen() - }}, PO.fullscreen) + fullscreen = e("button", { + icon: "fullscreen", class: ["topright", "fullscreen"], + onclick() { + if (document.fullscreenElement && document.fullscreenElement !== null) + document.exitFullscreen() + else + media_el.requestFullscreen() + } + }, PO.fullscreen) target.prepend(fullscreen) } |