Ninja Docs
  • What is VDO.Ninja?
    • How does it work
    • Use cases
    • Why use VDO.Ninja over other solutions?
    • Sponsor ❤
  • Getting started
    • VDO.Ninja basics
    • What are stream IDs?
    • The power of the URL parameter
    • Multi-Person Chat
    • Rooms
    • Even higher quality video
    • Mobile phone camera into webcam
    • Cheat sheet of basic parameters
  • Steve's helper apps & tools
    • Electron Capture
      • Documentation
    • Social Stream Ninja
      • Documentation reference
    • Meshcast.io
    • Caption.Ninja
    • Raspberry.Ninja
      • Documentation
    • Mixer App
    • WHIP and WHEP tooling
    • Versus.cam
    • Speed Test
    • Comms
    • Teleprompter Tool
    • LUT maker for color grading
    • Native mobile app versions
    • VDO Applications
    • Tech Demonstrations
    • Invite Link Generators
    • Community contributed tools
    • Mic test
  • Guides
    • Cheat Sheets
    • Common questions re: Rooms
    • Video bitrate for push/view links
    • Video bitrate in rooms
    • How to get permanent links
    • Basic hotkeys
    • MIDI, API and WebHID support
    • Hardware-accelerated video encoding
    • Audio Filters & Bitrate
    • Options to record streams
    • External guides and how-tos
    • How to lock the resolution
    • How to use VDO.Ninja as a webcam for Google Hangouts, Zoom, and more
    • How to capture without browser sources
    • How to control bitrate/quality
    • How to selectively allow access
    • Stream Scheduling and Promotion
    • How to send the audio/video output of one OBS to another OBS using VDO.Ninja
    • How to mirror a video while Full-Screen - For iPads and Teleprompters
    • How to capture an application's audio
    • How to control VDO.Ninja with Touch Portal
    • How to publish from OBS into VDO.Ninja
    • How to screen share your iPhone/iPad
    • How to get iPhones to output 1080p Videos
    • How to stream into Zoom without OBS
    • How to connect a smartphone to computer via USB
    • How to edit an invite after sending it
    • How to get highest video quality (for an interview)
    • How to stream 4K video using VDO.Ninja
    • How to get lowest audio latency possible
    • How to share webcam from inside OBS
    • How to publish to Facebook Live
    • How to embed VDO.Ninja into a site with iFrames
      • Detecting User Joins / Disconnects
    • How to use the green screen just locally
    • How to connect a GoPro to VDO.Ninja
    • How to install RaspNinja on Jetson
    • How to transfer guests to other rooms
    • How to set up a simple chat room
    • How to screen share in 1080p
    • How to control PowerPoint remotely with VDO.Ninja
    • How to improve quality of the native app
    • How to stream transparent video
    • Recommended OBS WHIP settings
    • How to use VDO.Ninja on a website
    • Keep Mic Active in Background on Android Browser
    • PlayStation or Xbox to VDO.Ninja
    • Enabling WebRTC Sources in OBS
    • Picking the right microphone
    • Set Up Proper Lighting
    • System requirements for streaming
    • From OBS to VDO.Ninja using WHIP
    • Deploy your own Meshcast-like service
    • Windows TTS Audio Capture Methods for OBS
    • Syncing USB audio with VDO.Ninja -> OBS Virtual Camera
  • Advanced Options (URL Parameters)
    • Most common Parameters
      • &push
      • &quality
      • &videodevice
      • &audiodevice
      • &effects
      • &label
      • &meshcast
      • &view
      • &videobitrate
      • &audiobitrate
      • &codec
      • &novideo
      • &noaudio
      • &showlabels
      • &room
      • &director
      • &proaudio
      • &scene
      • &roombitrate
      • &password
      • &broadcast
    • Setup Parameters
      • &push
      • &room
      • &password
      • &hash
      • &e2ee
      • &label
      • &labelsuggestion
      • &permaid
      • &group
      • &groupview
      • &groupaudio
      • &datamode
      • &audiooutput
      • &sink
      • &audiodevice
      • &videodevice
      • &vdo
      • &device
      • &miconly
      • &miconlyoption
      • &safemode
      • &autostart
      • &easyexit
      • &webcam
      • &webcam2
      • &screenshare
      • &screenshare2
      • &website
      • &fileshare
      • &intro
      • &host
      • &tips
      • &welcome
      • &welcomeb64
      • &welcomeimage
      • &hangupmessage
      • &humb64
      • &groupmode
      • &audience
    • Camera Parameters
      • &whitebalance
      • &exposure
      • &saturation
      • &sharpness
      • &contrast
      • &brightness
    • Video Parameters
      • &blind
      • &quality
      • &width
      • &height
      • &aspectratio
      • &contenthint
      • &mediasettings
      • &noscale
      • &fps
      • &maxframerate
      • &effects
      • &effectvalue
      • &imagelist
      • &avatar
      • &fullscreen
      • &showpreview
      • &minipreview
      • &minipreviewoffset
      • &largepreview
      • &nopreview
      • &hideguest
      • &videomute
      • &ptz
      • &webp
      • &webpquality
      • &scale
      • &viewwidth
      • &viewheight
      • &dpi
      • &sharper
      • &codec
      • &h264profile
      • &buffer
      • &buffer2
      • &fadein
      • &broadcast
      • &directoronly
      • &showonly
      • &novideo
      • &nodirectorvideo
      • &slideshow
      • &zoom
    • Video Bitrate Parameters
      • &outboundvideobitrate
      • &maxvideobitrate
      • &limittotalbitrate
      • &controlroombitrate
      • &roombitrate
      • &maxbandwidth
      • &videobitrate
      • &totalscenebitrate
      • &totalroombitrate
      • &totalbitrate
      • &zoomedbitrate
      • &optimize
    • Audio Parameters
      • &proaudio
      • &stereo
      • &mutespeaker
      • &deafen
      • &noaudioprocessing
      • &audiodevice
      • &echocancellation
      • &audiogain
      • &autogain
      • &compressor
      • &denoise
      • &distort
      • &equalizer
      • &limiter
      • &lowcut
      • &noisegate
      • &noisegatesettings
      • &audiocontenthint
      • &audiolatency
      • &micdelay
      • &mute
      • &automute
      • &outboundaudiobitrate
      • &inputchannels
      • &monomic
      • &audiooutput
      • &sink
      • &volume
      • &volumecontrol
      • &audiobitrate
      • &vbr
      • &mono
      • &noaudio
      • &nodirectoraudio
      • &panning
      • &sync
      • &samplerate
      • &channels
      • &channeloffset
      • &playchannel
      • &ptime
      • &maxptime
      • &minptime
      • &audiocodec
      • &dtx
      • &nofec
    • Mixer/Scene Parameters
      • &solo
      • &view
      • &include
      • &exclude
      • &layout
      • &activespeaker
      • &activespeakerdelay
      • &order
      • &slots
      • &fakeguests
      • &randomize
      • &cover
      • &43
      • &portrait
      • &square
      • &forceviewerlandscape
      • &animated
      • &manual
      • &locked
      • &poster
      • &hideplaybutton
      • &motiondetection
      • &scene
      • &scenetype
      • &autoadd
      • &hiddenscenebitrate
      • &preloadbitrate
      • &waitimage
      • &waitmessage
      • &waittimeout
      • &viewslot
    • Settings Parameters
      • &language
      • &remote
      • &controlobs
      • &allowedscenes
      • &stats
      • &sticky
      • &clearstorage
      • &disablehotkeys
      • &showlist
      • &nopush
      • &hidehome
      • &hidetranslate
      • &clock
      • &clock24
      • &timer
      • &powerpoint
      • &widget
      • &token
      • &transcribe
      • &signalmeter
      • &batterymeter
      • &consent
      • &prompt
      • &hands
      • &notify
      • &r2d2
      • &directorchat
      • &maxconnections
      • &maxviewers
      • &chunked
      • &retransmit
      • &rampuptime
      • &sensor
      • &sensorfilter
      • &postimage
      • &postinterval
      • &slot
      • &closedcaptions
      • &nocaptionlabels
      • &enhance
      • &bitratecutoff
      • &cutscene
      • &statsinterval
      • &keyframerate
      • &maxpublishers
      • &showconnections
      • &obsfix
      • &streamlabs
      • &getfaces
      • &nochunked
    • Buttons and Control Bar Parameters
      • &autohide
      • &controlbarspace
      • &nosettings
      • &nomicbutton
      • &nospeakerbutton
      • &novideobutton
      • &nofileshare
      • &screensharebutton
      • &nohangupbutton
      • &chatbutton
      • &bigbutton
      • &fullscreenbutton
      • &nowebsite
      • &hands
      • &videocontrols
      • &nocontrols
      • &forcecontrols
    • Design Parameters
      • &label
      • &showlabels
      • &fontsize
      • &style
      • &bgimage
      • &showall
      • &meterstyle
      • &cleanoutput
      • &cleanish
      • &css
      • &base64css
      • &js
      • &base64js
      • &mirror
      • &nomirror
      • &flip
      • &rotatewindow
      • &structure
      • &color
      • &blur
      • &border
      • &bordercolor
      • &rounded
      • &margin
      • &darkmode
      • &lightmode
      • &background
      • &chroma
      • &transparent
      • &nocursor
      • &favicon
      • &headertitle
      • &rotate
      • &grid
      • &hideheader
      • &hidemenu
      • &tally
      • &tallyoff
      • &cleanviewer
      • &obsoff
      • &pip
      • &pipall
      • &pipme
    • Director Parameters
      • &director
      • &codirector
      • &blindall
      • &cleandirector
      • &hidesolo
      • &hidecodirectors
      • &minidirector
      • &orderby
      • &queue
      • &rooms
      • &broadcasttransfer
      • &showdirector
      • &slotmode
      • &previewmode
      • &novice
      • &layouts
      • &maindirectorpassword
      • &totalroombitrate
      • &limittotalbitrate
      • &notify
      • &mutespeaker=0
      • &showconnections
      • &widget
      • &pausepreview
    • Screen-share Parameters
      • &screensharestereo
      • &screenshare
      • &screenshare2
      • &screenshareaec
      • &screenshareautogain
      • &screensharecursor
      • &screensharedenoise
      • &screensharefps
      • &screensharehide
      • &screenshareid
      • &screensharelabel
      • &screensharequality
      • &screensharecontenthint
      • &screenshareaspectratio
      • &screensharetype
      • &smallshare
      • &screensharevideoonly
      • &suppresslocalaudio
      • &prefercurrenttab
      • &selfbrowsersurface
      • &systemaudio
      • &displaysurface
      • &screensharebutton
      • &screensharebitrate
      • &sharperscreen
      • &sspaused
    • Recording Parameters
      • &record
      • &autorecord
      • &autorecordlocal
      • &autorecordremote
      • &recordcodec
      • &pcm
      • &recordmotion
      • &chunked
    • Guest queuing Parameters
      • &queue
      • &screen
      • &hold
      • &holdwithvideo
      • &queuetransfer
    • Meshcast Parameters
      • &meshcast
      • &meshcastaudiobitrate
      • &meshcastbitrate
      • &meshcastcodec
      • &mcscreensharebitrate
      • &mcscreensharecodec
      • &meshcastscale
      • &meshcastcode
      • &nomeshcast
    • WHIP Parameters
      • &whipout
      • &whipview
      • &whipoutcodec
      • &whipoutaudiobitrate
      • &whipoutvideobitrate
      • &whipoutscale
      • &whipoutscreensharecodec
      • &whipoutscreensharebitrate
      • &cftoken
      • &svc
    • Mobile Parameters
      • &facing
      • &forcelandscape
      • &forceportrait
      • &forceios
      • &notios
      • &flagship
      • &mobile
      • &notmobile
      • &app
    • API & MIDI Parameters
      • &api
        • API reference
        • API reference - AI Generated
        • Client (node) event example
      • &pie
      • &midi
      • &midiin
      • &midiout
      • &midiremote
      • &midichannel
      • &mididevice
      • &midioffset
      • &mididelay
      • &datamode
      • &postapi
    • TURN & STUN Parameters
      • &turn
      • &stun
      • &addstun
      • &icefilter
      • &proxy
      • &relay
      • &secure
      • &tcp
      • &tz
    • Parameters added in Version 24
    • Complete List of Parameters in v26
    • Upcoming Parameters
    • Other Parameters
  • Releases
    • v24
    • v23 🌱
    • v22 👑
    • v21 ❤️
    • v20 🎁
    • v19 🚀🤯
      • v19.1 - 19.4
    • v18
      • v18.3
    • v17
    • v16
      • v16.3
      • v16.4
    • v15
    • v14
    • v13
      • v13.4
    • v12
    • v10
    • v8
  • Updates
    • Updates - VDO.Ninja
    • Updates - Social Stream & Chat Overlay
      • Updates - Social Stream Standalone App
    • Updates - Electron Capture App
    • Updates - Raspberry.Ninja
    • Updates - Versus.cam
    • Updates - Mixer App
    • Updates - WHIP/WHEP
    • Updates - Native mobile apps
    • Updates - Caption.Ninja
    • Updates - Meshcast.io
    • Updates - Speed Test
    • Updates - Comms
    • Updates - Miscellaneous
  • Development Progress
  • Help!
    • Fail safes and Backups
    • Privacy and security details
      • VDO.Ninja Terms of Service
      • VDO.Ninja Privacy Policy
    • Project Contact Info
    • Where can I report a bug?
    • Where can I get support?
    • Feature Requests
    • Logos and media assets
    • What does VDO stand for?
  • Common errors and known issues
    • Can't screen capture certain games
    • ATEM not working with Firestick
    • Very old iPhone support
    • Can't select audio output on iOS
    • Screen-share is just a black video
    • Mic audio dropping out
    • Loss of audio when OBS minimized
    • Known issues
    • Echo or feedback issues
    • Works on WiFi but not on 4G
    • Can't capture an application's audio when screen-sharing
    • Can't load camera both in OBS and VDON
    • Can't select a camera lens on mobile
    • No video in OBS, just an "Add camera" button
    • Audio over VDO.Ninja isn't working
    • Loading circle shows in OBS or browser
    • Appearing then disappearing guest
    • Can't auto-start screen sharing
    • Audio Clicking / Popping / Distortion
    • Can't share my screen
    • Nothing shows up in OBS
    • Already in use or claimed errors
    • Blue spinning window
    • Cursor shows trailing or artifacting
    • Packet Loss
    • Overheating
    • Audio is delayed in OBS
    • vMix High CPU
    • OBS Virtual Camera has low FPS
    • Virtual camera not working on Mac
    • Mic stops on MacOS when OBS opens
    • Video stream looks corrupted
    • Video freezes mid-stream
    • Webcam freezes after a time
    • Is the VDO.Ninja server down?
    • Hosted your own TURN server?
    • Can't screen-share from certain devices
    • Cursor shows when screen-sharing
    • Getting “Overconstrained" Camera Error
    • Autoplay doesn't work in Chrome or vMix v77
    • Low frame rates
    • Black borders around the video in OBS
    • Mic's volume keeps changing
    • Enable Camera / Microphone permissions
    • FPS drop if app not in focus
    • Surround sound error when screen sharing with USB headset
    • Relay candidate being selected
    • Camera works in Safari; not Chrome
    • Robotic Audio Distortion
    • Can't load camera from non-SSL host
    • Camera on macOS doesn't show?
    • Can't screen share Adobe Lightroom
    • Decklink support?
    • iOS audio stops during phone calls
    • Can't turn off echo-cancellation on macOS
    • Video lag grows over time
    • Can't connect unless via VPN
    • Improving vMix performance
  • Platform specific issues
    • Android
    • macOS
    • iOS (iPhone/iPad)
    • Firefox
    • Opera GX
  • Useful Links
  • FAQ
  • Sponsor ❤
  • Edit this documentation
