From a1a73f7b4575e8e4fa74574146b70d7bc772c596 Mon Sep 17 00:00:00 2001 From: Alexey Khit Date: Sun, 15 Jan 2023 00:12:26 +0300 Subject: [PATCH] Rewrite WS+MP4 format to keyframes stream --- cmd/mp4/ws.go | 2 +- www/video-rtc.js | 56 +++++++++++++++++++-------------------------- www/video-stream.js | 3 +++ 3 files changed, 28 insertions(+), 33 deletions(-) diff --git a/cmd/mp4/ws.go b/cmd/mp4/ws.go index 281ca18b..8b01b00f 100644 --- a/cmd/mp4/ws.go +++ b/cmd/mp4/ws.go @@ -68,7 +68,7 @@ func handlerWSMP4(tr *api.Transport, msg *api.Message) error { return errors.New(api.StreamNotFound) } - cons := &mp4.Segment{} + cons := &mp4.Segment{OnlyKeyframe: true} if codecs, ok := msg.Value.(string); ok { log.Trace().Str("codecs", codecs).Msgf("[mp4] new WS/MP4 consumer") diff --git a/www/video-rtc.js b/www/video-rtc.js index cd96c29b..0bb9e471 100644 --- a/www/video-rtc.js +++ b/www/video-rtc.js @@ -228,16 +228,12 @@ export class VideoRTC extends HTMLElement { this.video.playsInline = true; this.video.preload = "auto"; - this.appendChild(this.video); - - // important for second video for mode MP4 - this.style.display = "block"; - this.style.position = "relative"; - this.video.style.display = "block"; // fix bottom margin 4px this.video.style.width = "100%"; this.video.style.height = "100%" + this.appendChild(this.video); + if (this.background) return; if ("hidden" in document && this.visibilityCheck) { @@ -547,46 +543,42 @@ export class VideoRTC extends HTMLElement { onmjpeg() { this.ondata = data => { + this.video.controls = false; this.video.poster = "data:image/jpeg;base64," + VideoRTC.btoa(data); }; this.send({type: "mjpeg"}); - this.video.controls = false; } onmp4() { - /** @type {HTMLVideoElement} */ - let video2; + /** @type {HTMLCanvasElement} **/ + const canvas = document.createElement("canvas"); + /** @type {CanvasRenderingContext2D} */ + let context; - this.ondata = data => { - // first video with default position (set container size) - // second video with position=absolute and top=0px - if (video2) { - this.removeChild(this.video); - this.video.src = ""; - this.video = video2; - video2.style.position = ""; - video2.style.top = ""; + /** @type {HTMLVideoElement} */ + const video2 = document.createElement("video"); + video2.autoplay = true; + video2.muted = true; + + video2.addEventListener("loadeddata", ev => { + if (!context) { + canvas.width = video2.videoWidth; + canvas.height = video2.videoHeight; + context = canvas.getContext('2d'); } - video2 = this.video.cloneNode(); - video2.style.position = "absolute"; - video2.style.top = "0px"; - this.appendChild(video2); + context.drawImage(video2, 0, 0, canvas.width, canvas.height); - video2.src = "data:video/mp4;base64," + VideoRTC.btoa(data); - video2.play().catch(() => console.log); - }; - - this.ws.addEventListener("close", () => { - if (!video2) return; - - this.removeChild(video2); - video2.src = ""; + this.video.controls = false; + this.video.poster = canvas.toDataURL("image/jpeg"); }); + this.ondata = data => { + video2.src = "data:video/mp4;base64," + VideoRTC.btoa(data); + }; + this.send({type: "mp4", value: this.codecs("mp4")}); - this.video.controls = false; } static btoa(buffer) { diff --git a/www/video-stream.js b/www/video-stream.js index c6b68a54..22615dc5 100644 --- a/www/video-stream.js +++ b/www/video-stream.js @@ -22,6 +22,9 @@ class VideoStream extends VideoRTC { this.innerHTML = `