From 193409787570c030a5cb57eddf831722faa4fe34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 8 Feb 2021 15:40:48 +0100 Subject: [PATCH 1/9] JS syntax highlighting - add syntax highlighting in IFRAME.md - update syntax to ES6 --- IFRAME.md | 314 +++++++++++++++++++++++++++--------------------------- 1 file changed, 157 insertions(+), 157 deletions(-) diff --git a/IFRAME.md b/IFRAME.md index 0b93c64..565e629 100644 --- a/IFRAME.md +++ b/IFRAME.md @@ -9,12 +9,12 @@ The solution decided on isn't an SDK framework, but rather the use of embeddable Modern web browsers allow the parent website to communicate with the child webpage, giving a high-level of control to a developer, while also abstracting the complex code and hosting requirements. Functionality, we can make an OBSN video stream act much like an HTML video element tag, where you can issue commands like play, pause, or change video sources with ease. Creating an OBSN iframe can be done in HTML or programmatically with Javascript like so: - - var iframe = document.createElement("iframe"); +```js + const iframe = document.createElement("iframe"); iframe.allow="autoplay;camera;microphone"; iframe.allowtransparency="false" iframe.src = "https://obs.ninja/?webcam"; - +``` Adding that iframe to the DOM will reveal a simple page accessing for a user to select and share their webcam. For a developer wishing to access a remote guest's stream, this makes the ingestion of that stream into production software like OBS Studios very easy. The level of customization and control opens up opportunities, such as a pay-to-join audience option for a streaming interactive broadcast experience. An example of how this API is used by OBS.Ninja is with its Internet Speedtest, which has two OBS.Ninja IFrames on a single page. One iframe feeds video to the other iframe, and the speed at which it does this is a measure of the system's performance. Detailed stats of the connection are made available to the parent window, which displays the results. @@ -52,161 +52,161 @@ As for API, allow for dynamic messaging, below are examples of the options avail - Get notified when there is a video connection As for the actually details for methods and options available to dynamically control child OBSN iframe, they are primarily kept up to via the iframe.html file that is mentioned previously. see: *iframe.html*. Below is a snippet from that file: - - var button = document.createElement("button"); - button.innerHTML = "Mute Speaker"; - button.onclick = function(){iframe.contentWindow.postMessage({"mute":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Un-Mute Speaker"; - button.onclick = function(){iframe.contentWindow.postMessage({"mute":false}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Toggle Speaker"; - button.onclick = function(){iframe.contentWindow.postMessage({"mute":"toggle"}, '*');} - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Mute Mic"; - button.onclick = function(){iframe.contentWindow.postMessage({"mic":false}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Un-Mute Mic"; - button.onclick = function(){iframe.contentWindow.postMessage({"mic":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Toggle Mic"; - button.onclick = function(){iframe.contentWindow.postMessage({"mic":"toggle"}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Disconnect"; - button.onclick = function(){iframe.contentWindow.postMessage({"close":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Low Bitrate"; - button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":30}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "High Bitrate"; - button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":5000}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Default Bitrate"; - button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":-1}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Reload"; - button.onclick = function(){iframe.contentWindow.postMessage({"reload":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "50% Volume"; - button.onclick = function(){iframe.contentWindow.postMessage({"volume":0.5}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "100% Volume"; - button.onclick = function(){iframe.contentWindow.postMessage({"volume":1.0}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Request Stats"; - button.onclick = function(){iframe.contentWindow.postMessage({"getStats":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Request Loudness Levels"; - button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":true}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Stop Sending Loudness Levels"; - button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":false}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "Say Hello"; - button.onclick = function(){iframe.contentWindow.postMessage({"sendChat":"Hello!"}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "previewWebcam()"; - button.onclick = function(){iframe.contentWindow.postMessage({"function":"previewWebcam"}, '*');}; - iframeContainer.appendChild(button); - - var button = document.createElement("button"); - button.innerHTML = "CLOSE IFRAME"; - button.onclick = function(){iframeContainer.parentNode.removeChild(iframeContainer);}; - iframeContainer.appendChild(button); - +```js +var button = document.createElement("button"); +button.innerHTML = "Mute Speaker"; +button.onclick = function(){iframe.contentWindow.postMessage({"mute":true}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "Un-Mute Speaker"; +button.onclick = function(){iframe.contentWindow.postMessage({"mute":false}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "Toggle Speaker"; +button.onclick = function(){iframe.contentWindow.postMessage({"mute":"toggle"}, '*');} +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "Mute Mic"; +button.onclick = function(){iframe.contentWindow.postMessage({"mic":false}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "Un-Mute Mic"; +button.onclick = function(){iframe.contentWindow.postMessage({"mic":true}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "Toggle Mic"; +button.onclick = function(){iframe.contentWindow.postMessage({"mic":"toggle"}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "Disconnect"; +button.onclick = function(){iframe.contentWindow.postMessage({"close":true}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "Low Bitrate"; +button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":30}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "High Bitrate"; +button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":5000}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "Default Bitrate"; +button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":-1}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "Reload"; +button.onclick = function(){iframe.contentWindow.postMessage({"reload":true}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "50% Volume"; +button.onclick = function(){iframe.contentWindow.postMessage({"volume":0.5}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "100% Volume"; +button.onclick = function(){iframe.contentWindow.postMessage({"volume":1.0}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "Request Stats"; +button.onclick = function(){iframe.contentWindow.postMessage({"getStats":true}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "Request Loudness Levels"; +button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":true}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "Stop Sending Loudness Levels"; +button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":false}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "Say Hello"; +button.onclick = function(){iframe.contentWindow.postMessage({"sendChat":"Hello!"}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "previewWebcam()"; +button.onclick = function(){iframe.contentWindow.postMessage({"function":"previewWebcam"}, '*');}; +iframeContainer.appendChild(button); + +var button = document.createElement("button"); +button.innerHTML = "CLOSE IFRAME"; +button.onclick = function(){iframeContainer.parentNode.removeChild(iframeContainer);}; +iframeContainer.appendChild(button); + As for listening events, where the parent listens for responses or events from the OBSN child frame: - - //////////// LISTEN FOR EVENTS - - var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; - var eventer = window[eventMethod]; - var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message"; - - eventer(messageEvent, function (e) { - if (e.source != iframe.contentWindow){return} // reject messages send from other iframes - - if ("stats" in e.data){ - var outputWindow = document.createElement("div"); - - var out = "
total_inbound_connections:"+e.data.stats.total_inbound_connections; - out += "
total_outbound_connections:"+e.data.stats.total_outbound_connections; - - for (var streamID in e.data.stats.inbound_stats){ - out += "