Powered by GitBook
On this page
  • Transparency
  • Advanced IFrame functionality
  • Basic full window IFRAME control
  • WebViews
  • Raw video and audio transport
  • Securing your stream ID
  • All to happy to support the IFRAME API

Was this helpful?

  1. Guides

How to embed VDO.Ninja into a site with iFrames

How to embed VDO.Ninja into your own website with the IFRAME API

PreviousHow to publish to Facebook LiveNextDetecting User Joins / Disconnects

Last updated 2 months ago

Was this helpful?

offers here a simple and free solution to quickly enable real-time video streaming in their websites. VDON wishes to make live video streaming development accessible to any developer, even novices, yet still remain flexible and powerful.

While VDO.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 allows us to embed a webpage inside a webpage, including VDO.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 VDON 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 VDON iframe can be done in HTML or programmatically with JavaScript like so:

const iframe = document.createElement("iframe");
iframe.allow = "document-domain;encrypted-media;sync-xhr;usb;web-share;cross-origin-isolated;midi *;geolocation;camera *;microphone *;fullscreen;picture-in-picture;display-capture;accelerometer;autoplay;gyroscope;screen-wake-lock;";
iframe.src = "https://vdo.ninja/?push=vhX5PYg&cleanoutput&transparent";

You can also make an VDO.Ninja without Javascript, using just HTML, like:

