mirror of
https://github.com/eliasstepanik/vdo.ninja.git
synced 2026-01-25 20:38:28 +00:00
JS syntax highlighting
- add syntax highlighting in IFRAME.md - update syntax to ES6
This commit is contained in:
parent
5c7648d86a
commit
1934097875
314
IFRAME.md
314
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.
|
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:
|
Creating an OBSN iframe can be done in HTML or programmatically with Javascript like so:
|
||||||
|
```js
|
||||||
var iframe = document.createElement("iframe");
|
const iframe = document.createElement("iframe");
|
||||||
iframe.allow="autoplay;camera;microphone";
|
iframe.allow="autoplay;camera;microphone";
|
||||||
iframe.allowtransparency="false"
|
iframe.allowtransparency="false"
|
||||||
iframe.src = "https://obs.ninja/?webcam";
|
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.
|
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
|
- 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
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "Mute Speaker";
|
button.innerHTML = "Mute Speaker";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"mute":true}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"mute":true}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "Un-Mute Speaker";
|
button.innerHTML = "Un-Mute Speaker";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"mute":false}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"mute":false}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "Toggle Speaker";
|
button.innerHTML = "Toggle Speaker";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"mute":"toggle"}, '*');}
|
button.onclick = function(){iframe.contentWindow.postMessage({"mute":"toggle"}, '*');}
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "Mute Mic";
|
button.innerHTML = "Mute Mic";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"mic":false}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"mic":false}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "Un-Mute Mic";
|
button.innerHTML = "Un-Mute Mic";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"mic":true}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"mic":true}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "Toggle Mic";
|
button.innerHTML = "Toggle Mic";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"mic":"toggle"}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"mic":"toggle"}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "Disconnect";
|
button.innerHTML = "Disconnect";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"close":true}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"close":true}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "Low Bitrate";
|
button.innerHTML = "Low Bitrate";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":30}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":30}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "High Bitrate";
|
button.innerHTML = "High Bitrate";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":5000}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":5000}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "Default Bitrate";
|
button.innerHTML = "Default Bitrate";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":-1}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"bitrate":-1}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "Reload";
|
button.innerHTML = "Reload";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"reload":true}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"reload":true}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "50% Volume";
|
button.innerHTML = "50% Volume";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"volume":0.5}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"volume":0.5}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "100% Volume";
|
button.innerHTML = "100% Volume";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"volume":1.0}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"volume":1.0}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "Request Stats";
|
button.innerHTML = "Request Stats";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"getStats":true}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"getStats":true}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "Request Loudness Levels";
|
button.innerHTML = "Request Loudness Levels";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":true}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":true}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "Stop Sending Loudness Levels";
|
button.innerHTML = "Stop Sending Loudness Levels";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":false}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"getLoudness":false}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "Say Hello";
|
button.innerHTML = "Say Hello";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"sendChat":"Hello!"}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"sendChat":"Hello!"}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "previewWebcam()";
|
button.innerHTML = "previewWebcam()";
|
||||||
button.onclick = function(){iframe.contentWindow.postMessage({"function":"previewWebcam"}, '*');};
|
button.onclick = function(){iframe.contentWindow.postMessage({"function":"previewWebcam"}, '*');};
|
||||||
iframeContainer.appendChild(button);
|
iframeContainer.appendChild(button);
|
||||||
|
|
||||||
var button = document.createElement("button");
|
var button = document.createElement("button");
|
||||||
button.innerHTML = "CLOSE IFRAME";
|
button.innerHTML = "CLOSE IFRAME";
|
||||||
button.onclick = function(){iframeContainer.parentNode.removeChild(iframeContainer);};
|
button.onclick = function(){iframeContainer.parentNode.removeChild(iframeContainer);};
|
||||||
iframeContainer.appendChild(button);
|
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
|
||||||
|
|
||||||
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
|
var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
|
||||||
var eventer = window[eventMethod];
|
var eventer = window[eventMethod];
|
||||||
var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message";
|
var messageEvent = eventMethod === "attachEvent" ? "onmessage" : "message";
|
||||||
|
|
||||||
eventer(messageEvent, function (e) {
|
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){
|
if ("stats" in e.data){
|
||||||
var outputWindow = document.createElement("div");
|
var outputWindow = document.createElement("div");
|
||||||
|
|
||||||
var out = "<br />total_inbound_connections:"+e.data.stats.total_inbound_connections;
|
var out = "<br />total_inbound_connections:"+e.data.stats.total_inbound_connections;
|
||||||
out += "<br />total_outbound_connections:"+e.data.stats.total_outbound_connections;
|
out += "<br />total_outbound_connections:"+e.data.stats.total_outbound_connections;
|
||||||
|
|
||||||
for (var streamID in e.data.stats.inbound_stats){
|
for (var streamID in e.data.stats.inbound_stats){
|
||||||
out += "<br /><br /><b>streamID:</b> "+streamID+"<br />";
|
out += "<br /><br /><b>streamID:</b> "+streamID+"<br />";
|
||||||
out += printValues(e.data.stats.inbound_stats[streamID]);
|
out += printValues(e.data.stats.inbound_stats[streamID]);
|
||||||
}
|
}
|
||||||
|
|
||||||
outputWindow.innerHTML = out;
|
outputWindow.innerHTML = out;
|
||||||
iframeContainer.appendChild(outputWindow);
|
iframeContainer.appendChild(outputWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("gotChat" in e.data){
|
if ("gotChat" in e.data){
|
||||||
var outputWindow = document.createElement("div");
|
var outputWindow = document.createElement("div");
|
||||||
outputWindow.innerHTML = e.data.gotChat.msg;
|
outputWindow.innerHTML = e.data.gotChat.msg;
|
||||||
outputWindow.style.border="1px dotted black";
|
outputWindow.style.border="1px dotted black";
|
||||||
iframeContainer.appendChild(outputWindow);
|
iframeContainer.appendChild(outputWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("action" in e.data){
|
if ("action" in e.data){
|
||||||
var outputWindow = document.createElement("div");
|
var outputWindow = document.createElement("div");
|
||||||
outputWindow.innerHTML = "child-page-action: "+e.data.action+"<br />";
|
outputWindow.innerHTML = "child-page-action: "+e.data.action+"<br />";
|
||||||
outputWindow.style.border="1px dotted black";
|
outputWindow.style.border="1px dotted black";
|
||||||
iframeContainer.appendChild(outputWindow);
|
iframeContainer.appendChild(outputWindow);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ("loudness" in e.data){
|
if ("loudness" in e.data){
|
||||||
console.log(e.data);
|
console.log(e.data);
|
||||||
if (document.getElementById("loudness")){
|
if (document.getElementById("loudness")){
|
||||||
outputWindow = document.getElementById("loudness");
|
outputWindow = document.getElementById("loudness");
|
||||||
} else {
|
} else {
|
||||||
var outputWindow = document.createElement("div");
|
var outputWindow = document.createElement("div");
|
||||||
outputWindow.style.border="1px dotted black";
|
outputWindow.style.border="1px dotted black";
|
||||||
iframeContainer.appendChild(outputWindow);
|
iframeContainer.appendChild(outputWindow);
|
||||||
outputWindow.id = "loudness";
|
outputWindow.id = "loudness";
|
||||||
}
|
}
|
||||||
outputWindow.innerHTML = "child-page-action: loudness<br />";
|
outputWindow.innerHTML = "child-page-action: loudness<br />";
|
||||||
for (var key in e.data.loudness) {
|
for (var 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";
|
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.
|
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.
|
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.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user