From 959f21359c2fd10761fb1e99308e87649a444aa7 Mon Sep 17 00:00:00 2001 From: Jurij Date: Tue, 6 Jun 2023 13:24:19 +0200 Subject: [PATCH] Iz janusa na proxied mjpeg --- www/index.html | 21 ++- www/js/streaming.js | 350 ++------------------------------------ www/js/streaming.js.bak | 367 ++++++++++++++++++++++++++++++++++++++++ www/stil.css | 2 +- 4 files changed, 401 insertions(+), 339 deletions(-) create mode 100644 www/js/streaming.js.bak diff --git a/www/index.html b/www/index.html index 6dc70e7..9b9973f 100644 --- a/www/index.html +++ b/www/index.html @@ -15,6 +15,22 @@ + + + + @@ -23,8 +39,9 @@

je umetniška instalacija, ki je del razstave Nevidni sopotnik v Mestni galeriji Nova Gorica.   Spodnja konzola vam omogoča upravljanje tamkajšnjega lebdečega objekta.

-
- +
+ +
diff --git a/www/js/streaming.js b/www/js/streaming.js index 0c8f428..651b913 100644 --- a/www/js/streaming.js +++ b/www/js/streaming.js @@ -1,23 +1,3 @@ -// We import the settings.js file to know which address we should contact -// to talk to Janus, and optionally which STUN/TURN servers should be -// used as well. Specifically, that file defines the "server" and -// "iceServers" properties we'll pass when creating the Janus session. - -var janus = null; -var streaming = null; -var opaqueId = "streamingtest-"+Janus.randomString(12); - -var remoteTracks = {}, dataMid = null; -var bitrateTimer = {}; -var spinner = {}; - -var simulcastStarted = {}, svcStarted = {}; - -var streamsList = {}; - -// Kar fiksiramo na 666 -var selectedStream = 666; - window.addEventListener('DOMContentLoaded', function () { var predvajaj = document.querySelector('#predvajaj'); @@ -32,340 +12,38 @@ window.addEventListener('DOMContentLoaded', function () { // Funkcije za veckratno rabo function omogociGumbe(kdaj) { setTimeout(function () { - vsiGumbi.forEach(function (gEl) { + vsiGumbi.forEach(function (gEl) { gEl.toggleAttribute('disabled', false); - }); + }); }, kdaj); } function onemogociGumbe() { vsiGumbi.forEach(function (gEl) { - gEl.toggleAttribute('disabled', true); + gEl.toggleAttribute('disabled', true); }); } - - function gremoLevo() { + // Gumbi levo in desno + gLevo.addEventListener('click', function () { console.log('GREMO LEVO!'); window.peljiLevo(); - onemogociGumbe(); - omogociGumbe(DOLZINA + PAVZA); - } - function gremoRavno() { - console.log('GREMO RAVNO!'); - window.peljiRavno(); onemogociGumbe(); omogociGumbe(DOLZINA + PAVZA); - } - function gremoDesno() { + }); + gDesno.addEventListener('click', function () { console.log('GREMO DESNO!'); window.peljiDesno(); onemogociGumbe(); omogociGumbe(DOLZINA + PAVZA); - } + }); + gRavno.addEventListener('click', function () { + console.log('GREMO RAVNO!'); + window.peljiRavno(); - // Initialize the library (all console debuggers enabled) - Janus.init({debug: "all", callback: function() { - // Make sure the browser supports WebRTC - if(!Janus.isWebrtcSupported()) { - console.log("ERROR cannot start; no WebRTC support... "); - return; - } - // Create session - janus = new Janus({ - server: server, - iceServers: iceServers, - // Should the Janus API require authentication, you can specify either the API secret or user token here too - // token: "mytoken", - // or - // apisecret: "serversecret", - success: function() { - // Attach to Streaming plugin - janus.attach({ - plugin: "janus.plugin.streaming", - opaqueId: opaqueId, - success: function(pluginHandle) { - streaming = pluginHandle; - Janus.log("Plugin attached! (" + streaming.getPlugin() + ", id=" + streaming.getId() + ")"); - - // Setup streaming session - updateStreamsList(); - - /* ustavitev neka? - for(var i in bitrateTimer) - clearInterval(bitrateTimer[i]); - bitrateTimer = {}; - janus.destroy(); - */ - - - // Kar zacnimo stream - startStream(); - }, - error: function(error) { - Janus.error(" -- Error attaching plugin... ", error); - }, - iceState: function(state) { - Janus.log("ICE state changed to " + state); - }, - webrtcState: function(on) { - Janus.log("Janus says our WebRTC PeerConnection is " + (on ? "up" : "down") + " now"); - if (on) { - // Gumbi levo in desno - gLevo.addEventListener('click', gremoLevo); - gDesno.addEventListener('click', gremoDesno); - gRavno.addEventListener('click', gremoRavno); - } else { - gLevo.removeEventListener('click', gremoLevo); - gDesno.removeEventListener('click', gremoDesno); - gRavno.removeEventListener('click', gremoRavno); - } - }, - slowLink: function(uplink, lost, mid) { - Janus.warn("Janus reports problems " + (uplink ? "sending" : "receiving") + - " packets on mid " + mid + " (" + lost + " lost packets)"); - }, - onmessage: function(msg, jsep) { - Janus.debug(" ::: Got a message :::", msg); - var result = msg["result"]; - if(result) { - if(result["status"]) { - var status = result["status"]; -// if(status === 'starting') -// else if(status === 'started') -// else if(status === 'stopped') - if(status === 'stopped') { - stopStream(); - } - } else if(msg["streaming"] === "event") { - // Does this event refer to a mid in particular? - var mid = result["mid"] ? result["mid"] : "0"; - // Is simulcast in place? - var substream = result["substream"]; - var temporal = result["temporal"]; - if((substream !== null && substream !== undefined) || (temporal !== null && temporal !== undefined)) { - if(!simulcastStarted[mid]) { - simulcastStarted[mid] = true; - } - } - // Is VP9/SVC in place? - var spatial = result["spatial_layer"]; - temporal = result["temporal_layer"]; - } - } else if(msg["error"]) { - console.log('NAPAKA', msg["error"]); - stopStream(); - return; - } - if(jsep) { - Janus.debug("Handling SDP as well...", jsep); - var stereo = (jsep.sdp.indexOf("stereo=1") !== -1); - // Offer from the plugin, let's answer - streaming.createAnswer({ - jsep: jsep, - // We only specify data channels here, as this way in - // case they were offered we'll enable them. Since we - // don't mention audio or video tracks, we autoaccept them - // as recvonly (since we won't capture anything ourselves) - tracks: [{ type: 'data' }], - customizeSdp: function(jsep) { - if(stereo && jsep.sdp.indexOf("stereo=1") == -1) { - // Make sure that our offer contains stereo too - jsep.sdp = jsep.sdp.replace("useinbandfec=1", "useinbandfec=1;stereo=1"); - } - }, - success: function(jsep) { - Janus.debug("Got SDP!", jsep); - var body = { request: "start" }; - streaming.send({ message: body, jsep: jsep }); - }, - error: function(error) { - Janus.error("WebRTC error:", error); - } - }); - } - }, - onremotetrack: function(track, mid, on, metadata) { - Janus.debug("Remote track (mid=" + mid + ") " + (on ? "added" : "removed") + - (metadata ? " (" + metadata.reason + ") ": "") + ":", track - ); - - var mstreamId = "mstream"+mid; - if(streamsList[selectedStream] && streamsList[selectedStream].legacy) { - mstreamId = "mstream0"; - } - - console.log('dodam?', on); - if(true) { - // If we're here, a new track was added - var stream = null; - - // New video track: create a stream out of it - stream = new MediaStream([track]); - console.log('MOJ PRETOK!', stream, track); - remoteTracks[mid] = stream; - Janus.log("Created remote video stream:", stream); - - var vidEl = document.querySelector('#videofeed'); - var zaslonEl = document.querySelector('.zaslon'); - - /* bitrate in resolucija - if(!bitrateTimer[mid]) { - bitrateTimer[mid] = setInterval(function() { - // Display updated bitrate, if supported - var bitrate = streaming.getBitrate(mid); - console.log('bitrate:', bitrate); - - // Check if the resolution changed too - var width = vidEl.videoWidth; - var height = vidEl.videoHeight; - if (width > 0 && height > 0) console.log('resolucija', width+'x'+height); - }, 1000); - } - */ - console.log('dodajam pretok', vidEl, stream); - Janus.attachMediaStream(vidEl, stream); - - vidEl.addEventListener('canplay', function () { - console.log('lahko predvajam!'); - zaslonEl.classList.remove('cakam'); - }); - - // Moramo kliknit za predvajanje :/ - // predvajaj.style.display = 'block'; - predvajaj.addEventListener('click', function () { - predvajaj.style.display = 'none'; - vidEl.play(); - }); - - vidEl.addEventListener('play', function () { - glavno.classList.add('predvajam'); - predvajaj.style.display = 'none'; - }); - - //vidEl.play(); - } - }, - ondataopen: function(data) { - Janus.log("The DataChannel is available!"); - window.dataKanal = data; - }, - ondata: function(data) { - Janus.debug("We got data from the DataChannel!", data); - console.log('DUBU DATA', data); - obdelajData(data); - }, - oncleanup: function() { - Janus.log(" ::: Got a cleanup notification :::"); - for(var i in bitrateTimer) - clearInterval(bitrateTimer[i]); - bitrateTimer = {}; - remoteTracks = {}; - dataMid = null; - } - }); - }, - error: function(error) { - Janus.error(error); - }, - destroyed: function() { - window.location.reload(); - } - }); -}}); -}); - -function updateStreamsList() { - var body = { request: "list" }; - Janus.debug("Sending message:", body); - streaming.send({ message: body, success: function(result) { - if(!result) { - console.log("Error: Got no response to our query for available streams"); - return; - } - if(result["list"]) { - var list = result["list"]; - if(list && Array.isArray(list)) { - list.sort(function(a, b) { - if(!a || a.id < (b ? b.id : 0)) - return -1; - if(!b || b.id < (a ? a.id : 0)) - return 1; - return 0; - }); - } - Janus.log("Got a list of available streams:", list); - streamsList = {}; - for(var mp in list) { - Janus.debug(" >> [" + list[mp]["id"] + "] " + list[mp]["description"] + " (" + list[mp]["type"] + ")"); - // Check the nature of the available streams, and if there are some multistream ones - list[mp].legacy = true; - if(list[mp].media) { - var audios = 0, videos = 0; - for(var mi in list[mp].media) { - if(!list[mp].media[mi]) - continue; - if(list[mp].media[mi].type === "audio") - audios++; - else if(list[mp].media[mi].type === "video") - videos++; - if(audios > 1 || videos > 1) { - list[mp].legacy = false; - break; - } - } - } - // Keep track of all the available streams - streamsList[list[mp]["id"]] = list[mp]; - } - - // Dajmo kar zacet - startStream(); - } - }}); -} - -function getStreamInfo() { - // Send a request for more info on the mountpoint we subscribed to - var body = { request: "info", id: parseInt(selectedStream) || selectedStream }; - streaming.send({ message: body, success: function(result) { - if(result && result.info && result.info.metadata) { - console.log('STREAM META', result.info.metadata); - } - }}); -} - -function startStream() { - Janus.log("Selected video id #" + selectedStream); - console.log('zacenjam', selectedStream, streamsList[selectedStream]); - if(!selectedStream || !streamsList[selectedStream]) { - console.log("Error: No stream selected to start"); - return; - } - - if(streamsList[selectedStream].legacy) { - for(mi in streamsList[selectedStream].media) { - // Add a new panel - var type = streamsList[selectedStream].media[mi].type; - if(type === "video") { - mid = streamsList[selectedStream].media[mi].mid; - break; - } - } - } - // Prepare the request to start streaming and send it - var body = { request: "watch", id: parseInt(selectedStream) || selectedStream }; - streaming.send({ message: body }); - getStreamInfo(); -} - -function stopStream() { - streaming.send({ message: body }); - streaming.hangup(); -} - -function obdelajData(data) { - console.log('obdelam webrtc podatke', data); + onemogociGumbe(); + omogociGumbe(DOLZINA + PAVZA); + }); } diff --git a/www/js/streaming.js.bak b/www/js/streaming.js.bak new file mode 100644 index 0000000..9bc5092 --- /dev/null +++ b/www/js/streaming.js.bak @@ -0,0 +1,367 @@ +// We import the settings.js file to know which address we should contact +// to talk to Janus, and optionally which STUN/TURN servers should be +// used as well. Specifically, that file defines the "server" and +// "iceServers" properties we'll pass when creating the Janus session. + +var janus = null; +var streaming = null; +var opaqueId = "streamingtest-"+Janus.randomString(12); + +var remoteTracks = {}, dataMid = null; +var bitrateTimer = {}; +var spinner = {}; + +var simulcastStarted = {}, svcStarted = {}; + +var streamsList = {}; + +// Kar fiksiramo na 666 +var selectedStream = 666; + +window.addEventListener('DOMContentLoaded', function () { + + var predvajaj = document.querySelector('#predvajaj'); + var gumbi = document.querySelector('#predvajaj'); + var glavno = document.querySelector('#glavno'); + + var gLevo = document.querySelector('#levo'); + var gDesno = document.querySelector('#desno'); + var gRavno = document.querySelector('#ravno'); + var vsiGumbi = [gLevo, gDesno, gRavno]; + + // Funkcije za veckratno rabo + function omogociGumbe(kdaj) { + setTimeout(function () { + vsiGumbi.forEach(function (gEl) { + gEl.toggleAttribute('disabled', false); + }); + }, kdaj); + } + + function onemogociGumbe() { + vsiGumbi.forEach(function (gEl) { + gEl.toggleAttribute('disabled', true); + }); + } + + // Initialize the library (all console debuggers enabled) + Janus.init({debug: "all", callback: function() { + // Make sure the browser supports WebRTC + if(!Janus.isWebrtcSupported()) { + console.log("ERROR cannot start; no WebRTC support... "); + return; + } + // Create session + janus = new Janus({ + server: server, + iceServers: iceServers, + // Should the Janus API require authentication, you can specify either the API secret or user token here too + // token: "mytoken", + // or + // apisecret: "serversecret", + success: function() { + // Attach to Streaming plugin + janus.attach({ + plugin: "janus.plugin.streaming", + opaqueId: opaqueId, + success: function(pluginHandle) { + streaming = pluginHandle; + Janus.log("Plugin attached! (" + streaming.getPlugin() + ", id=" + streaming.getId() + ")"); + + // Setup streaming session + updateStreamsList(); + + /* ustavitev neka? + for(var i in bitrateTimer) + clearInterval(bitrateTimer[i]); + bitrateTimer = {}; + janus.destroy(); + */ + + + // Kar zacnimo stream + startStream(); + }, + error: function(error) { + Janus.error(" -- Error attaching plugin... ", error); + }, + iceState: function(state) { + Janus.log("ICE state changed to " + state); + }, + webrtcState: function(on) { + Janus.log("Janus says our WebRTC PeerConnection is " + (on ? "up" : "down") + " now"); + if (on) { + // Gumbi levo in desno + gLevo.addEventListener('click', function () { + console.log('GREMO LEVO!'); + window.peljiLevo(); + + onemogociGumbe(); + omogociGumbe(DOLZINA + PAVZA); + }); + gDesno.addEventListener('click', function () { + console.log('GREMO DESNO!'); + window.peljiDesno(); + + onemogociGumbe(); + omogociGumbe(DOLZINA + PAVZA); + }); + gRavno.addEventListener('click', function () { + console.log('GREMO RAVNO!'); + window.peljiRavno(); + + onemogociGumbe(); + omogociGumbe(DOLZINA + PAVZA); + }); + } else { + gLevo.removeEventListener('click'); + gDesno.removeEventListener('click'); + gRavno.removeEventListener('click'); + } + }, + slowLink: function(uplink, lost, mid) { + Janus.warn("Janus reports problems " + (uplink ? "sending" : "receiving") + + " packets on mid " + mid + " (" + lost + " lost packets)"); + }, + onmessage: function(msg, jsep) { + Janus.debug(" ::: Got a message :::", msg); + var result = msg["result"]; + if(result) { + if(result["status"]) { + var status = result["status"]; +// if(status === 'starting') +// else if(status === 'started') +// else if(status === 'stopped') + if(status === 'stopped') { + stopStream(); + } + } else if(msg["streaming"] === "event") { + // Does this event refer to a mid in particular? + var mid = result["mid"] ? result["mid"] : "0"; + // Is simulcast in place? + var substream = result["substream"]; + var temporal = result["temporal"]; + if((substream !== null && substream !== undefined) || (temporal !== null && temporal !== undefined)) { + if(!simulcastStarted[mid]) { + simulcastStarted[mid] = true; + } + } + // Is VP9/SVC in place? + var spatial = result["spatial_layer"]; + temporal = result["temporal_layer"]; + } + } else if(msg["error"]) { + console.log('NAPAKA', msg["error"]); + stopStream(); + return; + } + if(jsep) { + Janus.debug("Handling SDP as well...", jsep); + var stereo = (jsep.sdp.indexOf("stereo=1") !== -1); + // Offer from the plugin, let's answer + streaming.createAnswer({ + jsep: jsep, + // We only specify data channels here, as this way in + // case they were offered we'll enable them. Since we + // don't mention audio or video tracks, we autoaccept them + // as recvonly (since we won't capture anything ourselves) + tracks: [{ type: 'data' }], + customizeSdp: function(jsep) { + if(stereo && jsep.sdp.indexOf("stereo=1") == -1) { + // Make sure that our offer contains stereo too + jsep.sdp = jsep.sdp.replace("useinbandfec=1", "useinbandfec=1;stereo=1"); + } + }, + success: function(jsep) { + Janus.debug("Got SDP!", jsep); + var body = { request: "start" }; + streaming.send({ message: body, jsep: jsep }); + }, + error: function(error) { + Janus.error("WebRTC error:", error); + } + }); + } + }, + onremotetrack: function(track, mid, on, metadata) { + Janus.debug("Remote track (mid=" + mid + ") " + (on ? "added" : "removed") + + (metadata ? " (" + metadata.reason + ") ": "") + ":", track + ); + + var mstreamId = "mstream"+mid; + if(streamsList[selectedStream] && streamsList[selectedStream].legacy) { + mstreamId = "mstream0"; + } + + console.log('dodam?', on); + if(true) { + // If we're here, a new track was added + var stream = null; + + // New video track: create a stream out of it + stream = new MediaStream([track]); + console.log('MOJ PRETOK!', stream, track); + remoteTracks[mid] = stream; + Janus.log("Created remote video stream:", stream); + + var vidEl = document.querySelector('#videofeed'); + var zaslonEl = document.querySelector('.zaslon'); + + /* bitrate in resolucija + if(!bitrateTimer[mid]) { + bitrateTimer[mid] = setInterval(function() { + // Display updated bitrate, if supported + var bitrate = streaming.getBitrate(mid); + console.log('bitrate:', bitrate); + + // Check if the resolution changed too + var width = vidEl.videoWidth; + var height = vidEl.videoHeight; + if (width > 0 && height > 0) console.log('resolucija', width+'x'+height); + }, 1000); + } + */ + console.log('dodajam pretok', vidEl, stream); + Janus.attachMediaStream(vidEl, stream); + + vidEl.addEventListener('canplay', function () { + console.log('lahko predvajam!'); + zaslonEl.classList.remove('cakam'); + }); + + // Moramo kliknit za predvajanje :/ + // predvajaj.style.display = 'block'; + predvajaj.addEventListener('click', function () { + predvajaj.style.display = 'none'; + vidEl.play(); + }); + + vidEl.addEventListener('play', function () { + glavno.classList.add('predvajam'); + predvajaj.style.display = 'none'; + }); + + //vidEl.play(); + } + }, + ondataopen: function(data) { + Janus.log("The DataChannel is available!"); + window.dataKanal = data; + }, + ondata: function(data) { + Janus.debug("We got data from the DataChannel!", data); + console.log('DUBU DATA', data); + obdelajData(data); + }, + oncleanup: function() { + Janus.log(" ::: Got a cleanup notification :::"); + for(var i in bitrateTimer) + clearInterval(bitrateTimer[i]); + bitrateTimer = {}; + remoteTracks = {}; + dataMid = null; + } + }); + }, + error: function(error) { + Janus.error(error); + }, + destroyed: function() { + window.location.reload(); + } + }); +}}); +}); + +function updateStreamsList() { + var body = { request: "list" }; + Janus.debug("Sending message:", body); + streaming.send({ message: body, success: function(result) { + if(!result) { + console.log("Error: Got no response to our query for available streams"); + return; + } + if(result["list"]) { + var list = result["list"]; + if(list && Array.isArray(list)) { + list.sort(function(a, b) { + if(!a || a.id < (b ? b.id : 0)) + return -1; + if(!b || b.id < (a ? a.id : 0)) + return 1; + return 0; + }); + } + Janus.log("Got a list of available streams:", list); + streamsList = {}; + for(var mp in list) { + Janus.debug(" >> [" + list[mp]["id"] + "] " + list[mp]["description"] + " (" + list[mp]["type"] + ")"); + // Check the nature of the available streams, and if there are some multistream ones + list[mp].legacy = true; + if(list[mp].media) { + var audios = 0, videos = 0; + for(var mi in list[mp].media) { + if(!list[mp].media[mi]) + continue; + if(list[mp].media[mi].type === "audio") + audios++; + else if(list[mp].media[mi].type === "video") + videos++; + if(audios > 1 || videos > 1) { + list[mp].legacy = false; + break; + } + } + } + // Keep track of all the available streams + streamsList[list[mp]["id"]] = list[mp]; + } + + // Dajmo kar zacet + startStream(); + } + }}); +} + +function getStreamInfo() { + // Send a request for more info on the mountpoint we subscribed to + var body = { request: "info", id: parseInt(selectedStream) || selectedStream }; + streaming.send({ message: body, success: function(result) { + if(result && result.info && result.info.metadata) { + console.log('STREAM META', result.info.metadata); + } + }}); +} + +function startStream() { + Janus.log("Selected video id #" + selectedStream); + console.log('zacenjam', selectedStream, streamsList[selectedStream]); + if(!selectedStream || !streamsList[selectedStream]) { + console.log("Error: No stream selected to start"); + return; + } + + if(streamsList[selectedStream].legacy) { + for(mi in streamsList[selectedStream].media) { + // Add a new panel + var type = streamsList[selectedStream].media[mi].type; + if(type === "video") { + mid = streamsList[selectedStream].media[mi].mid; + break; + } + } + } + // Prepare the request to start streaming and send it + var body = { request: "watch", id: parseInt(selectedStream) || selectedStream }; + streaming.send({ message: body }); + getStreamInfo(); +} + +function stopStream() { + streaming.send({ message: body }); + streaming.hangup(); +} + +function obdelajData(data) { + console.log('obdelam webrtc podatke', data); +} diff --git a/www/stil.css b/www/stil.css index 898ad12..6c83ca7 100644 --- a/www/stil.css +++ b/www/stil.css @@ -37,7 +37,7 @@ h2 { height: auto; } -video { +#videofeed { width: 100%; height: auto; box-sizing: border-box;