<iframe allow="document-domain;encrypted-media;sync-xhr;usb;web-share;cross-origin-isolated;midi *;geolocation;camera *;microphone *;fullscreen;picture-in-picture;display-capture;accelerometer;autoplay;gyroscope;screen-wake-lock;" src="https://vdo.ninja/?push=vhX5PYg&cleanoutput&transparent"></iframe> Adding that IFrame to the DOM will reveal a simple page for 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 VDO.Ninja is with its Internet Speedtest, which has two VDO.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.

More community-contributed IFrame examples can be found here:

A sandbox of options is available at this page, too: You can enter an VDO.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:

I also have an example of how you can transfer virtually any data (JSON, text, small images) via the IFrame API with just a few lines of code here: It's a pretty awesome example of how you can securely communicate peer to peer online with virtually zero effort and with no cost.

There's dozens of other examples of how the IFrame API can be used to communicate via p2p, easily with any website, such as controlling PowerPoint remotely, but here's an example of how to use it to control OBS Studio remotely.

Please note that since VDO.Ninja requires SSL to be strictly enabled site wide, any website you embed a VDO.Ninja IFrame into also will require SSL enabled site wide. Using a service like Cloudflare can provide SSL-enabled caching for websites to make this fairly easy to do.

Please also note that there we are allowing numerous permissions when setting up our IFRAME. You may need to adjust these for your use case; allow="camera *;microphone *;" for example.