streamID: "+streamID+"
"; - out += printValues(e.data.stats.inbound_stats[streamID]); - } - - outputWindow.innerHTML = out; - iframeContainer.appendChild(outputWindow); - } - - if ("gotChat" in e.data){ - var outputWindow = document.createElement("div"); - outputWindow.innerHTML = e.data.gotChat.msg; - outputWindow.style.border="1px dotted black"; - iframeContainer.appendChild(outputWindow); - } - - if ("action" in e.data){ - var outputWindow = document.createElement("div"); - outputWindow.innerHTML = "child-page-action: "+e.data.action+"
"; - outputWindow.style.border="1px dotted black"; - iframeContainer.appendChild(outputWindow); - } - - if ("loudness" in e.data){ - console.log(e.data); - if (document.getElementById("loudness")){ - outputWindow = document.getElementById("loudness"); - } else { - var outputWindow = document.createElement("div"); - outputWindow.style.border="1px dotted black"; - iframeContainer.appendChild(outputWindow); - outputWindow.id = "loudness"; - } - outputWindow.innerHTML = "child-page-action: loudness
"; - for (var key in e.data.loudness) { - outputWindow.innerHTML += key + " Loudness: " + e.data.loudness[key] + "\n"; - } - outputWindow.style.border="1px black"; - - } - }); - + +//////////// LISTEN FOR EVENTS + +var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; +var eventer = window[eventMethod]; +var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message"; + +eventer(messageEvent, function (e) { + if (e.source != iframe.contentWindow){return} // reject messages send from other iframes + + if ("stats" in e.data){ + var outputWindow = document.createElement("div"); + + var out = "
total_inbound_connections:"+e.data.stats.total_inbound_connections; + out += "
total_outbound_connections:"+e.data.stats.total_outbound_connections; + + for (var streamID in e.data.stats.inbound_stats){ + out += "

streamID: "+streamID+"
"; + out += printValues(e.data.stats.inbound_stats[streamID]); + } + + outputWindow.innerHTML = out; + iframeContainer.appendChild(outputWindow); + } + + if ("gotChat" in e.data){ + var outputWindow = document.createElement("div"); + outputWindow.innerHTML = e.data.gotChat.msg; + outputWindow.style.border="1px dotted black"; + iframeContainer.appendChild(outputWindow); + } + + if ("action" in e.data){ + var outputWindow = document.createElement("div"); + outputWindow.innerHTML = "child-page-action: "+e.data.action+"
"; + outputWindow.style.border="1px dotted black"; + iframeContainer.appendChild(outputWindow); + } + + if ("loudness" in e.data){ + console.log(e.data); + if (document.getElementById("loudness")){ + outputWindow = document.getElementById("loudness"); + } else { + var outputWindow = document.createElement("div"); + outputWindow.style.border="1px dotted black"; + iframeContainer.appendChild(outputWindow); + outputWindow.id = "loudness"; + } + outputWindow.innerHTML = "child-page-action: loudness
"; + for (var key in e.data.loudness) { + outputWindow.innerHTML += key + " Loudness: " + e.data.loudness[key] + "\n"; +} + outputWindow.style.border="1px black"; + + } +}); +``` This OBS.Ninja API is developed and expanded based on user feedback and requests. It is by no means complete. Regarding versioning, I currently host past versions of OBS.Ninja, so using those past versions can ensure some level of consistency and expectation. https://obs.ninja/v12/ for example is the version 12 hosted version. The active and main production version of OBSN of course undergoes constant updates, and while I try to maintain backwards compatibility with changes to the API, it is still early days and changes might happen. From 8ee5be2960f65af9e503b447082b9c141cb67a7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 8 Feb 2021 15:43:13 +0100 Subject: [PATCH 2/9] Var -> const --- IFRAME.md | 58 +++++++++++++++++++++++++++---------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/IFRAME.md b/IFRAME.md index 565e629..3dfe08d 100644 --- a/IFRAME.md +++ b/IFRAME.md @@ -53,97 +53,97 @@ As for API, allow for dynamic messaging, below are examples of the options avail As for the actually details for methods and options available to dynamically control child OBSN iframe, they are primarily kept up to via the iframe.html file that is mentioned previously. see: *iframe.html*. Below is a snippet from that file: ```js -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "Mute Speaker"; button.onclick = function(){iframe.contentWindow.postMessage({"mute":true}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "Un-Mute Speaker"; button.onclick = function(){iframe.contentWindow.postMessage({"mute":false}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "Toggle Speaker"; button.onclick = function(){iframe.contentWindow.postMessage({"mute":"toggle"}, '*');} iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "Mute Mic"; button.onclick = function(){iframe.contentWindow.postMessage({"mic":false}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "Un-Mute Mic"; button.onclick = function(){iframe.contentWindow.postMessage({"mic":true}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "Toggle Mic"; button.onclick = function(){iframe.contentWindow.postMessage({"mic":"toggle"}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "Disconnect"; button.onclick = function(){iframe.contentWindow.postMessage({"close":true}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "Low Bitrate"; button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":30}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "High Bitrate"; button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":5000}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "Default Bitrate"; button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":-1}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "Reload"; button.onclick = function(){iframe.contentWindow.postMessage({"reload":true}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "50% Volume"; button.onclick = function(){iframe.contentWindow.postMessage({"volume":0.5}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "100% Volume"; button.onclick = function(){iframe.contentWindow.postMessage({"volume":1.0}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "Request Stats"; button.onclick = function(){iframe.contentWindow.postMessage({"getStats":true}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "Request Loudness Levels"; button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":true}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "Stop Sending Loudness Levels"; button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":false}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "Say Hello"; button.onclick = function(){iframe.contentWindow.postMessage({"sendChat":"Hello!"}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "previewWebcam()"; button.onclick = function(){iframe.contentWindow.postMessage({"function":"previewWebcam"}, '*');}; iframeContainer.appendChild(button); -var button = document.createElement("button"); +const button = document.createElement("button"); button.innerHTML = "CLOSE IFRAME"; button.onclick = function(){iframeContainer.parentNode.removeChild(iframeContainer);}; iframeContainer.appendChild(button); @@ -152,20 +152,20 @@ As for listening events, where the parent listens for responses or events from t //////////// LISTEN FOR EVENTS -var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; -var eventer = window[eventMethod]; -var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message"; +const eventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; +const eventer = window[eventMethod]; +const messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message"; eventer(messageEvent, function (e) { if (e.source != iframe.contentWindow){return} // reject messages send from other iframes if ("stats" in e.data){ - var outputWindow = document.createElement("div"); + const outputWindow = document.createElement("div"); - var out = "
total_inbound_connections:"+e.data.stats.total_inbound_connections; + const out = "
total_inbound_connections:"+e.data.stats.total_inbound_connections; out += "
total_outbound_connections:"+e.data.stats.total_outbound_connections; - for (var streamID in e.data.stats.inbound_stats){ + for (const streamID in e.data.stats.inbound_stats){ out += "

streamID: "+streamID+"
"; out += printValues(e.data.stats.inbound_stats[streamID]); } @@ -175,14 +175,14 @@ eventer(messageEvent, function (e) { } if ("gotChat" in e.data){ - var outputWindow = document.createElement("div"); + const outputWindow = document.createElement("div"); outputWindow.innerHTML = e.data.gotChat.msg; outputWindow.style.border="1px dotted black"; iframeContainer.appendChild(outputWindow); } if ("action" in e.data){ - var outputWindow = document.createElement("div"); + const outputWindow = document.createElement("div"); outputWindow.innerHTML = "child-page-action: "+e.data.action+"
"; outputWindow.style.border="1px dotted black"; iframeContainer.appendChild(outputWindow); @@ -193,13 +193,13 @@ eventer(messageEvent, function (e) { if (document.getElementById("loudness")){ outputWindow = document.getElementById("loudness"); } else { - var outputWindow = document.createElement("div"); + const outputWindow = document.createElement("div"); outputWindow.style.border="1px dotted black"; iframeContainer.appendChild(outputWindow); outputWindow.id = "loudness"; } outputWindow.innerHTML = "child-page-action: loudness
"; - for (var key in e.data.loudness) { + for (const key in e.data.loudness) { outputWindow.innerHTML += key + " Loudness: " + e.data.loudness[key] + "\n"; } outputWindow.style.border="1px black"; From f0cfa1effd24390c8a143be20cdac89f0859149c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 8 Feb 2021 15:44:04 +0100 Subject: [PATCH 3/9] Format IFRAME.md --- IFRAME.md | 68 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 33 deletions(-) diff --git a/IFRAME.md b/IFRAME.md index 3dfe08d..49c8d4d 100644 --- a/IFRAME.md +++ b/IFRAME.md @@ -1,57 +1,59 @@ -## OBS.Ninja - iFrame API documentation +## OBS.Ninja - iFrame API documentation OBS.Ninja (OBSN) is offers here a simple and free solution to quickly enable real-time video streaming in their websites. OBSN wishes to make live video streaming development accessible to any developer, even novices, yet still remain flexible and powerful. While OBS.Ninja does offer source-code to customize the application and UI at a low level, this isn't for beginners and it is rather hard to maintain. As well, due to the complexity of video streaming in the web, typical approaches for offering API access isn't quite feasible either. -The solution decided on isn't an SDK framework, but rather the use of embeddable *IFrames* and a corresponding bi-directional iframe API. An [iframe](https://www.w3schools.com/tags/tag_iframe.ASP) allows us to embed a webpage inside a webpage, including OBS.Ninja into your own website. +The solution decided on isn't an SDK framework, but rather the use of embeddable _IFrames_ and a corresponding bi-directional iframe API. An [iframe](https://www.w3schools.com/tags/tag_iframe.ASP) allows us to embed a webpage inside a webpage, including OBS.Ninja into your own website. Modern web browsers allow the parent website to communicate with the child webpage, giving a high-level of control to a developer, while also abstracting the complex code and hosting requirements. Functionality, we can make an OBSN video stream act much like an HTML video element tag, where you can issue commands like play, pause, or change video sources with ease. Creating an OBSN iframe can be done in HTML or programmatically with Javascript like so: + ```js - const iframe = document.createElement("iframe"); - iframe.allow="autoplay;camera;microphone"; - iframe.allowtransparency="false" - iframe.src = "https://obs.ninja/?webcam"; +const iframe = document.createElement("iframe"); +iframe.allow = "autoplay;camera;microphone"; +iframe.allowtransparency = "false"; +iframe.src = "https://obs.ninja/?webcam"; ``` -Adding that iframe to the DOM will reveal a simple page accessing for a user to select and share their webcam. For a developer wishing to access a remote guest's stream, this makes the ingestion of that stream into production software like OBS Studios very easy. The level of customization and control opens up opportunities, such as a pay-to-join audience option for a streaming interactive broadcast experience. + +Adding that iframe to the DOM will reveal a simple page accessing for a user to select and share their webcam. For a developer wishing to access a remote guest's stream, this makes the ingestion of that stream into production software like OBS Studios very easy. The level of customization and control opens up opportunities, such as a pay-to-join audience option for a streaming interactive broadcast experience. An example of how this API is used by OBS.Ninja is with its Internet Speedtest, which has two OBS.Ninja IFrames on a single page. One iframe feeds video to the other iframe, and the speed at which it does this is a measure of the system's performance. Detailed stats of the connection are made available to the parent window, which displays the results. https://obs.ninja/speedtest More community-contributed IFRAME examples can be found here: https://github.com/steveseguin/obsninja/tree/master/examples -A sandbox of options is available at this page, too: https://obs.ninja/iframe You can enter an OBS.Ninja URL in the input box to start using it. For developers, viewing the source of that page will reveal examples of how all the available functions work, along with a way to test and play with each of them. You can also see here for the source-code on GitHub: https://github.com/steveseguin/obsninja/blob/master/iframe.html +A sandbox of options is available at this page, too: https://obs.ninja/iframe You can enter an OBS.Ninja URL in the input box to start using it. For developers, viewing the source of that page will reveal examples of how all the available functions work, along with a way to test and play with each of them. You can also see here for the source-code on GitHub: https://github.com/steveseguin/obsninja/blob/master/iframe.html -One thing to note about this iframe API is that it is a mix of URL parameters given to the iframe *src* URL, but also the postMessage and addEventListener methods of the browser. The later is used to dynamically control OBS.Ninja, while the former is used to initiate the instance to a desired state. +One thing to note about this iframe API is that it is a mix of URL parameters given to the iframe _src_ URL, but also the postMessage and addEventListener methods of the browser. The later is used to dynamically control OBS.Ninja, while the former is used to initiate the instance to a desired state. For more information on the URL parameters thare are available, please see: https://github.com/steveseguin/obsninja/wiki/Advanced-Settings Some of the more interesting ones primarily for iframe users might include: - - &webcam - - &screenshare - - &videodevice=1 or 0 - - &audiodevice=1 or 0 - - &autostart - - &chroma - - &transparency - - -As for API, allow for dynamic messaging, below are examples of the options available: +- &webcam +- &screenshare +- &videodevice=1 or 0 +- &audiodevice=1 or 0 +- &autostart +- &chroma +- &transparency +- As for API, allow for dynamic messaging, below are examples of the options available: - - Mute Speaker - - Mute Mic - - Disconnect - - Change Video Bitrate - - Reload the page - - Change the volume - - Request detailed connection stats - - Access the loudness level of the audio - - Send/Recieve a chat message to other connected guests - - Get notified when there is a video connection +- Mute Speaker +- Mute Mic +- Disconnect +- Change Video Bitrate +- Reload the page +- Change the volume +- Request detailed connection stats +- Access the loudness level of the audio +- Send/Recieve a chat message to other connected guests +- Get notified when there is a video connection + +As for the actually details for methods and options available to dynamically control child OBSN iframe, they are primarily kept up to via the iframe.html file that is mentioned previously. see: _iframe.html_. Below is a snippet from that file: -As for the actually details for methods and options available to dynamically control child OBSN iframe, they are primarily kept up to via the iframe.html file that is mentioned previously. see: *iframe.html*. Below is a snippet from that file: ```js const button = document.createElement("button"); button.innerHTML = "Mute Speaker"; @@ -140,7 +142,7 @@ iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "previewWebcam()"; -button.onclick = function(){iframe.contentWindow.postMessage({"function":"previewWebcam"}, '*');}; +button.onclick = function(){iframe.contentWindow.postMessage({"function":"previewWebcam"}, '*');}; iframeContainer.appendChild(button); const button = document.createElement("button"); @@ -148,7 +150,7 @@ button.innerHTML = "CLOSE IFRAME"; button.onclick = function(){iframeContainer.parentNode.removeChild(iframeContainer);}; iframeContainer.appendChild(button); -As for listening events, where the parent listens for responses or events from the OBSN child frame: +As for listening events, where the parent listens for responses or events from the OBSN child frame: //////////// LISTEN FOR EVENTS @@ -200,18 +202,18 @@ eventer(messageEvent, function (e) { } outputWindow.innerHTML = "child-page-action: loudness
"; for (const key in e.data.loudness) { - outputWindow.innerHTML += key + " Loudness: " + e.data.loudness[key] + "\n"; + outputWindow.innerHTML += key + " Loudness: " + e.data.loudness[key] + "\n"; } outputWindow.style.border="1px black"; } }); ``` + This OBS.Ninja API is developed and expanded based on user feedback and requests. It is by no means complete. Regarding versioning, I currently host past versions of OBS.Ninja, so using those past versions can ensure some level of consistency and expectation. https://obs.ninja/v12/ for example is the version 12 hosted version. The active and main production version of OBSN of course undergoes constant updates, and while I try to maintain backwards compatibility with changes to the API, it is still early days and changes might happen. Please feel free to follow me in the OBS.Ninja Discord channel, where I post news about updates and listen to requests. The upcoming version of OBS.Ninja is also often hosted at https://obs.ninja/beta, where you can explore new features and help crush any unexpected bugs. - -steve From e762910907e152d43ae44c7d5dc6a8241b5ae288 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 8 Feb 2021 15:44:40 +0100 Subject: [PATCH 4/9] Eqeqeq --- IFRAME.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IFRAME.md b/IFRAME.md index 49c8d4d..9c3d618 100644 --- a/IFRAME.md +++ b/IFRAME.md @@ -159,7 +159,7 @@ const eventer = window[eventMethod]; const messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message"; eventer(messageEvent, function (e) { - if (e.source != iframe.contentWindow){return} // reject messages send from other iframes + if (e.source !== iframe.contentWindow){return} // reject messages send from other iframes if ("stats" in e.data){ const outputWindow = document.createElement("div"); From c487bed90631e9e1887a629b0001e85fb950fb17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 8 Feb 2021 15:45:46 +0100 Subject: [PATCH 5/9] Invalid assignment to const --- IFRAME.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/IFRAME.md b/IFRAME.md index 9c3d618..c6f9efb 100644 --- a/IFRAME.md +++ b/IFRAME.md @@ -164,7 +164,7 @@ eventer(messageEvent, function (e) { if ("stats" in e.data){ const outputWindow = document.createElement("div"); - const out = "
total_inbound_connections:"+e.data.stats.total_inbound_connections; + let out = "
total_inbound_connections:"+e.data.stats.total_inbound_connections; out += "
total_outbound_connections:"+e.data.stats.total_outbound_connections; for (const streamID in e.data.stats.inbound_stats){ From 8c4c1cd040c4d8993c7347eb3df976cfd2f74274 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 8 Feb 2021 15:52:15 +0100 Subject: [PATCH 6/9] Arrow functions as onclick handlers --- IFRAME.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/IFRAME.md b/IFRAME.md index c6f9efb..3eed646 100644 --- a/IFRAME.md +++ b/IFRAME.md @@ -57,97 +57,97 @@ As for the actually details for methods and options available to dynamically con ```js const button = document.createElement("button"); button.innerHTML = "Mute Speaker"; -button.onclick = function(){iframe.contentWindow.postMessage({"mute":true}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "mute": true }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "Un-Mute Speaker"; -button.onclick = function(){iframe.contentWindow.postMessage({"mute":false}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "mute": false }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "Toggle Speaker"; -button.onclick = function(){iframe.contentWindow.postMessage({"mute":"toggle"}, '*');} +button.onclick = () => { iframe.contentWindow.postMessage({ "mute": "toggle" }, '*'); } iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "Mute Mic"; -button.onclick = function(){iframe.contentWindow.postMessage({"mic":false}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "mic": false }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "Un-Mute Mic"; -button.onclick = function(){iframe.contentWindow.postMessage({"mic":true}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "mic": true }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "Toggle Mic"; -button.onclick = function(){iframe.contentWindow.postMessage({"mic":"toggle"}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "mic": "toggle" }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "Disconnect"; -button.onclick = function(){iframe.contentWindow.postMessage({"close":true}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "close": true }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "Low Bitrate"; -button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":30}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "bitrate": 30 }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "High Bitrate"; -button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":5000}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "bitrate": 5000 }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "Default Bitrate"; -button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":-1}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "bitrate": -1 }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "Reload"; -button.onclick = function(){iframe.contentWindow.postMessage({"reload":true}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "reload": true }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "50% Volume"; -button.onclick = function(){iframe.contentWindow.postMessage({"volume":0.5}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "volume": 0.5 }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "100% Volume"; -button.onclick = function(){iframe.contentWindow.postMessage({"volume":1.0}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "volume": 1.0 }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "Request Stats"; -button.onclick = function(){iframe.contentWindow.postMessage({"getStats":true}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "getStats": true }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "Request Loudness Levels"; -button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":true}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "getLoudness": true }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "Stop Sending Loudness Levels"; -button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":false}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "getLoudness": false }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "Say Hello"; -button.onclick = function(){iframe.contentWindow.postMessage({"sendChat":"Hello!"}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "sendChat": "Hello!" }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "previewWebcam()"; -button.onclick = function(){iframe.contentWindow.postMessage({"function":"previewWebcam"}, '*');}; +button.onclick = () => { iframe.contentWindow.postMessage({ "function": "previewWebcam" }, '*'); }; iframeContainer.appendChild(button); const button = document.createElement("button"); button.innerHTML = "CLOSE IFRAME"; -button.onclick = function(){iframeContainer.parentNode.removeChild(iframeContainer);}; +button.onclick = () => { iframeContainer.parentNode.removeChild(iframeContainer); }; iframeContainer.appendChild(button); As for listening events, where the parent listens for responses or events from the OBSN child frame: From c7a801c0e074fdcda7ff049584a5d0d65e5f1e2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 8 Feb 2021 15:52:27 +0100 Subject: [PATCH 7/9] Template strings --- IFRAME.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/IFRAME.md b/IFRAME.md index 3eed646..5da537d 100644 --- a/IFRAME.md +++ b/IFRAME.md @@ -164,11 +164,11 @@ eventer(messageEvent, function (e) { if ("stats" in e.data){ const outputWindow = document.createElement("div"); - let out = "
total_inbound_connections:"+e.data.stats.total_inbound_connections; - out += "
total_outbound_connections:"+e.data.stats.total_outbound_connections; + let out = `
total_inbound_connections:${e.data.stats.total_inbound_connections}`; + out += `
total_outbound_connections:${e.data.stats.total_outbound_connections}`; for (const streamID in e.data.stats.inbound_stats){ - out += "

streamID: "+streamID+"
"; + out += `

streamID: ${streamID}
`; out += printValues(e.data.stats.inbound_stats[streamID]); } @@ -185,7 +185,7 @@ eventer(messageEvent, function (e) { if ("action" in e.data){ const outputWindow = document.createElement("div"); - outputWindow.innerHTML = "child-page-action: "+e.data.action+"
"; + outputWindow.innerHTML = `child-page-action: ${e.data.action}
`; outputWindow.style.border="1px dotted black"; iframeContainer.appendChild(outputWindow); } @@ -202,7 +202,7 @@ eventer(messageEvent, function (e) { } outputWindow.innerHTML = "child-page-action: loudness
"; for (const key in e.data.loudness) { - outputWindow.innerHTML += key + " Loudness: " + e.data.loudness[key] + "\n"; + outputWindow.innerHTML += `${key} Loudness: ${e.data.loudness[key]}\n`; } outputWindow.style.border="1px black"; From 1c3d45ae6ffa173946d91ceaed733b9caf5f20cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 8 Feb 2021 15:55:26 +0100 Subject: [PATCH 8/9] Const -> let because of re-declaration issues --- IFRAME.md | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/IFRAME.md b/IFRAME.md index 5da537d..32fc099 100644 --- a/IFRAME.md +++ b/IFRAME.md @@ -55,97 +55,97 @@ Some of the more interesting ones primarily for iframe users might include: As for the actually details for methods and options available to dynamically control child OBSN iframe, they are primarily kept up to via the iframe.html file that is mentioned previously. see: _iframe.html_. Below is a snippet from that file: ```js -const button = document.createElement("button"); +let button = document.createElement("button"); button.innerHTML = "Mute Speaker"; button.onclick = () => { iframe.contentWindow.postMessage({ "mute": true }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "Un-Mute Speaker"; button.onclick = () => { iframe.contentWindow.postMessage({ "mute": false }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "Toggle Speaker"; button.onclick = () => { iframe.contentWindow.postMessage({ "mute": "toggle" }, '*'); } iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "Mute Mic"; button.onclick = () => { iframe.contentWindow.postMessage({ "mic": false }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "Un-Mute Mic"; button.onclick = () => { iframe.contentWindow.postMessage({ "mic": true }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "Toggle Mic"; button.onclick = () => { iframe.contentWindow.postMessage({ "mic": "toggle" }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "Disconnect"; button.onclick = () => { iframe.contentWindow.postMessage({ "close": true }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "Low Bitrate"; button.onclick = () => { iframe.contentWindow.postMessage({ "bitrate": 30 }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "High Bitrate"; button.onclick = () => { iframe.contentWindow.postMessage({ "bitrate": 5000 }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "Default Bitrate"; button.onclick = () => { iframe.contentWindow.postMessage({ "bitrate": -1 }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "Reload"; button.onclick = () => { iframe.contentWindow.postMessage({ "reload": true }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "50% Volume"; button.onclick = () => { iframe.contentWindow.postMessage({ "volume": 0.5 }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "100% Volume"; button.onclick = () => { iframe.contentWindow.postMessage({ "volume": 1.0 }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "Request Stats"; button.onclick = () => { iframe.contentWindow.postMessage({ "getStats": true }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "Request Loudness Levels"; button.onclick = () => { iframe.contentWindow.postMessage({ "getLoudness": true }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "Stop Sending Loudness Levels"; button.onclick = () => { iframe.contentWindow.postMessage({ "getLoudness": false }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "Say Hello"; button.onclick = () => { iframe.contentWindow.postMessage({ "sendChat": "Hello!" }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "previewWebcam()"; button.onclick = () => { iframe.contentWindow.postMessage({ "function": "previewWebcam" }, '*'); }; iframeContainer.appendChild(button); -const button = document.createElement("button"); +button = document.createElement("button"); button.innerHTML = "CLOSE IFRAME"; button.onclick = () => { iframeContainer.parentNode.removeChild(iframeContainer); }; iframeContainer.appendChild(button); From 4e273219f87ca2148d0a485eb5e3ec2228a5074e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Tron=C3=AD=C4=8Dek?= Date: Mon, 8 Feb 2021 15:57:02 +0100 Subject: [PATCH 9/9] Format the JS and comment a plaintext comment --- IFRAME.md | 206 ++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 145 insertions(+), 61 deletions(-) diff --git a/IFRAME.md b/IFRAME.md index 32fc099..ce8b529 100644 --- a/IFRAME.md +++ b/IFRAME.md @@ -57,156 +57,240 @@ As for the actually details for methods and options available to dynamically con ```js let button = document.createElement("button"); button.innerHTML = "Mute Speaker"; -button.onclick = () => { iframe.contentWindow.postMessage({ "mute": true }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "mute": true + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "Un-Mute Speaker"; -button.onclick = () => { iframe.contentWindow.postMessage({ "mute": false }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "mute": false + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "Toggle Speaker"; -button.onclick = () => { iframe.contentWindow.postMessage({ "mute": "toggle" }, '*'); } +button.onclick = () => { + iframe.contentWindow.postMessage({ + "mute": "toggle" + }, '*'); +} iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "Mute Mic"; -button.onclick = () => { iframe.contentWindow.postMessage({ "mic": false }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "mic": false + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "Un-Mute Mic"; -button.onclick = () => { iframe.contentWindow.postMessage({ "mic": true }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "mic": true + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "Toggle Mic"; -button.onclick = () => { iframe.contentWindow.postMessage({ "mic": "toggle" }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "mic": "toggle" + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "Disconnect"; -button.onclick = () => { iframe.contentWindow.postMessage({ "close": true }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "close": true + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "Low Bitrate"; -button.onclick = () => { iframe.contentWindow.postMessage({ "bitrate": 30 }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "bitrate": 30 + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "High Bitrate"; -button.onclick = () => { iframe.contentWindow.postMessage({ "bitrate": 5000 }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "bitrate": 5000 + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "Default Bitrate"; -button.onclick = () => { iframe.contentWindow.postMessage({ "bitrate": -1 }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "bitrate": -1 + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "Reload"; -button.onclick = () => { iframe.contentWindow.postMessage({ "reload": true }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "reload": true + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "50% Volume"; -button.onclick = () => { iframe.contentWindow.postMessage({ "volume": 0.5 }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "volume": 0.5 + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "100% Volume"; -button.onclick = () => { iframe.contentWindow.postMessage({ "volume": 1.0 }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "volume": 1.0 + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "Request Stats"; -button.onclick = () => { iframe.contentWindow.postMessage({ "getStats": true }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "getStats": true + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "Request Loudness Levels"; -button.onclick = () => { iframe.contentWindow.postMessage({ "getLoudness": true }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "getLoudness": true + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "Stop Sending Loudness Levels"; -button.onclick = () => { iframe.contentWindow.postMessage({ "getLoudness": false }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "getLoudness": false + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "Say Hello"; -button.onclick = () => { iframe.contentWindow.postMessage({ "sendChat": "Hello!" }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "sendChat": "Hello!" + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "previewWebcam()"; -button.onclick = () => { iframe.contentWindow.postMessage({ "function": "previewWebcam" }, '*'); }; +button.onclick = () => { + iframe.contentWindow.postMessage({ + "function": "previewWebcam" + }, '*'); +}; iframeContainer.appendChild(button); button = document.createElement("button"); button.innerHTML = "CLOSE IFRAME"; -button.onclick = () => { iframeContainer.parentNode.removeChild(iframeContainer); }; +button.onclick = () => { + iframeContainer.parentNode.removeChild(iframeContainer); +}; iframeContainer.appendChild(button); -As for listening events, where the parent listens for responses or events from the OBSN child frame: +// As for listening events, where the parent listens for responses or events from the OBSN child frame: -//////////// LISTEN FOR EVENTS +// ////////// LISTEN FOR EVENTS const eventMethod = window.addEventListener ? "addEventListener" : "attachEvent"; const eventer = window[eventMethod]; const messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message"; eventer(messageEvent, function (e) { - if (e.source !== iframe.contentWindow){return} // reject messages send from other iframes + if (e.source !== iframe.contentWindow) { + return + } // reject messages send from other iframes - if ("stats" in e.data){ - const outputWindow = document.createElement("div"); + if ("stats" in e.data) { + const outputWindow = document.createElement("div"); - let out = `
total_inbound_connections:${e.data.stats.total_inbound_connections}`; - out += `
total_outbound_connections:${e.data.stats.total_outbound_connections}`; + let out = `
total_inbound_connections:${ + e.data.stats.total_inbound_connections + }`; + out += `
total_outbound_connections:${ + e.data.stats.total_outbound_connections + }`; - for (const streamID in e.data.stats.inbound_stats){ - out += `

streamID: ${streamID}
`; - out += printValues(e.data.stats.inbound_stats[streamID]); - } + for (const streamID in e.data.stats.inbound_stats) { + out += `

streamID: ${streamID}
`; + out += printValues(e.data.stats.inbound_stats[streamID]); + } - outputWindow.innerHTML = out; - iframeContainer.appendChild(outputWindow); - } + outputWindow.innerHTML = out; + iframeContainer.appendChild(outputWindow); + } - if ("gotChat" in e.data){ - const outputWindow = document.createElement("div"); - outputWindow.innerHTML = e.data.gotChat.msg; - outputWindow.style.border="1px dotted black"; - iframeContainer.appendChild(outputWindow); - } + if ("gotChat" in e.data) { + const outputWindow = document.createElement("div"); + outputWindow.innerHTML = e.data.gotChat.msg; + outputWindow.style.border = "1px dotted black"; + iframeContainer.appendChild(outputWindow); + } - if ("action" in e.data){ - const outputWindow = document.createElement("div"); - outputWindow.innerHTML = `child-page-action: ${e.data.action}
`; - outputWindow.style.border="1px dotted black"; - iframeContainer.appendChild(outputWindow); - } + if ("action" in e.data) { + const outputWindow = document.createElement("div"); + outputWindow.innerHTML = `child-page-action: ${ + e.data.action + }
`; + outputWindow.style.border = "1px dotted black"; + iframeContainer.appendChild(outputWindow); + } - if ("loudness" in e.data){ - console.log(e.data); - if (document.getElementById("loudness")){ - outputWindow = document.getElementById("loudness"); - } else { - const outputWindow = document.createElement("div"); - outputWindow.style.border="1px dotted black"; - iframeContainer.appendChild(outputWindow); - outputWindow.id = "loudness"; - } - outputWindow.innerHTML = "child-page-action: loudness
"; - for (const key in e.data.loudness) { - outputWindow.innerHTML += `${key} Loudness: ${e.data.loudness[key]}\n`; -} - outputWindow.style.border="1px black"; + if ("loudness" in e.data) { + console.log(e.data); + if (document.getElementById("loudness")) { + outputWindow = document.getElementById("loudness"); + } else { + const outputWindow = document.createElement("div"); + outputWindow.style.border = "1px dotted black"; + iframeContainer.appendChild(outputWindow); + outputWindow.id = "loudness"; + } + outputWindow.innerHTML = "child-page-action: loudness
"; + for (const key in e.data.loudness) { + outputWindow.innerHTML += `${key} Loudness: ${ + e.data.loudness[key] + }\n`; + } + outputWindow.style.border = "1px black"; - } + } }); ```