import "./libs/adapter.min.js";
import "./tensorflow.js";
import "./webrtcstreamer.js";
class WebRTCStreamerElement extends HTMLElement {
static get observedAttributes() {
return ['url', 'options', 'webrtcurl', 'notitle', 'width', 'height', 'algo'];
}
constructor() {
super();
this.shadowDOM = this.attachShadow({mode: 'open'});
this.shadowDOM.innerHTML = `
`;
this.initialized = false;
this.titleElement = this.shadowDOM.getElementById("title");
this.videoElement = this.shadowDOM.getElementById("video");
this.canvasElement = this.shadowDOM.getElementById("canvas");
this.modelLoaded = {};
}
connectedCallback() {
this.connectStream(true);
this.initialized = true;
}
disconnectedCallback() {
this.disconnectStream();
this.initialized = false;
}
attributeChangedCallback(attrName, oldVal, newVal) {
if (attrName === "notitle") {
this.titleElement.style.visibility = "hidden";
} else if (attrName === "width") {
this.videoElement.style.width = newVal;
} else if (attrName === "height") {
this.videoElement.style.height = newVal;
} if (this.initialized) {
this.connectStream((attrName !== "algo"));
}
}
disconnectStream() {
if (this.webRtcServer) {
this.webRtcServer.disconnect();
this.webRtcServer = null;
}
}
connectStream(reconnect) {
const webrtcurl = this.getAttribute("webrtcurl");
let videostream;
let audiostream;
const url = this.getAttribute("url");
if (url) {
try {
let urljson = JSON.parse(url);
videostream = urljson.video;
audiostream = urljson.audio;
} catch (e) {
videostream = url;
}
const notitle = this.getAttribute("notitle");
if (notitle === null) {
this.titleElement.innerHTML = videostream;
}
this.videoElement.title = videostream;
// stop running algo
Object.values(this.modelLoaded).forEach( promise => {
if (promise.model) {
promise.model.run = null;
}
});
let imgLoaded;
if (reconnect) {
this.disconnectStream();
imgLoaded = new Promise( (resolve,rejet) => {
this.videoElement.addEventListener('loadedmetadata', () => resolve(), { once: true });
} );
this.webRtcServer = new WebRtcStreamer(this.videoElement, webrtcurl);
this.webRtcServer.connect(videostream, audiostream, this.getAttribute("options"));
} else {
imgLoaded = new Promise( (resolve) => resolve() );
}
const algo = this.getAttribute("algo")
let modelLoaded = this.getModelPromise(algo);
Promise.all([imgLoaded, modelLoaded]).then(([event,model]) => {
this.setVideoSize(this.videoElement.videoWidth, this.videoElement.videoHeight)
model.run = this.getModelRunFunction(algo);
if (model.run) {
model.run(model, this.videoElement, this.canvasElement)
modelLoaded.model = model;
}
});
}
}
setVideoSize(width, height) {
this.videoElement.width = width;
this.videoElement.height = height;
this.canvasElement.width = width;
this.canvasElement.height = height;
}
getModelPromise(algo) {
let modelLoaded;
if (this.modelLoaded[algo]) {
modelLoaded = this.modelLoaded[algo];
}
else {
if (algo === "posenet") {
modelLoaded = posenet.load();
} else if (algo === "deeplab") {
modelLoaded = deeplab.load()
} else if (algo === "cocossd") {
modelLoaded = cocoSsd.load();
} else if (algo === "bodyPix") {
modelLoaded = bodyPix.load();
} else if (algo === "blazeface") {
modelLoaded = blazeface.load();
} else {
modelLoaded = new Promise( (resolve) => resolve() );
}
this.modelLoaded[algo] = modelLoaded;
}
return modelLoaded;
}
getModelRunFunction(algo) {
let modelFunction;
if (algo === "posenet") {
modelFunction = runPosenet;
} else if (algo === "deeplab") {
modelFunction = runDeeplab;
} else if (algo === "cocossd") {
modelFunction = runDetect;
} else if (algo === "bodyPix") {
modelFunction = runbodyPix;
} else if (algo === "blazeface") {
modelFunction = runblazeface;
}
return modelFunction;
}
}
customElements.define('webrtc-streamer', WebRTCStreamerElement);