Something else to note about this IFrame API is that it can not only be controlled via URL parameters given to the IFrame src URL, but also using postMessage and addEventListener methods of the browser. The later is used to dynamically control VDO.Ninja, while the former is used to initiate the instance to a desired state.

Some of the more interesting ones primarily for IFrame users might include:

  • 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

As for the actually details for methods and options available to dynamically control child VDON 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:

let button = document.createElement("button");
button.innerHTML = "Mute Speaker";
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
    }, '*');
};
iframeContainer.appendChild(button);

button = document.createElement("button");
button.innerHTML = "Toggle Speaker";
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
    }, '*');
};
iframeContainer.appendChild(button);

button = document.createElement("button");
button.innerHTML = "Un-Mute Mic";
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"
    }, '*');
};
iframeContainer.appendChild(button);

button = document.createElement("button");
button.innerHTML = "Disconnect";
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
    }, '*');
};
iframeContainer.appendChild(button);

button = document.createElement("button");
button.innerHTML = "High Bitrate";
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
    }, '*');
};
iframeContainer.appendChild(button);

button = document.createElement("button");
button.innerHTML = "Reload";
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
    }, '*');
};
iframeContainer.appendChild(button);

button = document.createElement("button");
button.innerHTML = "100% Volume";
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
    }, '*');
};
iframeContainer.appendChild(button);

