Update MP4 over WebSocket support

This commit is contained in:
Alexey Khit
2022-12-04 22:37:15 +03:00
parent 162b11213d
commit e64919838c
+30 -46
View File
@@ -108,10 +108,10 @@ class VideoRTC extends HTMLElement {
]; ];
/** /**
* Supported modes. * Supported modes (webrtc, mse, mse2, mp4, mjpeg).
* @type {string} * @type {string}
*/ */
this.modes = "webrtc,mse2,mp4"; this.modes = "webrtc,mse,mp4";
/** /**
* Run stream when not displayed on the screen. Default `false`. * Run stream when not displayed on the screen. Default `false`.
@@ -303,14 +303,11 @@ class VideoRTC extends HTMLElement {
this.appendChild(this.video); this.appendChild(this.video);
// don't know if styles like this is good idea // important for second video for mode MP4
this.style.display = "block"; this.style.display = "block";
this.style.position = "relative"; this.style.position = "relative";
this.style.width = "100%";
this.style.height = "100%";
// video position absolute important for second video child this.video.style.display = "block"; // fix bottom margin 4px
this.video.style.position = "absolute";
this.video.style.width = "100%"; this.video.style.width = "100%";
this.video.style.height = "100%" this.video.style.height = "100%"
@@ -347,6 +344,7 @@ class VideoRTC extends HTMLElement {
const ts = Date.now(); const ts = Date.now();
this.ws = new WebSocket(this.url); this.ws = new WebSocket(this.url);
this.ws.binaryType = "arraybuffer";
this.ws.addEventListener("open", () => { this.ws.addEventListener("open", () => {
console.debug("VideoRTC.ws.open", this.wsState); console.debug("VideoRTC.ws.open", this.wsState);
@@ -406,7 +404,6 @@ class VideoRTC extends HTMLElement {
this.video.srcObject = null; this.video.srcObject = null;
this.play(); this.play();
this.ws.binaryType = "arraybuffer";
this.ws.addEventListener("message", MediaSourceHandler(ms)); this.ws.addEventListener("message", MediaSourceHandler(ms));
} }
@@ -423,7 +420,6 @@ class VideoRTC extends HTMLElement {
} }
}); });
this.ws.binaryType = "arraybuffer";
this.ws.addEventListener("message", ev => { this.ws.addEventListener("message", ev => {
if (typeof ev.data === "string") { if (typeof ev.data === "string") {
worker.postMessage(ev.data); worker.postMessage(ev.data);
@@ -556,20 +552,9 @@ class VideoRTC extends HTMLElement {
internalMJPEG() { internalMJPEG() {
console.debug("VideoRTC.internalMJPEG"); console.debug("VideoRTC.internalMJPEG");
const reader = new FileReader();
reader.addEventListener("load", () => {
this.video.poster = reader.result;
});
this.ws.binaryType = "blob";
this.ws.addEventListener("message", ev => { this.ws.addEventListener("message", ev => {
if (typeof ev.data !== "string") { if (typeof ev.data === "string") return;
try { this.video.poster = "data:image/jpeg;base64," + VideoRTC.btoa(ev.data);
reader.readAsDataURL(ev.data);
} catch (e) {
console.debug(e);
}
}
}); });
this.send({type: "mjpeg"}); this.send({type: "mjpeg"});
@@ -582,49 +567,48 @@ class VideoRTC extends HTMLElement {
/** @type {HTMLVideoElement} */ /** @type {HTMLVideoElement} */
let video2; let video2;
/** @type {number} */ this.ws.addEventListener("message", ev => {
let i; if (typeof ev.data === "string") return;
const reader = new FileReader(); // first video with default position (set container size)
reader.addEventListener("load", () => { // second video with position=absolute and top=0px
if (video2) { if (video2) {
this.removeChild(this.video); this.removeChild(this.video);
this.video.src = ""; this.video.src = "";
this.video = video2; this.video = video2;
} else { video2.style.position = "";
// get position only once on first packet video2.style.top = "";
i = reader.result.indexOf(";");
console.debug("VideoRTC.file", reader.result.substring(0, i));
} }
video2 = this.video.cloneNode(); video2 = this.video.cloneNode();
video2.style.position = "absolute";
video2.style.top = "0px";
this.appendChild(video2); this.appendChild(video2);
video2.src = "data:video/mp4" + reader.result.substring(i); video2.src = "data:video/mp4;base64," + VideoRTC.btoa(ev.data);
video2.play().catch(() => console.log); video2.play().catch(() => console.log);
}); });
this.ws.binaryType = "blob";
this.ws.addEventListener("message", ev => {
if (typeof ev.data !== "string") {
try {
reader.readAsDataURL(ev.data);
} catch (e) {
console.debug(e);
}
}
});
this.ws.addEventListener("close", () => { this.ws.addEventListener("close", () => {
if (video2) { if (!video2) return;
this.removeChild(video2);
video2.src = ""; this.removeChild(video2);
} video2.src = "";
}); });
this.send({type: "mp4", value: this.codecs("mp4")}); this.send({type: "mp4", value: this.codecs("mp4")});
this.video.controls = false; this.video.controls = false;
} }
static btoa(buffer) {
const bytes = new Uint8Array(buffer);
const len = bytes.byteLength;
let binary = "";
for (let i = 0; i < len; i++) {
binary += String.fromCharCode(bytes[i]);
}
return window.btoa(binary);
}
} }
customElements.define("video-rtc", VideoRTC); customElements.define("video-rtc", VideoRTC);