button = document.createElement("button");
button.innerHTML = "Request Loudness Levels";
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
    }, '*');
};
iframeContainer.appendChild(button);

button = document.createElement("button");
button.innerHTML = "Say 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"
    }, '*');
};
iframeContainer.appendChild(button);

button = document.createElement("button");
button.innerHTML = "CLOSE IFRAME";
button.onclick = () => {
    iframeContainer.parentNode.removeChild(iframeContainer);
};
iframeContainer.appendChild(button);

// As for listening events, where the parent listens for responses or events from the VDON child frame:

// //////////  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 ("stats" in e.data) {
        const outputWindow = document.createElement("div");

        let out = `<br />total_inbound_connections:${
            e.data.stats.total_inbound_connections
        }`;
        out += `<br />total_outbound_connections:${
            e.data.stats.total_outbound_connections
        }`;

        for (const streamID in e.data.stats.inbound_stats) {
            out += `<br /><br /><b>streamID:</b> ${streamID}<br />`;
            out += printValues(e.data.stats.inbound_stats[streamID]);
        }

        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 ("action" in e.data) {
        const outputWindow = document.createElement("div");
        outputWindow.innerHTML = `child-page-action: ${
            e.data.action
        }<br />`;
        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<br />";
        for (const key in e.data.loudness) {
            outputWindow.innerHTML += `${key} Loudness: ${
                e.data.loudness[key]
            }\n`;
        }
        outputWindow.style.border = "1px black";

    }
});

This VDO.Ninja API is developed and expanded based on user feedback and requests. It is by no means complete, but it is getting better every week.

Transparency

Setting the allowtransparency attribute on the IFrame to true will allow for the contents to be transparent. You can then make VDO.Ninja transparent by adding &transparent to the URL, which sets the page's background to rgba(0,0,0,0).

https://vdo.ninja/iframe can demonstrate this by opening https://vdo.ninja/?transparent with it.

Advanced IFrame functionality

There's some users who wish to have an SDK instead of an IFrame API. While an SDK may happen eventually, currently the IFram API is surprisingly capable.

If you aren't self-hosting the code, you may run into cross origin permission issues or limitations on cross-origin permissions with certain features. You can get around these issues usually by hosting VDO.Ninja as a subdomains though, in certain cases at least, along with the correct web hosting settings set.

See the video below for an advanced demo of the IFRAME API and how videos hosted within VDO.Ninja can be accessed and manipulated by the parent window. Video works well in this fashion; pulling audio from the IFRAME is a bit trickier however. [update: document.domain or such is a bit depreciated now, and while it is possible to use a sub-domain still, you'll need to specify certain headers and permissions with your webserver to allow for it. https://versus.cam for example uses vdo.ninja as a subdomain to access frames across the IFRAME API]

Basic full window IFRAME control

Below is a simple code example of a website that can use VDO.Ninja as normal, full-window, while having a wrapper around it that controls it using the IFrame API.

It also will query the IFRAME every second for detailed state of the current setup, such as who is connected and visible.

This approach can allow you to do very advanced and dynamic configurations for VDO.Ninja, which might not be possible with the normal HTTPS/WSS API or URL parameters. Code injection is also supported, so there's no limit really to what you can do. If you would like to use VDO.Ninja with a custom API or inside an application as a webview, this is also a simple example of the concept.

<style>body,iframe{width:100%;height:100%;margin:0;padding:0;border:0;background-color:#0000;}</style><body></body><script>

var IFRAMEWINDOW = document.createElement("iframe"); // create VDO.Ninja in an IFRAME
IFRAMEWINDOW.src = "https://vdo.ninja/alpha/?scene&transparent&room=sssss123";

IFRAMEWINDOW.onload = function(){ // start polling shortly after we connect
    setInterval(function(){
            IFRAMEWINDOW.contentWindow.postMessage({"getDetailedState":true}, "*");  // get details every second
        },1000);
}
document.body.appendChild(IFRAMEWINDOW); // add the vdo.ninja element to the page, so its active/visible

window.addEventListener("message", (e) => {
  if (e.source != IFRAMEWINDOW.contentWindow){return} // only listen for vdo.ninja events
  console.log(e.data);// print the messages inbound to the console log
});
</script>

WebViews

The IFrame API is is also a WebView API, using the same concept of listening for events and post-messaging into the VDO.Ninja window.

WebViews are available within iOS and Android native apps, Electron.js apps, and other applications, like Unity or Unreal.

This is a great way to configure, edit, listen to, and control VDO.Ninja, without a web or MIDI API.

Raw video and audio transport

Securing your stream ID

Using the &audience option, you can have a consistent stream ID on your website that only you can publish to. Great for using VDO.Ninja as a small scale broadcast player on a personal website.

All to happy to support the IFRAME API

I am keen to continue to support the IFrame API, so please reach out if you have questions or requests.

-steve

=1 or 0

=1 or 0

If you wish to use your own video mixer logic for example, you can disable the existing auto-mixer logic that currently exists using the flag. You can then access the srcObject of each of the video elements in VDO.Ninja and pull those streams into the parent frame to manipulate or to connect to the parent DOM.

It's possible to transmit uncompressed video frames and audio data from VDO.Ninja to the parent window using the post-mesasging API. This allows video playback to happen outside the IFrame itself, using your own custom mixing logic. See for a code example; the website is on Steve's GitHub for reference. Please note, this may require a custom deployment of VDO.Ninja's website code (SameOriginPolicy), and likely will also require a recent Chromium-based browser to use.

Please feel free to follow me in the VDO.Ninja Discord channel () where I post news about updates and listen to requests. The upcoming version of VDO.Ninja is also often hosted at , where you can explore new features and help crush any unexpected bugs.

VDO.Ninja
IFrame
https://vdo.ninja/speedtest
https://github.com/steveseguin/vdoninja/tree/master/examples
https://vdo.ninja/iframe
https://github.com/steveseguin/vdoninja/blob/master/iframe.html
https://gist.github.com/steveseguin/15bba03d1993c88d0bd849f7749ea625
https://github.com/steveseguin/sample-p2p-tunnel
&webcam
&screenshare
&videodevice
&audiodevice
&autostart
&chroma
&transparent
&manual
https://javascript.info/cross-window-communication#windows-on-subdomains-document-domain
https://versus.cam
&audience
discord.vdo.ninja
https://vdo.ninja/beta