description |
---|
Understanding URL parameters and custom settings |
VDO.Ninja is a tool that can be seen as a mediator, negotiating a direct connection between a publishing device and a viewing device (such as OBS [Open Broadcaster Software]). There are generally two links involved; one to push (publish) and one to pull (view), although links can be made to do both at the same time.
The viewer (receiver) and the publisher (sender) each play their own role in determining the qualities of a stream, so likewise each side has its own set of parameters available to them. A publisher can have multiple viewers access their video stream, with each viewer having the ability to customize the quality of the stream they receive.
The following guide details the options, syntax, values, and general use of these available settings/parameters.
You can customize the playback of videos by adding query string parameters to the VDO.Ninja URL links, along with many other aspects. VDO.Ninja is highly flexible in this regard, letting you achieve your desired outcome without needing to code and without additional software.
For example, a simple viewer URL link such as https://vdo.ninja/?view=streamid
could be amended to https://vdo.ninja/?view=streamid&videobitrate=500
, which will cause the viewer to receive the publisher's video stream at a video bitrate of 500-kbps.
Multiple parameters can be appended together by using the ampersand (&
) as a separating character. For example, to view the video stream published at stream ID streamid
at a video bitrate of 500-kbps and set the &stereo
parameter to 1
:
http://vdo.ninja/?view=streamid&videobitrate=500&stereo=1
Some parameters, like &view
will accept a comma-separated list of valid values, so you can do some rather powerful combos, such as publish a video (using &push
) while also viewing multiple others videos. VDO.Ninja will auto-mix the videos together into a single layout for you:
http://vdo.ninja/?push=aaa&view=bbb,ccc,ddd
You might notice the stream ID values I'm using (ie: aaa
, bbb
, etc); these can be manually created and reused. Use &push=STREAMID
to publish a video and &view=STREAMID
to remotely view it. If you don't manually specify a stream ID, VDO.Ninja will sometimes generate one for you.
{% hint style="info" %} To make up a valid stream ID of your own though, choose something with less than 31-characters of length and ensure it's AlpHaNuMerIc-only. {% endhint %}
A stream ID must also not already be in active use, else you will be provided with an error.
All of the available parameters can be seperated in five categories. You find the category on the top of the page of a parameter.
- General Option (
&push
,&room
,&view
,&scene
,&solo
,&director
)
You can use these parameters as a sender or as a viewer as well as in scenes, solo-links and rooms or even as a director. - Sender-Side Option (
&push
)
You can use these parameters as a sender when you are publishing a video with&push
. You can use these parameters in rooms (&room
) when publishing or as a basic push link outside a room. These parameters will affect the outgoing stream. - Viewer-Side Option (
&view
,&scene
,&room
,&solo
)
You can use these parameters as a viewer of one or more video sources (scenes and solo-links in a room, as a guest in a room, or a basic&view
stream). These parameters will affect the incoming stream(s). - Director Option (
&director
)
These parameters are specifically for the director of a room. - Meshcast Option (
&meshcast
)
These parameters can only be used in combination with&meshcast
. You can find them in Meshcast Parameters. These parameters are always Sender-Side Option, so you will find&push
in the URL, too. - WHIP Option (WHIP and WHEP tooling)
WHIP Parameters are specific to WHIP and WHEP. You can find them in WHIP Parameters.
We've broken down the available URL parameters into 22 categories:
- cheat-sheet-of-basic-parameters (the basic and most common parameters)
- setup-parameters (stream ID, create a room, password, labels, groups, devices, auto-start, welcoming guests, sharing a website/file)
- camera-parameters (options to pre-set the camera settings)
- video-parameters (resolution, FPS, effects, self preview, mute video, PTZ, codec, buffer, broadcasting, scale)
- video-bitrate-parameters (changing the bitrate of the outgoing and incoming video and for rooms)
- audio-parameters (filters, adding delay, bitrate, channels, mono/stereo, muting guests, etc.)
- settings-parameters (language, save cookies, remote access, chat widget, chunked mode, raise hands, notify, transcription, closed captions)
- buttons-and-control-bar-parameters (show/hide buttons, adjust the user control bar and video control bar)
- design-parameters (labels, styles, clean output, CSS, mirroring, margin, dark mode, background color, disable tallies, etc.)
- mixer-scene-parameters (layout and design for the video mixer in rooms/scenes, preload/hidden scene bitrate)
- director-parameters (specific to the director's control room and director-specific features)
- screen-share-parameters (labels, audio filters, type, bitrate, quality, etc.)
- recording-parameters (options to specify recordings with VDO.Ninja)
- guest-queuing-parameters (options for guest queuing and approving system)
- meshcast-parameters (options for the
&meshcast
parameter like audio filters, bitrate, screen-share, codecs, etc.) - whip-parameters (options to specify the
&whip
parameter) - mobile-parameters (options to specify push links and guest invite links for mobile phones)
- api-and-midi-parameters (hotkey features via API and MIDI)
- turn-and-stun-parameters (options for setting up TURN and STUN servers)
- new-parameters.md (recently added to VDO.Ninja)
- upcoming-parameters.md (only on VDO.Ninja/beta and/or VDO.Ninja/alpha version at the moment)
- other-parameters.md (not ready for production, not intended to be used or not well-documented)
This link has been moved to here: https://docs.vdo.ninja/advanced-settings
Please find the new link here:
https://docs.vdo.ninja/sponsor
Web service URL: https://vdo.ninja/
Project development URL: https://github.com/steveseguin/vdo.ninja
Developer/maintainer: [email protected]
Donations: via GitHub Sponsors
Discord: https://discord.vdo.ninja
Reddit: https://www.reddit.com/r/VDONinja/
The preferred support mechanism is via Reddit or Discord, which offer community-assisted support. Development issues, feature requests, and bugs are tracked on GitHub. For mission critical support issues, or business-related inquiries, you can contact Steve directly.
It is most helpful to report bugs via the official GitHub. We also monitor the Reddit and Discord channels, though it is easier to miss reports that occur there.
VDO.Ninja relies heavily on WebRTC, a secure peer-to-peer streaming technology that exists in most modern web browsers. Most of the VDO.Ninja code runs completely within your browser, although some server-side components are hosted to help facilitate an initial ‘handshake’ between connecting peers.
As video data is streamed directly from one peer to the other, extremely low-latency and very high video quality is possible. If both peers are on the same Local Area Network (LAN), data transfer will stay local to your network, saving your bandwidth.
Since applications like OBS have a built-in browser, you can use VDO.Ninja to stream low-latency video directly into the application without any downloads or user accounts. It's possible to start streaming within seconds to OBS and many modern applications -- you can even watch VDO.Ninja streams on a Tesla EV or within the Unity game engine.
Essentially, the basic usage of VDO.Ninja makes use of two URLs; one for input (i.e. PUSH) and one as an output (i.e. VIEW).
The PUSH URL is loaded up in the browser on the remote device, which obtains access to the device's camera and microphone.
To view the stream, you load up the corresponding VIEW URL in another browser, from anywhere. That's it. The video will begin playing in a full-window, without pesky watermarks or visual distractions, ready for professional-level video capture.
Since collaboration is a big part of live streaming video, VDO.Ninja also offers group chat rooms, allowing for more complex options and controls over multiple streams at a time. What's possible with VDO.Ninja can be rather overwhelming, as the feature set does not end there, but the basic defaults are designed to satisfy the needs of most users.
One thing that may not be intuitive at first is the use of URL-parameters to control settings, video quality, and many of the other options. URL parameters are used by VDO.Ninja in the same conceptual way that command-line parameters are used, such as by FFmpeg. Some URL parameters are set on the VIEW side, while others can be set on the PUSH side to allow for configuration of a standard offering with the opportunity for viewers to further refine their experience. The documentation is a great resource for finding out more on all the advanced options and how to use them.
Description | URL |
---|---|
Official Version | https://vdo.ninja/ |
Beta Version | https://vdo.ninja/beta/ |
Alpha Version | https://vdo.ninja/alpha/ |
BackUp Version | https://backup.vdo.ninja/ |
Previous Versions | https://docs.vdo.ninja/releases |
Project Development on GitHub | https://github.com/steveseguin/vdo.ninja |
Development Progress | https://docs.vdo.ninja/updates/updates-vdo.ninja |
Description | URL |
---|---|
Wizard-style | https://linkgen.vdo.ninja/ |
Toggle-style | https://invite.vdo.ninja/ |
Excel-based | https://drive.google.com/file/d/1A7qiFAC... |
Trampoline | https://rse.github.io/vdo-ninja-trampoline/ |
URL Obfuscator for VDO.Ninja | https://invite.cam/ |
Invite Dock for OBS | https://vdo.ninja/dock |
Description | URL |
---|---|
iOS | https://apps.apple.com/us/app/vdo-ninja/id1607609685 |
Android | https://play.google.com/store/apps/details?id=flutter.vdo.ninja |
Description | URL |
---|---|
GitHub Sponsors | https://github.com/sponsors/steveseguin |
Buy Steve a coffee | https://www.buymeacoffee.com/steveseguin |
PayPal | https://www.paypal.com/paypalme/steveseguin |
Discord Server | https://discord.vdo.ninja/ |
---|---|
https://reddit.com/r/vdoninja | |
Steve's YouTube | https://www.youtube.com/c/SteveSeguin82 |
Description | URL |
---|---|
Overview | https://docs.vdo.ninja/steves-helper-apps |
Live stream to multiple people | https://meshcast.io/ |
Electron Capture App | https://github.com/steveseguin/electroncapture |
Steve's App | https://steves.app/ |
Social Stream | https://socialstream.ninja/ |
Captioning Tool | https://caption.ninja/ |
Translation Tool | https://caption.ninja/translate |
Raspberry Ninja | https://raspberry.ninja/ |
YouTube, Twitch chat and social comment Overlays plugin | https://chat.overlay.ninja/ |
Lets you toggle your mouse cursor's visibility on and off | https://github.com/steveseguin/hide-cursor |
Description | URL |
---|---|
Vingester (ingest web pages as NDI-multicasted streams) | https://vingester.app/ |
Vingester (v22 compatible) | https://github.com/steveseguin/vingester/releases/tag/2.8.1 |
Companion Module (remote control VDON via this plugin for Companion) | https://github.com/bitfocus/companion-module-vdo-ninja |
Known issues that are most critical are normally listed on the main page of VDO.Ninja.
You can also refer to the #report-bugs channel on discord, at https://discord.vdo.ninja, to see recently reported issues. I push bug fixes daily to beta, at https://vdo.ninja/beta, so give that a shot if you find a bug on the main release.
Since bugs and issues are ever evolving, it's hard to keep all issues up to date and verified.
Below are some links to third parties, for a list of known issues that commonly will apply to VDO.Ninja as well:\
https://docs.agora.io/en/All/web_sdk_compatibility?platform=Web
https://github.com/twilio/twilio-video.js/blob/master/COMMON_ISSUES.md
https://support.twilio.com/hc/en-us/articles/223180908-Troubleshooting-Common-Problems-with-the-Twilio-Voice-JavaScript-SDK
https://github.com/webrtc/samples/issues
https://bugs.chromium.org/p/chromium/issues/list?q=webrtc%20type%3DBug&can=2&sort=-pri
There are some more parameters on VDO.Ninja which are currently not ready for production, not intended to be used, or not well-documented.
You could find out more about these parameters when searching for them on this link:
https://github.com/steveseguin/vdo.ninja/blob/develop/main.js
Parameter | Explanation |
---|---|
&crop | Changes the aspect ratio on the publisher side, but lets you pass an integer value to represent a percentile cropping value. So, &crop=10 will reduce the width by 90% and &crop=-10 will increase the aspect ratio. The assumed base aspect ratio is 16:9. |
&debug | Sends live debug log data to a remote server. That debug server is normally off, but this flag can be used by Steve to debug issues remotely. The debug data is not stored at any point. |
&directorview | Not currently an active feature. |
&nomouseevents | Disables 'some' of the mouse/touch/drag triggers and events; for debugging and niche situations. |
&nonacks | 'Tries' to force the browser to not send key frames or lower quality/resolution; doesn't really work. Tells the browser to not send NACK feedback. |
&nopli | Tries to find ways to combat frame stutter caused by packet loss or key frame requests. Doesn't really work. Tells the browser to not send picture loss indicators. |
&noremb | Deletes the flag for Chrome's bandwidth estimation logic. |
&pusheffectsdata | Makes the data for the active digital effect available to the IFRAME API or a remote guest. |
&retry | Used in rare cases, sometimes with the Raspberry Ninja project, where the peer connection may "crash" and the remote viewer won't bother to try reconnecting. |
&retrytimeout | Should not be changed (value in milliseconds). |
&salt | Mainly to allow Versus.cam to work with VDO.Ninja. |
&slot | Not currently an active feature. |
&speedtest | Forces essentially UDP mode, unless TCP is specified, and some other stuff. |
&viewereffect | Not currently an active feature. |
&wss | Specify the handshake server address to use. |
&graphs | ? |
&lowmobilebitrate | ? |
&maxmobilebitrate | ? |
&minroombitrate | ? |
&sendframes | ? |
&overlaycontrols | ? |
&pushloudness | This sets the loudness IFRAME API output, if available |
&hangupbutton | ? |
&socialstream | ? |
&fakeuser | ? |
&androidfix | ? |
&scenelinkcodec | This is mainly for a niche IFRAME API use |
&scenelinkbitrate | This is mainly for a niche IFRAME API use |
&showheader | Forces the header bar to show even if using &cleanoutput for example |
°rade | Firefox, and maybe Safari, supported I think. The possible values are maintain-framerate , maintain-resolution , or balanced . The default value is balanced. |
&iframetarget | Specifies the IFRAME Hostname target |
&bypass | ? |
&mixminus | In development |
&nopassword | ? |
&micsamplerate | Lets you specify the capture audio sample rate. Also added purely for experimental reasons; I don't recommend touching. |
&insertablestreams | Enables a special mode that allows for custom codecs |
&leaveorientationflag | ? |
&motionrecord | Switch OBS to this scene when there is motion, and "solo view" this video in the VDO.Ninja auto-mixer, if used |
&alpha | Fixed &webp + &codec=webp + &alpha so it properly supports alpha channels. If your needs are modest it can offer transparent streaming video when using &fileshare /w a transparent WebM video source (or a virtual background /w a transparent png) |
In its simplest form, VDO.Ninja brings live video from a smartphone, tablet, or remote computer, directly into OBS Studio or other browser-enabled software. VDO.Ninja is offered as a free web service, but it's also available as customizable and deployable code. Some have called it the modern Swiss Army knife of audio and video transmission. 🛠\
{% embed url="https://www.youtube.com/watch?index=1&list=PLWodc2tCfAH1l_LDvEyxEqFf42hOBKqQM&v=QaA_6aOP9z8" %} Video intro to VDO.Ninja and getting-started playlist {% endembed %}
There is a playlist of videos above that will demonstrate some of the basics. YouTube actually has MANY community-created guides, in various languages, that you can check out also.
The documentation that you are reading here contains details of advanced settings (URL parameters), support information, starting guides, and more. Using the search-box is a great way to navigate it for specific topics.
There are some cheat sheet and quick-start guides here:
{% content-ref url="guides/cheat-sheets.md" %} cheat-sheets.md {% endcontent-ref %}
There are a few basic guides for beginners here as well:
{% content-ref url="getting-started/" %} getting-started {% endcontent-ref %}
The preferred support mechanism is via Reddit or Discord, which offer community-assisted support. Discord is very active, so check it out. As well, development issues, feature requests, and bugs are tracked on GitHub.
For mission critical support issues, or business-related inquiries, you can contact Steve directly. Please don't make it a habit.
It is most helpful to report bugs via the official GitHub. While we monitor the Reddit and Discord channels, it is easy to miss issues/details that occur in comments and older threads.
- #electron-capture
- #youtube-twitch-chat-and-social-comment-overlays-plugin
- #meshcast.io
- #caption.ninja
- #raspberry-ninja
- #native-mobile-app-versions-for-vdo.ninja
- #social-stream
- #versus.cam
https://github.com/steveseguin/electroncapture
Created for VDO.Ninja users, it can provide users a clean way of window capturing websites. In the case of VDO.Ninja, it may offer a more flexible and reliable method of capturing live video than the browser source plugin built into OBS.
On some systems the OBS Browser Source plugin isn't available or doesn't work all that well, so this tool is a viable alternative. It lets you cleanly screen-grab just a video stream without the need of the Browser Source plugin. It also makes it easy to select the output audio playback device, such as a Virtual Audio device: ie) https://vb-audio.com/Cable/ (Windows & macOS; donationware).
The app can also be set to remain on top of other windows, attempts to hide the mouse cursor when possible, provides accurate window sizes for 1:1 pixel mapping, and supports global system hotkeys (CTRL+M
on Windows, for example).
Windows users may find it beneficial too, as it offers support for VDO.Ninja's &buffer
audio sync command and it has robust support for video packet loss. In other words, it can playback live video better than OBS can, with fewer video playback errors and with better audio/video sync. If you have a spare monitor, it may at times be worth the hassle to use instead of OBS alone.
The Electron Capture app uses recent versions of Chromium, which is more resistant to desync, video smearing, and other issues that might exist in the native OBS browser source capture method. More benefits listed here
Lastly, since playback is agnostic, you can window-capture the same video multiple times, using one copy in a mixed-down live stream, while using a window-capture to record a clean full-resolution isolated video stream.
This Chrome browser extension turns your social chat and comments section into selectable social overlays for OBS Studio or other studio production software.
This chat overlay extension will forward the selected chat message over a web-socket connection to a secondary webpage, which can be used in OBS-Studio as a simple browser source. This makes capturing the chat messages from a live video stream very easy and fast -- no Chroma keying or window-capturing needed. It also makes customizing the style pretty easy, with no Chrome extension development needed.
Supported sites as of August 2022 (requests welcomed)
- glimesh.tv (pop-out chat)
- youtube.com (pop-out chat)
- twitch.tv (pop-out chat)
- restream.io (go here: https://chat.restream.io/chat)
- trovo.live (pop-out chat)
- Instagram (posts) (trigger it with a button)
- Instagram Live (click on chat messages)
- Twitter (works with tweets and replies)
- Facebook Live chat (no pop up option; does not support Mobile/4G/LTE - wifi or ethernet only)
- Crowdcast.io
- Zoom.us (text chat and polls)
- polleverywhere.com (https://www.polleverywhere.com/discourses/xxxxx question page)
- Trovo (open the chat pop-up page: https://trovo.live/chat/xxxxxx)
📺 Video demoing how to install and use here: https://youtu.be/UOg3RvHO-xk
This is a free to use service that can work in conjunction with VDO.Ninja. It's a low latency video CDN (content delivery network), which can be used to host larger group rooms in VDO.Ninja. It's not designed for mass broadcast, not at present anyways, but it can handle upwards of 100-viewers without taxing your CPU or network.
{% embed url="https://www.youtube.com/watch?v=-7QsLChfdsE" %} https://youtu.be/-7QsLChfdsE {% endembed %}
Although VDO.Ninja supports captions, sometimes you need something simple yet flexible. Caption.Ninja lets you use the browser's built in speech-to-text service to provide overlay captions for your live stream.
Captions are streamed via a web-socket service to your OBS or other studio software, where they can be shown over your video.
Transcriptions can be saved by means of copy and paste when done, multiple languages are supported, and even manual user-entered captions support is provided at https://caption.ninja/manual
https://caption.ninja/translate
Added a "translation" component to caption.ninja, so you can convert speakers to a single language for overlay on stream. I tried this before, but only now do I think I have it working okay. There's two ways to use it:
1. You can go here to explore and tinker. https://caption.ninja/translate which offers a bit of a menu to play with, but is sender's side-based translation (works in a single page, but you can't translate to more than one language)
2. And then there's the normal way of using caption.ninja, which offers viewer-side translation and scrolling support, so you can use this mode to have different languages as outputs instead of just one (assuming the viewer supports the translation code).
https://caption.ninja/?room=ufv3QaH&lang=en-US (to capture as english) and https://caption.ninja/overlay?room=ufv3QaH&translate=fr (viewer-side, which converts to french).
I welcome feedback.
Turn your Raspberry Pi or Nvidia Jetson into a Ninja-cam with hardware-acceleration enabled! Publish live streaming video to VDO.Ninja on the cheap at very high resolutions! The script for the Nvidia Jetson ($69 and up) is setup to plug in a $10 1080p30 HDMI to USB adapter and go, while the Raspberry Pi is setup as a quick-deploy image that can work with the official Raspicam.\
Mobile native app versions of VDO.Ninja can be found behind the link below. These are mainly backup options for when the browser-based versions fail to work or lack a certain feature due to system restrictions.
{% content-ref url="getting-started/native-mobile-app-versions.md" %} native-mobile-app-versions.md {% endcontent-ref %}
Consolidate your live social messaging streams, including Youtube, Twitch, and more, into a single chat stream that can be docked into OBS and be used to to select featured chat messages as an overlay.
Very much like Chat Overlay Ninja, except is purely for live chat and has a focus on consolidation of chat messages, instead of just featured chat. Has many features and supported sites at this point.
{% embed url="https://social.overlay.ninja" %} https://github.com/steveseguin/social_stream#readme {% endembed %}
Versus.cam is the upcoming and standalone replacement for the vdo.ninja/monitor page. Versus.cam has some interesting features that are specific to the upcoming version of VDO.Ninja, so at the moment it only works in conjunction with vdo.ninja/alpha.
- It contains a larger and dedicated graph per scene/view link than what the vdo.ninja/beta/'s director room has under scene-stats. Both color code to indicate packet loss, where red is bad, and green is good.
- It is setup to use a group room by default, with a very simple interface to login and get started without visiting vdo.ninja itself.
- Despite having a group room by default, it works with standalone push/view links as well, via the "Add a stream manually" button, which lets you include normal view links that exist outside rooms.
- All the scene links and invite links are preconfigured for E-Sports , where video is set to pull around 20-mbps for smooth 1080p60 game play. The idea is, if you choose to use this page for creating links, it's all already setup to be used for ingestion.
- The room is configured so that guests cannot see or talk to each other. All guests can do is text-chat with the versus host.
- Versus.cam is compatible with a director and the director room, so you can use a director room AND the Versus.cam room at the same time, without conflict.
- A new feature that Versus.cam has, that will also soon be coming to the normal VDO.Ninja directors' room, is the ability to dynamically change the resolution and bitrate of remote scenes. This works by means of the
&remote
control feature, which is preconfigured in the links already, so no director is needed when using versus. This will then also work with non-room links, so long as&remote
is included in their URL. - I don't intend to add many advanced features to this site.
- It's designed to be very simple, elegant, and hyper focused on a single use case and user type.
- E-Sports and one-way ingestion of very high quality video. I'll likely be making more scenario-specific interfaces in the future like this, to make VDO.Ninja easier and less cluttered for common use cases.
- Versus.cam is built using the VDO.Ninja IFRAME API, which I hope demonstrates the flexibility of it.
- Versus.cam is only supported by Chrome/Chromium-based browsers; it isn't yet compatible with Firefox/Safari (they lack the features needed for it to operate).
Please report bugs. It's a first release, using the alpha version of VDO.Ninja, so bugs are kind of expected.
{% embed url="https://youtu.be/I12ASNWHPPI" %} https://youtu.be/I12ASNWHPPI {% endembed %}
- What is VDO.Ninja?
- Getting started
- Steve's helper apps & tools
- Electron Capture
- Social Stream Ninja
- Meshcast.io
- Caption.Ninja
- Raspberry.Ninja
- 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
- How Group Chat works
- Video bitrate for push/view links
- Video bitrate in rooms
- 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
- 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 get permanent links
- 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
- 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
- How to set up OBS WHIP output settings
- How to use VDO.Ninja on a website
- Advanced Options (URL Parameters)
- Most common Parameters
- 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
- Camera Parameters
- 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
- Video Bitrate Parameters
- 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
- &order
- &slots
- &fakeguests
- &randomize
- &cover
- &43
- &portrait
- &square
- &forceviewerlandscape
- &animated
- &manual
- &locked
- &poster
- &hideplaybutton
- &motiondetection
- &scene
- &scenetype
- &autoadd
- &hiddenscenebitrate
- &preloadbitrate
- &waitimage
- &waitmessage
- &waittimeout
- 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
- ¬ify
- &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
- 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
- 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
- Guest queuing Parameters
- Meshcast Parameters
- WHIP Parameters
- Mobile Parameters
- API & MIDI Parameters
- TURN & STUN Parameters
- New Parameters in Version 24
- Upcoming Parameters
- Other Parameters
- Releases
- Updates
- Updates - VDO.Ninja
- Updates - Social Stream & Chat Overlay
- 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!
- 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
- Can't share my screen
- Nothing shows up in OBS or it is choppy
- 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
- Can't load camera from non-SSL host
- Camera on macOS doesn't show?
- Can't screen share Adobe Lightroom
- Decklink support?
- Platform specific issues
- Useful Links
- FAQ
- Sponsor ❤
- Edit this documentation
- Redirect
- Redirect 2
description: >- The use cases of VDO.Ninja are many; they go far beyond the original scope of the project
- To allow your mobile device to be used as a wireless remote camera.
- To pull in other people's video and audio for podcasting/broadcast (guest appearances).
- For sharing high-quality and low-latency audio and video across the Internet and within LANs.
- Bring a friend's remote game stream into your OBS and do side-by-side gaming together.
- For VR chat applications.
- For high-quality audio streaming, including remote DJing.
- Wirelessly stream video from any pro camera using just a $10 Raspberry Pi and HDMI adapter.
- For sending any streaming-data peer-to-peer over the Internet in a few lines of code, including JSON.
- To allow you to publish to YouTube with your smartphone even though you don't yet have enough followers to broadcast to YouTube with the YT mobile yet.
- To watch movies with friends, via screen sharing, privately, and with low-enough latency to talk on the phone together while watching it.
- Use as a remote low-latency teleprompter feed.
- Recording remote or local video at high quality without needing any downloads.
- Remotely streaming MIDI device output, such as MIDI keyboards or production control boards.
- Controlling OBS remotely from any computer on the Internet using VDO.Ninja as a p2p bridge.
- Recording remote participates during interviews directly to their own computer; perfect recordings.
- Applying green screens, digital face effects, and other advanced video filters to video streams.
- Real-time closed-captions and transcriptions.
- For whatever other reason you might come up with.
In some cases, the functionality of VDO.Ninja may overlap with existing solutions. However, in its primary function as an ultra-low latency peer-to-peer video bridge to OBS, it has many benefits and advantages over other methods:
- 100% free. There's no downloads required, no personal data collected, and no sign-in needed.
- Compatible with most modern browsers and mobile devices.
- Free support offered via email, Discord, Reddit and numerous written guides.
- Video data is peer-to-peer, so unlike Skype, your video data does not go thru the NSA's spying servers.
- Video can be transferred over a LAN directly, so if using your phone as a webcam, you can crank the bitrates up to 40-mbps if you want, and your bandwidth won't be affected.
- Low latency. I'm talking as low as 30-ms, and normally it never goes higher than 200-ms.
- Adjustable resolutions and video bitrates (1920x1080p60 @ 30-mbps -- or even custom resolutions). 4K @ 30fps is possible, but CPU intensive.
- Control over audio denoise, echo-cancellation, and auto-gain is available, along with custom audio bitrates, and stereo-sound. It is an exceptional tool for podcasters and live streaming DJs.
- You can parameterize many aspects of VDO.Ninja such as total bitrate usage, bitrate per viewer usage, auto-select a device, autostart a session, removing the preview window.
- The interface is open-source, so you can white-label, stylize, tweak, and deploy the website code however you want.
- Reusable invite links, meaning OBS Browser Sources don't need to be recreated or changed once created and shared.
- Playback of video has been tested to work on using Amazon's Firestick's with Silk browser, along with a Tesla's Model 3's infotainment display.
- No plugins needed for OBS -- just drag the selected link into OBS (v25 or newer on PC*) and it auto generates the OBS Browser source with the correct resolution. (*MacOS users need to update to OBS v26.1.2 to access support for VDO.Ninja natively.)
- QR Code support for invite links, which allows for easy ingestion of mobile devices without needing to use the keyboard.
- Browser-based control of OBS scenes.
- No overlays or windows to crop -- VDO.Ninja auto-fills the window and if there is a black border, it becomes a transparent layer.
- Group rooms available with a Director able to control participants, the options presented to them, and even an autojoin experience.
- Group chat rooms have an "auto-mix" mode, making for easy management of dynamic group chat sessions.
- Those in a group-chat can also be split up into individual streams, so the Director has control to treat them like different sources in OBS, switching and mixing as they want.
- Free TURN servers are hosted for VDO.Ninja users, which normally are quite costly, but are kindly subsidized by community sponsors and by Steve, the developer of the application. Sponsor ❤
- Tally-light support is offered when VDO.Ninja is used in conjunction with OBS.
- Group rooms and streams can be password protected and given extra security.
- The group-room director has a "push to talk" capability, along with text-chat being available.
- Support for ISO feed recording via the Director's Control Room.
- With little dependence on video servers, at peak usage hours video quality does not suffer.
- VDO.Ninja is a project of passion, built by creators for creators, and we like to think it shows.
Please find the new link here:
https://docs.vdo.ninja/getting-started/donate
This link has been moved to here: https://docs.vdo.ninja/advanced-settings
These parameters are all on production in v24 of VDO.Ninja
Parameter | Explanation |
---|---|
&pipall | New floating picture in picture mode, so you can pop out the entire video mix as a pinned window overlay |
&pipme | Will cause your self-video preview window to pop out into its own picture in picture |
&nomirror | Disables the default mirror state of the video preview for a guest |
&hangupmessage | Option for a custom hang-up message |
&humb64 | The same as &hangupmessage , except this takes an input as a base64 encoded string |
&welcomeb64 | The same as &welcome , except this takes an input as a base64 encoded string |
&whipoutscale | Scales down the WHIP video output via the URL |
&whipoutscreensharecodec | Option to change codec of the WHIP while screen-sharing |
&whipoutscreensharebitrate | Option to change outbound screen-share video bitrate of WHIP |
&cftoken | Accepts the special token without needing to specify the cloudflare.vdo.ninja part if using &whipout instead |
&clock24 | The same as &clock option, except it uses 24-hour time for the display |
&motiondetection | Does a few things when it detects motion in a video |
&forceviewerlandscape | Keeps all incoming videos oriented (rotated) so that the aspect ratio is always above 1 |
&screen | Replaces the way &queue worked before, where the guest can see/hear the director, but not other guests, until activated |
&hold | Like &queue , except the guest gets a message telling them they need to wait until approved by the director |
&holdwithvideo | Just like &hold , except the director does see the guest's video and audio before the guest is activated |
&nocaptionlabels | Disables showing the names when using the &closedcaptions feature |
&largepreview | Will disable the mini-preview functionality |
&nodirectorvideo | Disables all video playback from room directors |
&nodirectoraudio | Disables all audio playback from room directors |
&retransmit | Will relay the incoming 'chunked' media stream to others connected to you, without transcoding |
&recordmotion | Takes a video snapshot and saves it to disk whenever there is motion detected in a video |
&svc | Useful for publishing to WHIP broadcast servers that support scalable video modes |
e2ee | Support for something called "end to end encryption" using "insertable streams" |
&whitebalance | Lets you manually pre-set the white balance of the camera/webcam |
&exposure | Lets you manually pre-set the exposure of the camera/webcam |
&saturation | Lets you manually pre-set the saturation of the camera/webcam |
&sharpness | Lets you manually pre-set the sharpness of the camera/webcam |
&contrast | Lets you manually pre-set the contrast of the camera/webcam |
&brightness | Lets you manually pre-set the brightness of the camera/webcam |
&forcecontrols | Will try to keep the video controls visible, even if your mouse isn't hovering over the video |
{% hint style="info" %} Version 24 was released on December 19th. All new parameters are here. {% endhint %}
You can use/test these new parameters for Version 25 on vdo.ninja/alpha and/or vdo.ninja/beta:
Parameter | Explanation |
---|---|
updates-vdo.ninja.md | More new parameters |
*ALPHA-ONLY - Only available at https://vdo.ninja/alpha/
**on vdo.ninja/beta and vdo.ninja/alpha
General Option! (&push
, &room
, &view
, &scene
)
Example: &mididelay=1000
Value | Description |
---|---|
(numeric value) | delay in ms |
&mididelay=1000
lets you precisely delay the MIDI play-out from VDO.Ninja to your MIDI device when using &midiin
, irrespective of network latency.
Use case: If you have a remote drum machine, you can have it play out the beat exactly 4-bars ahead, allowing for music jamming types with even high ping delays between locations.
{% content-ref url="../../midi-settings/midi.md" %} midi.md {% endcontent-ref %}
{% content-ref url="../../midi-settings/midiin.md" %} midiin.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&posturl
Example: &postapi=https%3A%2F%2Fwebhook.site%2Fb190f5bf-e4f8-454a-bd51-78b5807df9c1
Value | Description |
---|---|
(custom POST URL) | Data JSON encoded, post URL requires HTTPS+CORS, and the passed URL parameter value needs to be encodedURLComponent |
&postapi
lets you specify a custom POST URL to send events within VDO.Ninja to.
Data JSON encoded, post URL requires HTTPS+CORS, and the passed URL parameter value needs to be encodedURLComponent.
ie: &postapi=https%3A%2F%2Fwebhook.site%2Fb190f5bf-e4f8-454a-bd51-78b5807df9c1
If you don't want to listen for events with the websocket server API I host, you can use this with your own API https server instead and get key events pushed to you that way.
--- description: hotkey features via API and MIDI ---Parameter | Explanation |
---|---|
&api | Remote control API (HTTP-GET / WSS-based) |
&pie | Support for piesocket.com |
&midi | Global hotkey support via MIDI input and more |
&midiin | Allows for receiving of remote MIDI |
&midiout | Broadcast MIDI commands to a remote computer's virtual MIDI device |
&midiremote | Remote MIDI control |
&midichannel | Allows for specifying which midi channel (1 to 16) to listen on |
&mididevice | Allows to specify which midi device (1 and up) selected |
&midioffset | Allows you to set a series of buttons on a MIDI controller to be mute controls for those guests |
&mididelay | Lets you precisely delay the MIDI play-out |
&datamode | Combines a bunch of flags together; no video, no audio, GUI, etc. |
&postapi | Lets you specify a custom POST URL to send events within VDO.Ninja to |
For the most up to date copy of this API endpoint documentation, please go to https://github.com/steveseguin/Companion-Ninja/#readme
For a test sandbox, to easily try out a few of the basic API options via a web dashboard, please go to: https://companion.vdo.ninja/
You can use this API on its own directly, or can use it indirectly via the Bitfocus Companion app /w the VDO.Ninja module. The Companion app can be found here: https://bitfocus.io/companion
While not maintained or controlled by VDO.Ninja, you can find the third-party Bitfocus Companion module for VDO.Ninja here: https://github.com/bitfocus/companion-module-vdo-ninja
Remote control VDO.Ninja using an HTTP or Websocket interface; now Companion compatible.
Support for Companion.Ninja is now built into VDO.Ninja (v19), with a set of hard-coded commands. The available API commands and their related options are listed further down. The index.html file contains sample code with an interactive layer, where you can press buttons to send commands to VDO.Ninja. HTTP and Websocket methods of sending commands are provided as examples. Details of those two methods are also below.
To use the integrated command set and API, just add &api=XXXXXX to the VDO.Ninja link you wish to remotely control, like you would any other parameter. ie: https://vdo.ninja?api=XXXXXX The API value needs to match the value used by Companion Ninja and should be kept private. Then just send commands however you may wish.
Note: This API should also work with the vdo.ninja/beta/mixer?api=XXXXX page.
A fantastic user in the community also has made a BitFocus-Companion module for this VDO.Ninja API. If you wish to avoid doing custom API calls, definitely give the module a go.
https://github.com/bitfocus/companion-module-vdo-ninja
You can also use the Companion Ninja service with your own custom set of commands if desired. You would wrap VDO.Ninja into an IFRAME, and use the parent-window to relay commands to VDO.Ninja and Companion Ninja. You can speak to VDO.Ninja via the IFRAME API in that case, to have access to the more exhaustive set of remote control options.
An example of this approach can be found here:
https://github.com/steveseguin/Companion-Ninja/blob/main/iframe_api_customizable_example.html
Also note, the IFRAME API used by VDO.Ninja (v19.1) is also largely backwards compatible with the Companion Ninja API. You can find the IFRAME developer sandbox here: https://vdo.ninja/beta/iframe to get a sense of what is available.
The API is likely to change over time, as this is still early days and user feedback with direct how things evolve. More commands added on request.
HTTP/GET API (/w SSL)
The HTTP API uses GET-requests (not POST/PUT), and is structured in a way to be compatible with existing hotkey control software.
https://api.vdo.ninja/{apiID}/{action}/{target}/{value}
or
https://api.vdo.ninja/{apiID}/{action}/{value}
or
https://api.vdo.ninja/{apiID}/{action}
Any field can be replaced with "null", if no value is being passed to it. Double slashes will cause issues though, so avoid those.
Websocket API
If using the Websocket API, this accepts JSON-based commands
connect to: wss://api.vdo.ninja:443
On connection, send: {"join": $apiID }
, where $apiID
is your api ID.
- be sure to stringify objects as JSON before sending over the websocket connection. ie:
JSON.stringify(object)
Once joined, you can then issue commands at will, such as this object
{
"action":"reload",
"value": "true",
"target" "null"
}
Be sure to implement reconnection logic with the websocket connection, as it will timeout every minute or so by default otherwise. You will need to rejoin after a timeout.
API Commands
The API and its commands are currently in a DRAFT form, and as such, may/will undergo change.
Action | Target | Value | Details |
---|---|---|---|
speaker | null | true | Unmute the Local Speaker |
speaker | null | false | Mute the Local Speaker |
speaker | null | toggle | Toggle the state of the local Speaker |
mic | null | true | Unmute the local Microphone |
mic | null | false | Mute the local Microphone |
mic | null | toggle | Toggle the state of the local Microphone |
camera | null | true | Unmute local Camera |
camera | null | false | Mute local Camera |
camera | null | toggle | Toggle the state of the local Camera |
volume | null | true | Mutes all local audio tracks by setting the volume to 0% |
volume | null | false | Sets the playback volume of all audio tracks to 100% |
volume | null | {integer value between 0 and 100} | Sets the playback volume of all local playback audio |
sendChat | null | {some chat message} | Sends a chat message to everyone connected. Better suited for the websocket API over the HTTP one. |
record | null | true | Start recording the local video stream to disk; will probably create a popup currently |
record | null | false | Stops recording the local video stream |
reload | null | null | Reload the current page |
hangup | null | null | Hang up the current connection. For the director, this just stops the mic and camera mainly. |
bitrate | null | true | Unlock/reset bitrate of all currently incoming video |
bitrate | null | false | Pause all currently incoming video streams (bitrate to 0) |
bitrate | null | {some integer} | Set video bitrate of all incoming video streams to target bitrate in kilobits per second. |
panning | null | true | Centers the pan |
panning | null | false | Centers the pan |
panning | null | {an integer between 0 and 180} | Sets the stereo panning of all incoming audio streams; left to right, with 90 being center. |
togglehand | null | null | Toggles whether your hand is raised or not |
togglescreenshare | null | null | Toggles screen sharing on or off; will still ask you to select the screen though. |
forceKeyframe | null | null | Forces the publisher of a stream to issue keyframes to all viewers; "rainbow puke fix" |
group | null | {an integer between 1 and 8} | Toggle the director of a room in/out of a specified group room (vdo.ninja +v22). Useful for Comms app, etc |
joinGroup | null | {an integer between 1 and 8} | Have the director of a room join a specified group room (vdo.ninja +v22.12) |
leaveGroup | null | {an integer between 1 and 8} | Have the director of a room leave a specified group room (vdo.ninja +v22.12) |
viewGroup | null | {an integer between 1 and 8} | Toggle the director of a room's preview of a specific group (vdo.ninja +v22). Useful for Comms app, etc |
joinViewGroup | null | {an integer between 1 and 8} | Have the director of a room preview a specific group (vdo.ninja +v22.12) |
leaveViewGroup | null | {an integer between 1 and 8} | Have the director of a room un-preview a specific group (vdo.ninja +v22.12) |
getDetails | null | null | Will return a JSON object containing detailed state of everything. If a director, this will contain guest-state as seen by the director. |
nextSlide | null | null | Next PowerPoint slide. See https://github.com/steveseguin/powerpoint\_remote for setup (vdo.ninja +v22.12) |
prevSlide | null | null | Previous PowerPoint slide. See https://github.com/steveseguin/powerpoint\_remote for setup (vdo.ninja +v22.12) |
soloVideo | null | toggle | Toggle the Highlight of video for all guests (if a director) (vdo.ninja +v23) |
soloVideo | null | true | Highlight your video for all guests (if a director) (vdo.ninja +v23) |
soloVideo | null | false | Un-highlight your video for all guests (if a director) (vdo.ninja +v23) |
stopRoomTimer | null | null | Stop the timer for everyone in the room (if a director) (vdo.ninja +v23.9) |
startRoomTimer | null | Integer to count down from | Value to count down from is in seconds in the room; applies to everyone in a room (if a director) (vdo.ninja +v23.9) |
PauseRoomTimer | null | null | Pause the timer for all everyone in the room (if a director) (vdo.ninja +v23.9) |
getGuestList | null | null | Returns an object containing the guest slots positional values, so "1", "2", etc. Each is a key that contains the stream ID and label for that guest as well. |
layout | null | {** see below}
Custom layout switching **
You can create an array of layouts, set them via the URL parameters in VDO.Ninja, and then switch between them remotely using the API.
The value passed to the API can either be a number, representing the position in the array of the layout you want to activate, or it can be a single layout object.
{action: "layout", value:3}
or {action: "layout", value:[{"x":0,"y":0,"w":100,"h":100,"slot":0}]}
layout 0 is the auto mixer
layout 1 is the first custom layout
layout 2 is the second custom layout
etc
If using the Mixer App, the layout objects are controlled via the mixer app itself, so you don't need to pass an object in that case to the URL.
?layouts=[[{"x":0,"y":0,"w":100,"h":100,"slot":0}],[{"x":0,"y":0,"w":100,"h":100,"slot":1}],[{"x":0,"y":0,"w":100,"h":100,"slot":2}],[{"x":0,"y":0,"w":100,"h":100,"slot":3}],[{"x":0,"y":0,"w":50,"h":100,"c":false,"slot":0},{"x":50,"y":0,"w":50,"h":100,"c":false,"slot":1}],[{"x":0,"y":0,"w":100,"h":100,"z":0,"c":false,"slot":1},{"x":70,"y":70,"w":30,"h":30,"z":1,"c":true,"slot":0}],[{"x":0,"y":0,"w":50,"h":50,"c":true,"slot":0},{"x":50,"y":0,"w":50,"h":50,"c":true,"slot":1},{"x":0,"y":50,"w":50,"h":50,"c":true,"slot":2},{"x":50,"y":50,"w":50,"h":50,"c":true,"slot":3}],[{"x":0,"y":16.667,"w":66.667,"h":66.667,"c":true,"slot":0},{"x":66.667,"y":0,"w":33.333,"h":33.333,"c":true,"slot":1},{"x":66.667,"y":33.333,"w":33.333,"h":33.333,"c":true,"slot":2},{"x":66.667,"y":66.667,"w":33.333,"h":33.333,"c":true,"slot":3}]]
Some of these layout features are only available with Version 22 of VDO.Ninja; specifically the &layouts=
parameter is available on v22.5 or newer only.
See for details and better documentation on this layout function:
Commands that target remote guests as a director (available on VDO.Ninja v19)
The guest slot (1 to 99) or the guests's stream ID can be used as a target.
Currently toggling is primarily available for options; on/off absolute value options will be coming soon.
Action | Target | Value | Details |
---|---|---|---|
forward | {guest slot or stream ID} | {destination room} | Transfer guest to specified room |
addScene | {guest slot or stream ID} | {scene ID; 0 to 8, or an active custom scene name} | Toggle guest in/out of specified scene |
muteScene | {guest slot or stream ID} | {scene ID; 0 to 8, or an active custom scene name} | Toggle guest's mic audio in scenes |
group | {guest slot or stream ID} | {group ID; 1 to 8} | Toggle guest in/out of specified group; default group 1 |
mic | {guest slot or stream ID} | null | Toggle the mic of a specific guest |
hangup | {guest slot or stream ID} | null | Hangup a specific guest |
soloChat | {guest slot or stream ID} | null | Toggle solo chat with a specific guest |
soloChatBidirectional | {guest slot or stream ID} | null | Toggle two-way solo chat with a specific guest |
speaker | {guest slot or stream ID} | null | Toggle speaker with a specific guest |
display | {guest slot or stream ID} | null | Toggle whether a specific guest can see any video or not |
sendDirectorChat | {guest slot or stream ID} | {some chat message} | Sents a chat message to a guest and overlays it on their screen |
forceKeyframe | {guest slot or stream ID} | null | Trigger a keyframe for active scenes, wrt to a guest; helps resolve rainbow puke |
soloVideo | {guest slot or stream ID} | null | Toggle whether a video is highlighted everywhere |
volume | {guest slot or stream ID} | {0 to 100} | Set the microphone volume of a specific remote guest |
stopRoomTimer | {guest slot or stream ID} | null | Stop the timer for the specific guest (+v23.9) |
startRoomTimer | {guest slot or stream ID} | Integer to count down from | Value to count down from is in seconds (+v23.9) |
PauseRoomTimer | {guest slot or stream ID} | null | Pause the timer for the specific guest (+v23.9) |
Start with Version 22 of VDO.Ninja, the API requests will have a response reflecting the state of the request.
For example, if toggling a mic of a guest, the response of the HTTP API request will be true
or false
, based on whether the mic is now muted or not. If the request is an object, such as when using getDetails
, you'll get a JSON response instead of basic text. There's also getGuestList
, which can be useful for getting a set of possible guest slot positional values, along with its corresponding stream ID and label.
Basic text/word responses are such things as true
, false
, null
, fail
, {somevalue
}, or timeout
. Timeout occurs if there's no listener or no response to a request; the system will stop the callback and fail to a timeout after 1-second.
If the request was made via WebSockets, instead of the HTTP request, you'll get a JSON object back that contains the same data, along with the original request, including custom data fields. These custom data fields, such as data.cid = 3124
, can be used to link requests with the callback, if precision with the requests is needed.
There is no time-out when using WebSockets; the callback can happen seconds or minutes later even, although normally a response should be expected in under a second as well.
Sender-Side Option! (&push
)
&audiohint
&audiocontenttype
&audiocontent
Example: &audiocontenthint=music
Value | Description |
---|---|
music |
seems to be a fixed bitrate of 32-kbps sent out by default |
speech |
bitrate is variable, using less bandwidth when not speaking |
There are two options for &audiocontenthint
: speech
and music
. No idea what it does exactly, but when using music
there seems to be a fixed bitrate of 32-kbps sent out by default, where as with speech
it is variable, using less bandwidth when not speaking.
{% hint style="warning" %} This parameter has been tested on Chrome, but other browsers may vary in behavior. Safari seems to just ignore things, for example. {% endhint %}
{% content-ref url="../view-parameters/vbr.md" %} vbr.md {% endcontent-ref %}
{% content-ref url="../video-parameters/and-contenthint.md" %} and-contenthint.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&g
&gain
Example: &audiogain=80
Value | Description |
---|---|
0 | mutes the microphone so that only the Director can unmute it; the guest cannot unmute. |
100 | full volume - default |
(integer value) | value will be applied as a percentage. |
Adding &audiogain=50
to a source link sets the audio gain of the source to 50%.
- Can be used to have a guest muted by default when joining a room (
&audiogain=0
). - Can be remotely controlled by the Director if in a room; the guest cannot unmute themselves.
- Only applies to the first audio-source selected by a guest, if there is more than one selected.
- If audio processing is on, then this should be available by default for the director to remotely control.
- The gain function will NOT work if web-audio node processing cannot be enabled.
In Version 22 you can control the audio gain in the Audio Settings. If you want the guests to be able to change it by themselves, you can add &mediasettings
to the guests' link.
{% hint style="warning" %} Enables the audio processing pipeline. {% endhint %}
{% content-ref url="and-volume.md" %} and-volume.md {% endcontent-ref %}
{% content-ref url="../../source-settings/autogain.md" %} autogain.md {% endcontent-ref %}
{% content-ref url="../../source-settings/and-limiter.md" %} and-limiter.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&am
Example: &automute=2
Value | Description |
---|---|
(no value given) | will auto mute the microphone of a guest when not loaded in an active OBS scene |
2 | will mute it everywhere, while the default will still allow the director to speak to the guest, even if not in a scene |
&automute
will auto mute the microphone of a guest when not loaded in an active OBS scene. Useful for perhaps limiting the discussion in a group chat to those on air.
&automute=2
will mute it everywhere, while the default will still allow the director to speak to the guest, even if not in a scene.
This is a guest-side URL parameter; you may want to apply it to all guests.
Required quite a bit of code reworking; error reporting is on in the console, so please report issues. Feedback also welcomed.
{% content-ref url="../../source-settings/and-mute.md" %} and-mute.md {% endcontent-ref %}
{% content-ref url="and-audiogain.md" %} and-audiogain.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
Example: &playchannel=1
Value | Description |
---|---|
1 | Will play the left audio channel only |
2 | Will play the right audio channel only |
3-6 | Will play the selected channel |
&playchannel
will play either the left or right audio stream-only for an incoming stereo stream.
It will play back the selected channel as mono audio, dropping other channels from the playback. &playchannel=1
is left channel; 2
is right; and if multi channel works for you, then you can target 6 different channels.
This is useful if you wanted to capture the left and right audio channels of a remote guest in OBS in different browser sources, without having to do any fancy audio routing on the studio side.
Both left and right audio channels are still sent; it's just during local playback that the non-selected channels are dropped, so it's not as efficient as local routing, nor will both channel be in exact sync anymore either.
This will not currently work in conjunction with &panning
of &channeloffset
; and will override those options.
Example usage: https://vdo.ninja/?view=XXXXXXXX&stereo&playchannel=1
{% content-ref url="../view-parameters/and-channels.md" %} and-channels.md {% endcontent-ref %}
{% content-ref url="and-inputchannels.md" %} and-inputchannels.md {% endcontent-ref %}
{% content-ref url="../view-parameters/and-channels.md" %} and-channels.md {% endcontent-ref %}
description: >- Will try to "distort" your microphone's output audio, making your voice a bit anonymous
Sender-Side Option! (&push
)
&distort
as a URL parameter for the sender's side will try to "distort" your microphone's output audio, making your voice a bit anonymous.
https://vdo.ninja/?push&webcam&distort
description: >- Audio capture device to select N-number of audio channels; force mono or stereo capture
Sender-Side Option! (&push
)
&channelcount
&ac
Example: &inputchannels=6
Value | Description |
---|---|
1 |
Audio capture device set to mono; 1 channel |
2 |
Audio capture device set to 2 channels |
6 |
Audio capture device set to 6 channels |
(integer value X) | Audio capture device set to X channels |
&inputchannels=N
tells the audio capture device explicitly to select N-number of audio channels.
Setting &stereo=0
will set &inputchannels=1
by default.
If using &proaudio
you want want to disable stereo-audio capture, particularly if you are using an XLR to USB microphone preamp that has two channels, but only one microphone connected.
For example, if a guest joins and you can only hear them in the left or right channel, either add &mono
to the view-link or add &inputchannels=1
to the respective guest invite-link.
If looking for a memorable parameter to set a guest's audio input to mono (1-channel), &monomic
is the same as &inputchannels=1
. This was added in VDO.Ninja v22.
{% content-ref url="and-monomic.md" %} and-monomic.md {% endcontent-ref %}
{% content-ref url="../view-parameters/mono.md" %} mono.md {% endcontent-ref %}
{% content-ref url="../../general-settings/stereo.md" %} stereo.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&channelcount=1
&ac=1
&inputchannels=1
&monomic
sets a guest's audio input to mono (1-channel). &monomic
is the same as &inputchannels=1
.
There is &mono
to set the audio output to mono on the viewer's side.
{% content-ref url="and-inputchannels.md" %} and-inputchannels.md {% endcontent-ref %}
{% content-ref url="../view-parameters/mono.md" %} mono.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&nodirectoraudio
is just like &noaudio
(disables all audio playback on the local computer), except it only applies to incoming connections from room directors. So, if your are using the Mixer App with OBS, but you want to exclude the audio of yourself from the OBS, this potentially could be an easy way to do that.
{% content-ref url="../view-parameters/noaudio.md" %} noaudio.md {% endcontent-ref %}
{% content-ref url="../video-parameters/and-nodirectorvideo.md" %} and-nodirectorvideo.md {% endcontent-ref %}
{% content-ref url="../../viewers-settings/director.md" %} director.md {% endcontent-ref %}
{% content-ref url="../../steves-helper-apps/mixer-app.md" %} mixer-app.md {% endcontent-ref %}
description: >- Lets you tweak the &noisegate variables, making it more or less aggressive as needed
Sender-Side Option! (&push
)
Example: &noisegatesettings=10,25,3000
Value | Description |
---|---|
(TargetGain,Threshold,GateOpenPosition) | see Details for more information |
10,25,3000 |
example |
&noisegatesettings
is used in conjunction with &noisegate
. This feature lets you tweak the noise-gate's variables, making it more or less aggressive as needed.
It takes a comma separated list:
- First value is target volume (0 to 100), although 0 to 40 is probably the recommended range here.
- Since how we perceive loudness isn't linear, to have the audio become inaudible, you'll want to set this to 0 to 3. Setting it to 10 for example will leave it still quite audible, but just dampened.
- Second value is the threshold value where the gate is triggered if below it. ~ 100 is loudly speaking, ~ 20 is light background noise levels, and under 5 is quiet background levels.
- Third value is how 'sticky' the gate-open position is, in milliseconds. Having this set to a few seconds should prevent someone from being cut off while speaking or if taking a short pause.
- You may want to try a value of 10 to 300 for this third value, if just testing or want a sharper cut off.
Example:
https://vdo.ninja/?noisegate&noisegatesettings=10,25,3000
{% content-ref url="../../source-settings/noisegate.md" %} noisegate.md {% endcontent-ref %}
description: >- Improves the audio quality, changes default audio settings and sets the audio mode to stereo
General Option! (&push
, &room
, &view
, &scene
)
&stereo
&s
Example: &proaudio=1
Value | Description |
---|---|
(no value given) | it behaves like 3 or 1, depending on if you are a guest or not |
0 | will try to down-mix your mic to mono. Does not enable any pro-audio settings |
1 | enables it for both push and view (if used on both links) and switches off aec/denoise/autogain settings |
2 | enables it just for viewing requests and not publishing requests |
3 | enables it for just publishing requests and not viewing requests |
4 | enables 5.1-multichannel audio support (Experimental and may require a Chrome flag to be set) |
5 | this is the default if nothing is set. It behaves like 3 or 1, depending on if you are a guest or not |
6 | solely just enables stereo for both in/out |
Adding &proaudio
to the URL will apply audio-specific setting presets. For inbound audio streams, it can be used to increase the audio bitrate from 32-kbps to 256-kbps. For outbound streams, it will disable echo-cancellation and noise-reduction. When applied to both the outbound and inbound sides of an audio stream, it will also enable stereo audio if available.
There are a variety of different modes that apply different combination of presets. You can also override any preset with other URL parameters, such as &audiobitrate
, &outboundaudiobitrate
, and &aec=1
.
If using a microphone, wearing headphones is strongly recommended if using this parameter, along with knowledge of correctly setting your microphone gain settings. Echo and feedback issues can occur if this option is used incorrectly.
When using this option in a group room, you can't simply just apply this URL option to the director and have it apply to all guests. You will need to add the flag to each guest and to each scene-link to enable the pro-audio stereo mode. Depending on the value you pass to the URL parameter, you will get slightly different outcomes.
There is a director's room toggle for guest's invite link and for scene links:
&stereo
and &proaudio
currently do the same thing, so they are just aliases of each other. When used, they can be used to setup the audio transfer pipeline to allow for unprocessed, high-bitrate, stereo audio.
Use of this option is generally for advanced users who understand the consequences of enabling this. High-quality audio can cause audio clicking, reduced video quality, feedback issues, low volume levels, and higher background noise levels.
For stereo-channel support to work, you will want both the viewer AND the publisher of the stream to have the respective &proaudio
flag add to their URL.
You can customize things further using &aec
, &ag
, &dn
, &ab
and &mono
. These flags will override the presets applied by the &proaudio
flag. Please note, depending on your browser, enabling &aec
, &ag
, or &dn
can force disable stereo audio.
The most powerful mode is proaudio=1
, which if enabled:
- Turns off audio normalization or auto-gain when publishing (
&push
) - Turns off noise-cancellation when publishing
- Turns off echo-cancellation when publishing
- Enables higher audio bitrate playback, up to 256-kbps, when listening (
&view
)
If the parameter is used, but left without a value, it is treated as a special case (either 1 or 3). Please see follow link for more info:
Option | alias | aec | autogain | denoise | stereo playback | stereo output | default ab in | max ab out | limited ab in | cbr |
---|---|---|---|---|---|---|---|---|---|---|
&proaudio=0 | off | on | on | on | off | no | 32 | 510 | 510 | no |
&proaudio=1 | both | off | off | off | on | yes | 256 | 510 | 510 | yes |
&proaudio=2 | in | on | on | on | on | no | 256 | 510 | 510 | yes |
&proaudio=3 | out | off | off | off | off | yes | 32 | 510 | 510 | no |
&proaudio=4 | multi | off | off | off | on (5.1) | yes | 256 | 510 | 510 | yes |
The default mode when &proaudio
is used alone is &proaudio=5
, which acts like either &proaudio=3
or &proaudio=1
, depending on whether the link its applied to is a room guest or not. This option will make the most sense for most users.
Option | Context | alias | aec | autogain | denoise | stereo playback | stereo output | default ab in | max ab out | limited ab in | cbr |
---|---|---|---|---|---|---|---|---|---|---|---|
&proaudio=5 |
Regular/OBS | 5 | off | off | off | on | yes | 256 | 510 | 510 | yes |
&proaudio=5 |
Director | 5 | off | off | off | on | yes | 32 | 510 | 510 | no |
&proaudio=5 |
Room Guest | 5 | off | off | off | off | yes | 32 | 510 | 510 | no |
Option | alias | aec | autogain | denoise | stereo playback | stereo output | default ab in | max ab out | limited ab in | cbr |
---|---|---|---|---|---|---|---|---|---|---|
iOS devices | on | on | on | off | off | 32 | 32 | 32 | no |
Just for reference, the audio codec used by VDO.Ninja is OPUS (48khz), which can provide high-fidelity music transfer when the audio bitrate is set to 80-kbps per channel or higher. The default audio bitrate used is 32-kbps VBR, which is sufficient for most voice applications. Increasing the audio bitrate to a near-lossless 500-kbps or something may end up causing more problems than anything, but that is supported if needed.
If you want to use the &proaudio
parameter but wish the output to still be mono (1-channel), there's some options.
&inputchannels=1
or&monomic
can be used on the sender's side, which will force their audio-capture device (microphone) to only capture in mono.&mono
can be added to the viewer's side, which will try to playback incoming audio as mono.- If using OBS, in the audio settings, you can set the browser-source's audio to be mono.
{% content-ref url="../view-parameters/audiobitrate.md" %} audiobitrate.md {% endcontent-ref %}
{% content-ref url="../../source-settings/and-outboundaudiobitrate.md" %} and-outboundaudiobitrate.md {% endcontent-ref %}
{% content-ref url="../../newly-added-parameters/and-screensharestereo.md" %} and-screensharestereo.md {% endcontent-ref %}
Viewer-Side Option! (&scene
, &room
, &view
, &solo
)
&vol
Example: &volume=50
Value | Description |
---|---|
(0-100) | audio playback volume in percent |
&volume
can set the 'default' playback volume for all video elements in VDO.Ninja. Currently the range is 0 to 100 and other volume commands or mute states may override this value. The default is 100.
&volume=50
{% content-ref url="and-audiogain.md" %} and-audiogain.md {% endcontent-ref %}
{% content-ref url="../../source-settings/autogain.md" %} autogain.md {% endcontent-ref %}
{% content-ref url="and-volumecontrol.md" %} and-volumecontrol.md {% endcontent-ref %}
Viewer-Side Option! (&scene
, &room
, &view
, &solo
)
&volumecontrols
&vc
&volumecontrol
shows a dedicated local audio-volume control bar for canvas or image elements. Video elements already have a control-bar with volume, so I don't show it there currently.
The Comms app is a good demonstrator of the feature @vdo.ninja/alpha/comms.
{% content-ref url="and-volume.md" %} and-volume.md {% endcontent-ref %}
{% content-ref url="and-audiogain.md" %} and-audiogain.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
, &solo
)
Example: &audiocodec=opus
Value | Description |
---|---|
opus |
default; selects audio codec opus |
red |
selects audio codec red |
pcmu |
selects audio codec pcmu |
pcma |
selects audio codec pcma |
isac |
selects audio codec isac |
g722 |
selects audio codec g722 |
pcm |
selects audio codec pcm |
&audiocodec
on the viewer side can let you specify the audio codec; opus
(default), pcmu
, pcma
, isac
, g722
, red
and pcm
.
&audiocodec=red
is pretty much like sending two opus streams, with one as a backup in case of packet loss; support in Chromium 97 and up, but the only way I can so far tell that it is working is to check if the audio bitrate has doubled.
When using &proaudio
, &stereo
, or higher than &audiobitrate=216
with this, the resulting bitrate may not actually double. I don't quite understand what's going on here, if its still working or not, so to be safe when using &proaudio
or &stereo
, along with &audiocodec=red
, I set the bitrate to 216 by default, which will then result in a sending bitrate of around 440-kbps.
I've tried to enable RED-mode to work with PCM audio, but so far it will only work with OPUS audio.
&audiocodec=pcm
now will support 48khz and 44.1khz mono playback (48khz default), and if &stereo
is used, it changes to two-channel stereo 32khz.
The existing &samplerate=44100
option can lower the sample rate of this pcm mode (down to 8khz even), and hence the resulting audio bitrate. Since PCM is raw, &audiobitrate
won't work, so expect 550 to 1200-kbps in just audio bitrates per viewer.
There may be clicking when using PCM mode (L16) if you are on a bad connection, as PCM doesn't have much in the way of error correction. You'll need to address this yourself probably with post-processing if any issue.
In the near future you'll be able to send PCM audio via &chunked
mode, which will guarantees delivery of all packets sent, however there may be buffering issues if your connection can't keep up with bandwidth requirements.
Currently &chunked
mode does work with OPUS-audio though; please provide feedback and requests if you use it. Chunked mode does not support WHIP/WHEP or Meshcast.
{% content-ref url="../view-parameters/codec.md" %} codec.md {% endcontent-ref %}
{% content-ref url="minptime-3.md" %} minptime-3.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
, &solo
)
&usedtx
Using &dtx
will turn off the audio encoder automatically when no little to no sound is detected. The VDO.Ninja default uses a dynamic audio bitrate mode (&vbr
), but using &dtx
takes things to the next level. It might be useful as a very mild noise-gate I suppose?
{% content-ref url="../view-parameters/vbr.md" %} vbr.md {% endcontent-ref %}
{% content-ref url="minptime-3.md" %} minptime-3.md {% endcontent-ref %}
{% content-ref url="minptime-1.md" %} minptime-1.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
, &solo
)
&nofec
on the viewer side can disable audio forward error correction (FEC). I show the audio codec now used in the stats, along with whether FEC is on or not (on by default).
They are separated in three groups: general options (push and view), source side (push) options and viewer side (view) options.
You can add them to both, source (&push
) and viewer (&view
, &scene
or &solo
) sides.
Parameter | Explanation |
---|---|
&proaudio | Improves the audio quality, changes default audio settings and sets the audio mode to stereo |
&stereo | Sets the audio mode to stereo and changes default audio settings to improve audio quality |
&mutespeaker | Auto mutes the speaker |
&deafen | Audio playback is muted |
&noaudioprocessing | Disables all webaudio audio-processing pipelines |
You have to add them to the source side (&push
).
Parameter | Explanation |
---|---|
&audiodevice | Pre-configures the selected audio device |
&echocancellation | Automatic echo-cancellation is ON or OFF |
&audiogain | Applies a gain multiplier (as a percentage) to the local microphone |
&autogain | Sets whether audio auto-normalization is ON or OFF |
&compressor | Applies a generic audio compressor to the local microphone |
&denoise | Turn audio noise reduction filter ON or OFF |
&distort | Will try to "distort" your microphone's output audio, making your voice a bit anonymous |
&equalizer | Provides access to a generic audio equalizer that can be applied to the local microphone |
&limiter | Applies a generic audio limiter to the local microphone |
&lowcut | Adds a low-cut filter |
&noisegate | Lowers your mic volume to 10% of its current value based on volume-level activity |
&noisegatesettings | Lets you tweak the &noisegate variables, making it more or less aggressive as needed |
&audiocontenthint | =music fixed bitrate; =speech bitrate is variable |
&audiolatency | Adds an audio-latency to the published audio stream |
&micdelay | Delays the microphone by specified time in ms |
&mute | Starts with the microphone muted by default |
&automute | Will mute the microphone of a guest when not loaded in an active OBS scene |
&outboundaudiobitrate | Target audio bitrate and max bitrate for outgoing audio streams |
&inputchannels | Audio capture device to select N-number of audio channels |
&monomic | Sets a guest's audio input to mono (1-channel) |
You have to add them to the viewer side (&view
, &scene
or &solo
).
Parameter | Explanation |
---|---|
&audiooutput | Like &sink , but selects the audio output device |
&sink | Outputs the audio to the specified audio output device, rather than the default |
&volume | Sets the 'default' playback volume for all video elements |
&volumecontrol | Shows a dedicated local audio-volume control bar for canvas or image elements |
&audiobitrate | Manually sets the audio bitrate in kbps |
&vbr | Sets the audio bitrate to be variable, instead of constant |
&mono | Has the inbound audio playback as mono audio |
&noaudio | Delivers video only streams; audio playback is disabled |
&nodirectoraudio * | Disables all audio playback from room directors |
&panning | Pans the outgoing audio left or right, allowing for spatial audio group chats |
&sync | Sets an offset (in ms) for the automatic audio sync fix node |
&samplerate | Audio playback sample-rate, in hz |
&channels | Specifies the number of output audio channels you wish to mix up or down to |
&channeloffset | Shifts audio channels 0 and 1 up channels, based on the offset value |
&playchannel | Will play either the left or right audio stream-only for an incoming stereo stream |
&ptime | Audio packet size |
&maxptime | Maximum packet size of audio |
&minptime | Minimum packet size of audio |
&audiocodec | Lets you specify the audio codec |
&dtx | Turns off the audio encoder automatically when no little to no sound is detected |
&nofec | Disables FEC (audio forward error correction) |
*NEW IN VERSION 24
description: >- Will try to keep the video controls visible, even if your mouse isn't hovering over the video
General Option! (&push
, &room
, &view
, &scene
)
&forcecontrols
is experimental, but it will try to keep the video controls visible, even if your mouse isn't hovering over the video.
{% hint style="info" %} The VDO.Ninja tab/window still needs to be 'active' however, for this to work; changing focus to another tab will stop it. {% endhint %}
{% hint style="warning" %} Only works really for Chrome/Chromium on desktop; not Firefox, etc. {% endhint %}
{% content-ref url="../newly-added-parameters/and-videocontrols.md" %} and-videocontrols.md {% endcontent-ref %}
{% content-ref url="../settings-parameters/and-nocontrols.md" %} and-nocontrols.md {% endcontent-ref %}
Parameter | Explanation |
---|---|
&autohide | Auto-hides the control bar after a few moments of the mouse being idle |
&controlbarspace | Forces the user control bar to be in its own dedicated space |
&nosettings | Disables the local settings button |
&nomicbutton | Disables the mic button; guests can't mute audio |
&nospeakerbutton | Hides the speaker button |
&novideobutton | Disables the video button; guests can't mute video |
&nofileshare | Hides the ability for a guest to upload a file |
&screensharebutton | Forces the screen-share button to appear for guests |
&nohangupbutton | Hides the hang-up button |
&chatbutton | Shows or hides the chat button |
&bigbutton | Makes the microphone mute button a lot bigger |
&fullscreenbutton | Adds a full-screen button to the control bar |
&nowebsite | Disables IFrames from loading, such as remotely shared websites by another guest or director |
&hands | Enables a "Raise Hand" button for guests |
While you can position the control bar by dragging it around, you can also set it's initial position with the use of a custom CSS parameter. For example:
&cssb64=I3N1YkNvbnRyb2xCdXR0b25ze3RyYW5zZm9ybTp0cmFuc2xhdGUoMHB4LCBjYWxjKC0xMDB2aCArIDkwcHgpKSFpbXBvcnRhbnR9Ow
The above is a base64 encoded version of the following CSS, which positions the control bar at the top by default. Base64 encoding allows us to use stylings safely as a URL parameter.
#subControlButtons{transform:translate(0px, calc(-100vh + 90px))!important};
Parameter | Explanation |
---|---|
&videocontrols | Shows the video control bar |
&nocontrols | Will force hide the video control bar |
&forcecontrols * | Will try to keep the video controls visible, even if your mouse isn't hovering over the video |
*NEW IN VERSION 24
Sender-Side Option! (&push
)
Example: &brightness=128
Value | Description |
---|---|
(integer value; 1 to 255 ) | brightness of the camera |
Lets you manually pre-set the brightness of the camera/webcam:
It will normally take an integer value in the range of 1
to 255
, at least for a Logitech webcam, but will vary based on the camera / device you are using.
VDO.Ninja already tries to auto-save camera settings for android devices that support video settings, but for desktop browsers, it does not. Using these new values though you can manually set things to auto-configure as you want.
These settings will apply to ALL video devices though, not just a specific one. If a setting isn't supported by your camera or browser, it will just fail quietly, and not apply. You'll see an error in the console log though.\
{% hint style="warning" %}
- Firefox and Safari may not support this feature.
- Not all cameras/smartphones will support this option {% endhint %}
You can check the video settings menu as to whether a device supports a certain feature or what value ranges are support; you can also check it out here https://vdo.ninja/supports.
{% content-ref url="./" %} . {% endcontent-ref %}
Sender-Side Option! (&push
)
Example: &contrast=128
Value | Description |
---|---|
(integer value; 1 to 255 ) | contrast of the camera |
Lets you manually pre-set the contrast of the camera/webcam:
It will normally take an integer value in the range of 1
to 255
, at least for a Logitech webcam, but will vary based on the camera / device you are using.
VDO.Ninja already tries to auto-save camera settings for android devices that support video settings, but for desktop browsers, it does not. Using these new values though you can manually set things to auto-configure as you want.
These settings will apply to ALL video devices though, not just a specific one. If a setting isn't supported by your camera or browser, it will just fail quietly, and not apply. You'll see an error in the console log though.\
{% hint style="warning" %}
- Firefox and Safari may not support this feature.
- Not all cameras/smartphones will support this option {% endhint %}
You can check the video settings menu as to whether a device supports a certain feature or what value ranges are support; you can also check it out here https://vdo.ninja/supports.
{% content-ref url="./" %} . {% endcontent-ref %}
Sender-Side Option! (&push
)
Example: &exposure=128
Value | Description |
---|---|
(integer value; 1 to 255 ) | exposure of the camera for a Logitech webcam |
(integer value; 1 to 8000 ) | exposure of the camera for a Pixel 4a Android smartphone |
Lets you manually pre-set the exposure of the camera/webcam:
It will normally take an integer value in the range of 1
to 255
, at least for a Logitech webcam, but will vary based on the camera / device you are using.
VDO.Ninja already tries to auto-save camera settings for android devices that support video settings, but for desktop browsers, it does not. Using these new values though you can manually set things to auto-configure as you want.
These settings will apply to ALL video devices though, not just a specific one. If a setting isn't supported by your camera or browser, it will just fail quietly, and not apply. You'll see an error in the console log though.\
{% hint style="warning" %}
- Firefox and Safari may not support this feature.
- Not all cameras/smartphones will support this option {% endhint %}
You can check the video settings menu as to whether a device supports a certain feature or what value ranges are support; you can also check it out here https://vdo.ninja/supports.
{% content-ref url="./" %} . {% endcontent-ref %}
Sender-Side Option! (&push
)
Example: &saturation=128
Value | Description |
---|---|
(integer value; 1 to 255 ) | saturation of the camera for a Logitech camera |
Lets you manually pre-set the saturation of the camera/webcam:
It will normally take an integer value in the range of 1
to 255
, at least for a Logitech webcam, but will vary based on the camera / device you are using.
VDO.Ninja already tries to auto-save camera settings for android devices that support video settings, but for desktop browsers, it does not. Using these new values though you can manually set things to auto-configure as you want.
These settings will apply to ALL video devices though, not just a specific one. If a setting isn't supported by your camera or browser, it will just fail quietly, and not apply. You'll see an error in the console log though.\
{% hint style="warning" %}
- Firefox and Safari may not support this feature.
- Not all cameras/smartphones will support this option {% endhint %}
You can check the video settings menu as to whether a device supports a certain feature or what value ranges are support; you can also check it out here https://vdo.ninja/supports.
{% content-ref url="./" %} . {% endcontent-ref %}
Sender-Side Option! (&push
)
Example: &sharpness=128
Value | Description |
---|---|
(integer value; 1 to 255 ) | sharpness of the camera |
Lets you manually pre-set the sharpness of the camera/webcam:
It will normally take an integer value in the range of 1
to 255
, at least for a Logitech webcam, but will vary based on the camera / device you are using.
VDO.Ninja already tries to auto-save camera settings for android devices that support video settings, but for desktop browsers, it does not. Using these new values though you can manually set things to auto-configure as you want.
These settings will apply to ALL video devices though, not just a specific one. If a setting isn't supported by your camera or browser, it will just fail quietly, and not apply. You'll see an error in the console log though.\
{% hint style="warning" %}
- Firefox and Safari may not support this feature.
- Not all cameras/smartphones will support this option {% endhint %}
You can check the video settings menu as to whether a device supports a certain feature or what value ranges are support; you can also check it out here https://vdo.ninja/supports.
{% content-ref url="./" %} . {% endcontent-ref %}
Sender-Side Option! (&push
)
&wb
Example: &whitebalance=5000
Value | Description |
---|---|
(integer value) | white balance in Kelvin (5000 to 6500 are typical values) |
Lets you manually pre-set the white balance of the camera/webcam:
It is normally in Kelvin, so 5000
or 6500
are typical values it will take.
VDO.Ninja already tries to auto-save camera settings for android devices that support video settings, but for desktop browsers, it does not. Using these new values though you can manually set things to auto-configure as you want.
These settings will apply to ALL video devices though, not just a specific one. If a setting isn't supported by your camera or browser, it will just fail quietly, and not apply. You'll see an error in the console log though.\
{% hint style="warning" %}
- Firefox and Safari may not support this feature.
- Not all cameras/smartphones will support this option {% endhint %}
You can check the video settings menu as to whether a device supports a certain feature or what value ranges are support; you can also check it out here https://vdo.ninja/supports.
{% content-ref url="./" %} . {% endcontent-ref %}
You have to add the parameters to the source link (&push
).
Parameter | Explanation |
---|---|
&whitebalance * | Lets you manually pre-set the white balance of the camera/webcam |
&exposure * | Lets you manually pre-set the exposure of the camera/webcam |
&saturation * | Lets you manually pre-set the saturation of the camera/webcam |
&sharpness * | Lets you manually pre-set the sharpness of the camera/webcam |
&contrast * | Lets you manually pre-set the contrast of the camera/webcam |
&brightness * | Lets you manually pre-set the brightness of the camera/webcam |
*NEW IN VERSION 24
VDO.Ninja makes heavy use of URL-based parameters to configure settings. Some of the most commonly used ones are listed below, with a brief explanation of what they are for and links to more detail.
Sender-side parameter | Explanation |
---|---|
&push |
The stream ID you wish to publish your video under; it must be unique. The value can be defined manually and reused. If left blank, a value will be generated automatically. |
&quality |
Sets the default target resolution and frame rate. If not used, the system default is 720p60. Setting &quality=0 will result in 1080p60 being the new target default, but this may significantly increase the CPU load on the sender's computer. |
&videodevice |
Specify an video device to auto-select on load. If left blank, the system's default audio device will be selected. |
&audiodevice |
Specify an audio device to auto-select on load. If left blank, the system's default audio device will be selected. |
&effects |
This parameter will allow for digital effects to be applied to the video, including background-blurring and a digital greenscreen. You can preset which effect is loaded by setting this value to a corresponding number, such as &effects=4 . |
&label |
Allows the guest connection to be assigned a display name, which will be used in chat and if overlays are turned on. If left blank, the guest will be prompted to enter a display name. |
&meshcast |
Adding &meshcast to a guest or director link will trigger the service, causing the outbound audio/video stream to be transferred to a hosted server, which then distributes the stream to all the viewers. This adds a bit of latency to the stream, but it implies the guest/director does not need to encode and upload multiple videos, lowering CPU load and bandwidth usage. |
Viewer-side parameter | Explanation |
---|---|
&view |
The stream ID you wish to view/hear; a comma-separated list can be passed as well to view multiple at a time. This isn't required if using a group room, but it can be used in conjunction with the |
&videobitrate |
The video bitrate you wish to view a video at, in kbps. The default is 2500-kbps and is well-suited for interviews and talking-heads, but you may need to increase it if video contains significant motion and scene changes. |
&audiobitrate |
Sets the audio bitrate, in kbps. The system default is 32-kbps, with the max limit being between 300 to 510-kbps, based on other factors. Too high and you may actually introduce clicking noise issues. |
&codec |
h264, vp9, vp8, and sometimes av1 are options. Setting &codec=h264 can sometimes trigger the sender's hardware encoder to be used, but this can often have unexpected consequences. The default is left up to the browsers to decide. |
&novideo |
This flag will disable incoming video streams. Connections will still be established, allowing for data and audio still. You can pass a list of stream IDs to exempt streams from this filter. |
&noaudio |
This flag will disable incoming audio streams. Connections will still be established, allowing for data and video still. You can pass a list of stream IDs to exempt streams from this filter. |
&showlabels |
If the sender has set a display name, you can overlay that name by using this parameter. Different styles of labels are available, which can be set by passing their corresponding style ID to this parameter. |
Director, room, and general parameters | Explanation |
---|---|
&room |
Defines a room for guests to chat in. If used, everyone in a room will auto-connect to each other on joining, unless Guests in a room have limited control and will see videos at reduced quality; this is intentional. |
&director |
The director flag should be set to whatever the room name is. The first director to join a room then becomes the controller of the room. They have the ability to remotely control guest's settings, such as microphone volume of a guest, and they can add and remove guests to scenes. |
&proaudio |
Several other parameters into one, designed to quick-start applications needing high-quality audio. This parameter can be considered pretty heavy duty, so it's primarily designed for professional users needing near-raw audio quality, such as music DJs. When applied to the viewer's side as well, it will increase the connection's audio bitrate to 256-kbps and request stereo-audio from the sender, if it is available. |
&scene |
If using a room, then to view a specific stream or collection of streams, the Different scenes and scene types are available, and since a director can add and remove streams from scenes from their control room, multiple scenes can be used together to act as media slots in complex show layouts. |
&roombitrate |
This parameter can be added to a guest's invite link to reduce the maximum video bandwidth they will make available to each other guest. On mobile devices, outbound bandwidth to other guest is already set very low, but if a guest is still struggling to participate in a group room, adding |
&password |
Specifies the custom password to be used. If left blank, the user will be prompted for the password on page load. Passwords are not stored and used purely client-side. They are used to encrypt the initial connection handshake between peers and to obfuscate room names. |
&broadcast |
Adding this flag will have guests only accept video connections from the director, but still share audio and accept audio-connections from other guests. This reduces the CPU and network load on guests, allowing for larger rooms, so long as the director can also support those larger rooms. |
{% content-ref url="../../advanced-settings.md" %} advanced-settings.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
)
&appbg
Example: &background=./media/logo_cropped.png
Value | Description |
---|---|
(encoded URL) | Changes the background of VDO.Ninja |
Accepts a URL-encoded image URL to make as the app's default background.
To test:
https://vdo.ninja/?background=./media/logo_cropped.png
The image will scale in size to cover the VDO.Ninja app's background. &chroma
can still be used to set the background color, if using transparencies. There already exists &bgimage
, which will set the default background image for videos; this however will set a background image for the entire page.
You can encode and decode a URL here:
https://www.urlencoder.org/
{% content-ref url="and-bgimage.md" %} and-bgimage.md {% endcontent-ref %}
{% content-ref url="chroma.md" %} chroma.md {% endcontent-ref %}
{% content-ref url="../newly-added-parameters/and-waitimage.md" %} and-waitimage.md {% endcontent-ref %}
description: >- Lets you add css to the URL, but as a single string, so no external reference to a file is needed
General Option! (&push
, &room
, &view
, &scene
)
&b64css
&cssbase64
&cssb64
Example: &base64css=JTIzbWFpbm1lbnUlN0JiYWNrZ3JvdW5kLWNvbG9yJTNBJTIwcGluayUzQiUyMCVFMiU5RCVBNA
Value | Description |
---|---|
(string) | Custom base64 string |
This command lets you add CSS to VDO.Ninja via the URL, but as a single string, so no external reference to a file is needed.
Example usage:
https://vdo.ninja/?base64css=JTIzbWFpbm1lbnUlN0JiYWNrZ3JvdW5kLWNvbG9yJTNBJTIwcGluayUzQiUyMCVFMiU5RCVBNA
You can create the base64 encoding using btoa(encodeURIComponent(csshere))
, for example window.btoa(encodeURIComponent("#mainmenu{background-color: pink; ❤" ));
Will return the base64 encoded string required. Special non-latin characters are supported with this approach; not just latin characters.
The https://invite.vdo.ninja/ tool has an option to do these base64 encoding steps under "General Options".
{% content-ref url="css.md" %} css.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
,&solo
)
&jsb64
&b64js
&jsb64
Example: &base64js=YWxlcnQoJ2hpJyk=
Value | Description |
---|---|
(string) | Javascript URL |
&base64js
lets a user add raw java script to the URL to run on page load.
To test:
https://vdo.ninja/?base64js=YWxlcnQoJ2hpJyk=
{% content-ref url="and-base64css.md" %} and-base64css.md {% endcontent-ref %}
{% content-ref url="and-js.md" %} and-js.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
)
&bgimg
&avatarimg
Example: &bgimage=https%3A%2F%2Fvdo.ninja%2Fmedia%2Fold_icon.png
Value | Description |
---|---|
(Encoded URL) | URL or base64 data image/svg |
&bgimage
can be used to set the default image avatar, when using &style=0
or &style=6
. This only impacts what the person with the parameter added sees and must be either a URL or a base64 data image/svg. URL-encoded values.
You can encode your URL here:
https://www.urlencoder.org/
If you want to change the background image / avatar on the sender's side for all viewers, use &avatar
.
&bgimage2
and &bgimage3
work in conjunction with the existing &bgimage
parameter. You pass an URL-encoded image URL to each, and when a guest speaks, it will switch their background image between the 3 possible images, based on their loudness.
eg:
vdo.ninja/alpha/?view=stream2,stream2&avatarimg=./media/avatar1.png&avatarimg2=./media/avatar2.png&avatarimg3=./media/avatar3.png
I've included some hand-drawn avatar sample images to test with; they are the default values for &bgimage
, &bgimage2
, and &bgimage3
.
The images will only show when there is no active video and is essentially the same as using &meterstyle=4
with some custom CSS to specify the behaviour, but it is not stream ID specific however.
{% content-ref url="style.md" %} style.md {% endcontent-ref %}
{% content-ref url="../video-parameters/and-avatar.md" %} and-avatar.md {% endcontent-ref %}
{% content-ref url="../newly-added-parameters/and-waitimage.md" %} and-waitimage.md {% endcontent-ref %}
{% content-ref url="and-background.md" %} and-background.md {% endcontent-ref %}
description: >- Will try to add a blurred background to the video so it fits the structured video container
General Option! (&push
, &room
, &view
, &scene
)
Example: &blur=25
Value | Description |
---|---|
(no value given) | blurring intensity = 10 |
(integer) | blurring intensity |
25 |
blurring intensity = 25 |
&blur
which will try to add a blurred background to the video so it fits the structured video container. Using &blur
auto enables &structure
.
Code in the auto mixer, so you won't see the effect in a simple preview or some self-preview types.
&blur
doesn't work with &color
, etc.
You can change the blurring intensity with &blur=25
or whatever; 10
is default
&blur=0
works as well.
May be buggy if using it with &forcedlandscape
or &rotate
{% content-ref url="and-structure.md" %} and-structure.md {% endcontent-ref %}
{% content-ref url="and-border.md" %} and-border.md {% endcontent-ref %}
{% content-ref url="and-color.md" %} and-color.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
)
Example: &border=20
Value | Description |
---|---|
(no value given) | adds a border with 10 px |
(integer value) | adds a border in px |
Adds a border around the videos.
{% content-ref url="and-bordercolor.md" %} and-bordercolor.md {% endcontent-ref %}
{% content-ref url="margin.md" %} margin.md {% endcontent-ref %}
{% content-ref url="rounded.md" %} rounded.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
)
Example: &bordercolor=ffffff
or &bordercolor=white
Value | Description |
---|---|
(no value given) | black border |
(HEX) | (color name) | specifies the color of the border |
ffffff |
white border |
{% hint style="danger" %} Do not include the # character with the hex value. {% endhint %}
Defines the color of &border
.
{% content-ref url="and-border.md" %} and-border.md {% endcontent-ref %}
{% content-ref url="margin.md" %} margin.md {% endcontent-ref %}
{% content-ref url="rounded.md" %} rounded.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&cv
This is the exact same thing as &cleanoutput
, except it only triggers if added to a view-only link.
Hides many of the UI elements and pop-ups that may cause unwanted visual elements not desired in a high-stakes live stream.
{% content-ref url="cleanoutput.md" %} cleanoutput.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
Example: &color=ffffff
or &color=white
Value | Description |
---|---|
(no value given) | black background |
(HEX) | (color name) | specifies the color of the background |
ffffff |
white background |
{% hint style="danger" %} Do not include the # character with the hex value. {% endhint %}
You can specify the background color independent of the border color with &color
. If using &border
, it will not set the background color, so you may need to use both &border
and &color
.
May not yet work with &forcedlandscape
or &rotate
.\
{% content-ref url="and-structure.md" %} and-structure.md {% endcontent-ref %}
{% content-ref url="and-border.md" %} and-border.md {% endcontent-ref %}
{% content-ref url="and-blur.md" %} and-blur.md {% endcontent-ref %}
{% content-ref url="and-bordercolor.md" %} and-bordercolor.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
)
Example: &favicon=https%3A%2F%2Fmeshcast.io%2Ffavicon.ico
Value | Description |
---|---|
(URL encoded URL) | Changes the favicon |
&favicon
will change the browser's page favicon image. Passed values should be URL encoded. (Google URL encoding if needed). Since this is Javascript based, the values only update once the page loads. Meta-page-previews will likely not reflect the values.
Sample link: https://vdo.ninja/?headertitle=LINDENKRON4TW&favicon=https%3A%2F%2Fmeshcast.io%2Ffavicon.ico
{% content-ref url="and-headertitle.md" %} and-headertitle.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
Inverts the video so it is upside down. That's it. It doesn't change the viewer's link. If you want to have the viewer's link. If you want to flip the viewer's link as well, you have to add &flip
to the viewer's side as well.
If you are looking for a form of rotation and flipping that rotates the actual video, rather than relying on CSS to achieve it, you can check out the sender-side &effects
options.
https://vdo.ninja/?effects=-1
, which will flip the video
https://vdo.ninja/?effects=-2
, which will flip and mirror the video
https://vdo.ninja/?effects=2
, which will mirror the video
Effects however may increase CPU/GPU usage, and could cause frame rate instability, especially if the browser tab is not in active focus.
There's a dedicated tool for mirror, flipping, and rotating websites as part of VDO.Ninja as well:
In case the built-in options to mirror or flip don't work, the teleprompter app might be a good alternative.
{% content-ref url="../../steves-helper-apps/teleprompter-tool.md" %} teleprompter-tool.md {% endcontent-ref %}
{% content-ref url="and-mirror.md" %} and-mirror.md {% endcontent-ref %}
{% content-ref url="../../source-settings/effects.md" %} effects.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
)
Example: &headertitle=LINDENKRON4TW
Value | Description |
---|---|
(string) | Changes the browser's page title |
&headertitle
will change the browser's page title.
Sample link: https://vdo.ninja/?headertitle=LINDENKRON4TW&favicon=https%3A%2F%2Fmeshcast.io%2Ffavicon.ico
{% content-ref url="and-favicon-alpha.md" %} and-favicon-alpha.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&noheader
&hh
&hideheader
could be useful for hiding VDO.Ninja branding, making videos a bit larger at times, or for IFRAME use-case applications.
It hides this:
{% content-ref url="and-hidemenu.md" %} and-hidemenu.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&hm
Hides the VDO.Ninja-branded menu and header bar.
Useful for making videos larger for guests by freeing up space.
{% content-ref url="and-hideheader.md" %} and-hideheader.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
Example: &js=https%3A%2F%2Fvdo.ninja%2Fexamples%2Ftestjs.js
Value | Description |
---|---|
(encoded URL) | Third party hosted java script file URL |
&js
lets you pass a third party hosted java script file URL (URL-encoded), allowing for a custom code injection without self-hosting, IFrames or chrome extensions.
Example:
https://vdo.ninja/?js=https%3A%2F%2Fvdo.ninja%2Fexamples%2Ftestjs.js
You can use this tool to encode the URL you want to link to
https://www.urlencoder.org/
{% content-ref url="and-base64js.md" %} and-base64js.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
Forces to enable the lightmode. It's the same like &darkmode=0
or &darkmode=false
.
{% content-ref url="darkmode.md" %} darkmode.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
Example: &mirror=2
Value | Description |
---|---|
(no value given) | Mirroring is forced for all videos |
0 | Preview video is mirrored only (excluding rear cameras and OBS Virtualcam/NDI) |
1 | Mirroring is forced for all videos |
2 | Inverts the default; local previews are not mirrored, but guests are mirrored |
3 | Same as default, except everything is mirrored, including text - useful for teleprompters |
Mirroring does not work if using the browser's native video full-screen button. Use &effects=2
instead for this use case.
Try F11
or the Electron Capture app (right-click → Resize window -> Fullscreen) to hide the browser menu instead.
If you are looking for a form of rotation and flipping that rotates the actual video, rather than relying on CSS to achieve it, you can check out the sender-side &effects
options.
https://vdo.ninja/beta/?effects=-1
, which will flip the video https://vdo.ninja/beta/?effects=-2
, which will flip and mirror the video
https://vdo.ninja/beta/?effects=2
, which will mirror the video
Effects however may increase CPU/GPU usage, and could cause frame rate instability, especially if the browser tab is not in active focus.
There's a dedicated tool for mirror, flipping, and rotating websites as part of VDO.Ninja as well:
In case the built-in options to mirror or flip don't work, the teleprompter app might be a good alternative.
{% content-ref url="../../steves-helper-apps/teleprompter-tool.md" %} teleprompter-tool.md {% endcontent-ref %}
{% content-ref url="../../source-settings/effects.md" %} effects.md {% endcontent-ref %}
{% content-ref url="and-flip.md" %} and-flip.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&nomirror
disables the default mirror state of the video preview for a guest, unlike &mirror=0
. Previews are often mirrored by default. &mirror
can be applied on top of that state, to mirror things back for everyone if needed.
{% content-ref url="and-mirror.md" %} and-mirror.md {% endcontent-ref %}
{% content-ref url="../../guides/how-to-mirror-a-video-while-full-screen-for-ipads-and-teleprompters.md" %} how-to-mirror-a-video-while-full-screen-for-ipads-and-teleprompters.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&oo
&disableobs
Disables the tally light effects; can be applied to both viewer or publisher. Tally lights are represented as a glowing red border around videos. When the light is on, the video is considered "VISIBLE" within OBS Studio. This is based on whether OBS Studio tells VDO.Ninja if a video is active or not.
{% hint style="info" %} Videos on first-load in OBS, even if visible in OBS, don't glow red; it requires an initial visibility change to trigger it. {% endhint %}
&obsoff
can be used to set permissions to fully off (also disables tally light and scene optimizations tho) when added to the OBS browser source link.
{% content-ref url="../settings-parameters/and-controlobs.md" %} and-controlobs.md {% endcontent-ref %}
{% content-ref url="tallyoff-1.md" %} tallyoff-1.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
Adding this to a guest's link in a room, it forces the system-based PIP to trigger on the first video that loads.
{% content-ref url="and-pipall-alpha.md" %} and-pipall-alpha.md {% endcontent-ref %}
{% content-ref url="and-pipme-alpha.md" %} and-pipme-alpha.md {% endcontent-ref %}
description: >- New floating picture in picture mode, so you can pop out the entire video mix as a pinned window overlay
General Option! (&push
, &room
, &view
, &scene
)
&pip2
Added a new floating picture in picture mode, so you can pop out the entire video mix as a pinned window overlay.
&pipall
will add a dedicated button for this mode.
Or just right-click any video and select "Picture in picture all" from the context menu. This is available without any URL option.
This requires Chrome v115 right now; it might vanish in v116 due to it being in a chrome field trial
, and so you might need to enable it via chrome:flags
if it stops working.
Update: Doesn't break the site if browser does not supported.
{% content-ref url="and-pip.md" %} and-pip.md {% endcontent-ref %}
{% content-ref url="and-pipme-alpha.md" %} and-pipme-alpha.md {% endcontent-ref %}
description: >- Will cause your self-video preview window to pop out into its own picture in picture
General Option! (&push
, &room
, &view
, &scene
)
&mypip
&pip3
&pipme
will cause your self-video preview window to pop out into its own picture in picture (floating/draggable) on load.
This is not compatible with &autostart
. Works with director or guest; not tested on mobile.
CTRL + ALT + P
will also toggle the picture in picture, without needing any URL parameters. (cmd + ALT + P
on Mac)
{% content-ref url="and-pip.md" %} and-pip.md {% endcontent-ref %}
{% content-ref url="and-pipall-alpha.md" %} and-pipall-alpha.md {% endcontent-ref %}
Sender-Side Option! (&push
)
Example: &rotate=180
Value | Description |
---|---|
(no value given) | 90 | 90 degree |
(degree) | Rotates the camera in the specified value in degree |
Applies to the publisher's side. Rotates the camera 90-deg by default, or specify &rotate=180
or &rotate=270
to rotate more.
Rotates your video for the guests/OBS as well. The rotation uses CSS.
{% hint style="warning" %} CSS-based video effects will not work in full-screen mode. As well, the control-bar gets rotated with the video, when using CSS. {% endhint %}
If you are looking for a form of mirroring and flipping that changes the actual video, rather than relying on CSS to achieve the effect, you can check out the sender-side &effects
options.
https://vdo.ninja/beta/?effects=-1
, which will flip the video https://vdo.ninja/beta/?effects=-2
, which will flip and mirror the video
https://vdo.ninja/beta/?effects=2
, which will mirror the video
Effects however may increase CPU/GPU usage, and could cause frame rate instability, especially if the browser tab is not in active focus.
There's also the &flip
and &mirror
options, which use CSS, but are generally viewer-side only.
There's a dedicated tool for mirror, flipping, and rotating websites as part of VDO.Ninja as well:
https://vdo.ninja/teleprompter
In case the built-in options to mirror or flip don't work, the teleprompter app might be a good alternative.
{% content-ref url="../../source-settings/effects.md" %} effects.md {% endcontent-ref %}
{% content-ref url="and-flip.md" %} and-flip.md {% endcontent-ref %}
{% content-ref url="and-mirror.md" %} and-mirror.md {% endcontent-ref %}
{% content-ref url="and-rotatewindow.md" %} and-rotatewindow.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&rotatepage
Example: &rotatewindow=270
Value | Description |
---|---|
(no value given) | 90 | 90 degree |
(degree) | Rotates the page in the specified value in degree |
&rotatewindow
will rotate the contents of the VDO.Ninja window. It doesn't target any specific video, and can be used on the viewer-side, not just the sender.
This will be overridden by &forcelandscape
mode, if that is used also.
You can pass 90
, 180
, or 270
as a value to the parameter, to rotate accordingly. The default is 90
though, if used without any value.
You might still want to use OBS to rotate instead, but if not using OBS and find the teleprompter app too cumbersome, this is a good option.
{% content-ref url="and-rotate.md" %} and-rotate.md {% endcontent-ref %}
{% content-ref url="and-flip.md" %} and-flip.md {% endcontent-ref %}
{% content-ref url="and-mirror.md" %} and-mirror.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
)
&style=7
Added &showall
(or &style=7
), which will include non-media-based push connections as video elements in a group room. This can include guests that joined without audio/video, directors, or a data-only connection, like maybe MIDI-output source.
To help avoid some types of connections showing up when using &showall
, I've also added a &nopush
mode, which blocks outbound publishing connections. This acts a bit like a &scene=1
link, so unless &showall
is added, you'll need to use the IFRAME API to show/hide videos in it.
{% content-ref url="style.md" %} style.md {% endcontent-ref %}
{% content-ref url="../settings-parameters/and-nopush.md" %} and-nopush.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&structure
will have the video holding div element be structured to 16:9 (or whatever &aspectratio
is set to), making it easier to apply custom CSS backgrounds to videos.
It will have the label/border/margins align relative to the 16:9 holder element, rather than video itself.
Also related, you can also specify the background color independent of the border color with &color
. If using &border
, it will not set the background color, so you may need to use both &border
and &color
.
May not yet work with &forcedlandscape
or &rotate
.
Updated &structure
to work with &cover
, allowing for some more flexibility with controlling fixed aspect-ratios from the viewer/scene side.
ie: https://vdo.ninja/?room=XXXXX&scene&cover&structure&square&fakeguests=10
{% content-ref url="../mixer-scene-parameters/and-locked.md" %} and-locked.md {% endcontent-ref %}
{% content-ref url="and-color.md" %} and-color.md {% endcontent-ref %}
{% content-ref url="and-blur.md" %} and-blur.md {% endcontent-ref %}
{% content-ref url="and-border.md" %} and-border.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&transparency
Makes the background for the website transparent using CSS.
The browser source in OBS already has a transparent background by default.
This is useful for embedding VDO.Ninja as an IFRAME.
Not helpful with the Electron Capture app.
Not needed for OBS if using default OBS CSS stylesheet:
body {
background-color: rgba(0, 0, 0, 0);
margin: 0px auto;
overflow: hidden;
}
A video demo of the &chunked
transfer and how to enable support for alpha-channel transparency is available here: https://youtu.be/SWDlm1Jf-Oo
{% content-ref url="chroma.md" %} chroma.md {% endcontent-ref %}
{% content-ref url="../../newly-added-parameters/and-chunked.md" %} and-chunked.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
Example: &chroma=F0F
Value | Description |
---|---|
(no value given) | green background |
F0F |
any RGB format color |
DEDEDE |
any RRGGBB format color |
{% hint style="info" %} Use it to chroma-key out the background on the Electron Capture app. {% endhint %}
{% hint style="danger" %} Do not include the # character with the hex value. {% endhint %}
Can be 3 or 6 characters in length, 0 to F, in RGB or RRGGBB format.
https://vdo.ninja/?scene&room=roomname&chroma
See &color
if you want to set the background color of one single video feed.
{% content-ref url="and-color.md" %} and-color.md {% endcontent-ref %}
{% content-ref url="and-transparent.md" %} and-transparent.md {% endcontent-ref %}
{% content-ref url="and-background.md" %} and-background.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
Same as &cleanoutput
, except it still shows the play button that allows handling gesture requirements in chrome.
Director direct overlay messages are still visible.
When using &cleanish
and &record
, you'll get the record button showing, but nothing else.
{% content-ref url="cleanoutput.md" %} cleanoutput.md {% endcontent-ref %}
{% content-ref url="../../director-settings/cleandirector.md" %} cleandirector.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&clean
Hides many of the UI elements and pop-ups that may cause unwanted visual elements not desired in a high-stakes live stream.
{% content-ref url="cleanish.md" %} cleanish.md {% endcontent-ref %}
{% content-ref url="../../director-settings/cleandirector.md" %} cleandirector.md {% endcontent-ref %}
{% content-ref url="and-cleanviewer.md" %} and-cleanviewer.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
Example: &css=https%3A%2F%2Fbackup.vdo.ninja%2Fdev4321%2Fexamples%2Fmain.css
Value | Description |
---|---|
(encoded URL) | will show the VU-style meter that the director has by default already |
Any URL-encoded URL that links to a CSS file.
Example:
https://vdo.ninja/?css=https%3A%2F%2Fbackup.vdo.ninja%2Fdev4321%2Fexamples%2Fmain.css
You can use this tool to encode the URL you want to link to
https://www.urlencoder.org/
Link to a remotely hosted CSS style sheet via the URL. You can stylize VDO.Ninja without needing to host anything more than a CSS file. The page elements are not visible until the remote style sheet has been loaded.
I've made the &css
parameter within VDO.Ninja more tolerant to invalid forms of input, so if you don't know what URL or Base64 encoding is, you might be able to get away without using any now.
https://vdo.ninja/?css=body{background-color:blue!important}
You can pass CSS as a base64-encoded string using the &base64css
parameter. This needs to be URLComponent encoded first, and then converted to base 64.
The https://invite.vdo.ninja/ tool has an option to do these base64 encoding steps under "General Options".
Customizable director's dock for OBS example made:
&css=minidirector.css
Example:
https://vdo.ninja/?css=minidirector.css&cleanoutput&hidesolo&director
{% content-ref url="and-base64css.md" %} and-base64css.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&nightmode
Example: &darkmode=0
Value | Description |
---|---|
(no value given) | enables the dark-mode |
0 | false |
disables the dark-mode |
Enables the dark-mode stylings of the website.
Conversely, setting &lightmode
, &darkmode=0
or &darkmode=false
will disable the dark-mode, forcing the light-mode.
The dark-mode will be selected automatically by default if your system is set to dark color mode, so this flag can be used to override that.
{% content-ref url="and-lightmode.md" %} and-lightmode.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&ruler
&thirds
Example: &grid=./media/thirdshead.svg
Value | Description |
---|---|
(no value given) | adds a white rule-of-thirds grid overlay |
(encoded URL) | adds an image as a overlay |
Applies an rule-of-thirds grid overlay to the self-preview video window. This is useful for passively nudging guests to better center themselves while on camera.
{% hint style="warning" %} As of v19.0, this only works for guests of a room or of a faux-room. It doesn't yet support basic push/view links, as those don't use the auto-mixer code, which is where this code is currently applied. {% endhint %}
Added the option to customize the &grid
effect by passing an image link (can help center guests).
A transparent PNG or an SVG file are the recommended options.
It will stretch to cover the camera preview-area, so probably best to keep things 16:9 aspect if needed.
URL can be URL-encoded, for more complex URLs. Simple URLs might work without.
Technically this can be used as an overlay for other things, but it only works with the self-preview.
Example: https://vdo.ninja/?push&grid=./media/thirdshead.svg
Leave the passed value empty if you wish to have the white basic rule-of-thirds show as default.
{% hint style="info" %}
- As of v22, it now works in non-room mode (basic push links):
https://vdo.ninja/?push&grid - You can now also toggle it in the director's room to add it to the guest's link:
{% endhint %}
You can encode your URL here:
https://www.urlencoder.org/
General Option! (&push
, &room
, &view
, &scene
)
Example: &margin=100
Value | Description |
---|---|
(no value given) | margin value = 10px |
(integer value) | margin value in px |
Adds 10px around the videos for some spacing, by default. It can be customized.
https://vdo.ninja/?scene&room=roomname&margin=100
General Option! (&push
, &room
, &view
, &scene
, &director
)
&meter
Example: &meterstyle=3
Value | Description |
---|---|
1 | (no value given) | will show the VU-style meter that the director has by default already |
2 | will show a green-border around the guest's video when they are talking |
3 | will show a little green dot in the top-right corner when the guest's talking; this is default for the guest's view already |
4 | no meter is shown, but a data-attribute named data-loudness is applied to the video element. This can be targeted with CSS to do custom styles via OBS browser source or with &css |
5 | has the audio-only background image pulse larger in size when that specific guest is speaking |
If you add this to a director's/guest's URL, it will show an optional audio style type, when a guest is talking.
When using any &meterstyle
effect, I now include a data attribute called data-speaking
to the video element. It will be either 0, 1, or 2. 0 is quiet, 1 is whispering, and 2 is loud. &meterstyle=4
includes a fine-grain option already for loudness as an attribute, but for basic CSS needs, this option might be more approachable.
You can use this attribute to use CSS to customize your own effects when someone speaks. You can further target what is CSS used based on a specific guest by using each video's stream ID data attribute as well.
When using &meterstyle=4
or greater, the background of an audio-only element is transparent now; not black. I also specifically hide the video-control bar when using &meterstyle=4
, but you can use &videocontrols
to add them back in if needed.
It can be used in conjunction with &bgimage
to specific a custom background image for the video, which will pulse in size. ie: &meterstyle=5&bgimage=./media/avatar1.png
{% content-ref url="style.md" %} style.md {% endcontent-ref %}
description: >- Labels, styles, clean output, CSS, mirroring, margin, dark mode, background color, disable tallies etc.
They are separated in three groups: general options (push and view), source side (push) options and viewer side (view) options.
You can add them to both, source (&push
) and viewer (&view
or &scene
) sides.
Parameter | Explanation |
---|---|
&label | Sets a display name label |
&showlabels | Display labels as a video overlay |
&fontsize | Let you set font-size of the closed captions and stream labels |
&style | Lets you select how audio-only elements are displayed in OBS and for guests |
&bgimage | Can be used to set the default image avatar, when using &style=0 or &style=6 |
&showall | Includes non-media-based push connections as video elements in a group room |
&meterstyle | Optional audio meter style type |
&cleanoutput | Keeps the output as clean as possible from UI elements |
&cleanish | Cleaner output; not as clean as &cleanoutput |
&css | Loads a custom CSS file |
&base64css | Lets you add css to the URL, but as a single string, so no external reference to a file is needed |
&js | Lets you pass a third party hosted javascript file URL |
&base64js | Lets a user add raw javascript to the URL to run on page load |
&mirror | Inverts the video so it is the mirror reflection |
&nomirror * | Disables the default mirror state of the video preview for a guest |
&flip | Inverts the video so it is upside down |
&rotatewindow | Will rotate the contents of the VDO.Ninja window |
&structure | Will have the video holding div element be structured to the aspect ratio |
&color | You can specify the background color independent of the border color |
&blur | Will try to add a blurred background to the video so it fits the structured video container |
&border | Adds a border around the videos |
&bordercolor | Defines the color of &border |
&rounded | Rounds the edges of videos |
&margin | Adds a margin around the videos in pixel |
&darkmode | Darkens the website and interface |
&lightmode | Forces to enable the lightmode / disable the darkmode |
&background | Accepts a URL-encoded image URL to make as the app's default background |
&chroma | Sets the background for the website to a particular hex color |
&transparent | Makes the background transparent |
&nocursor | Hides the mouse cursor over videos at a CSS level |
&favicon | Will change the browser's page favicon image |
&headertitle | Will change the browser's page title |
&pipall * | New floating picture in picture mode, so you can pop out the entire video mix as a pinned window overlay |
&pipme * | Will cause your self-video preview window to pop out into its own picture in picture |
*NEW IN VERSION 24
You have to add them to the source side (&push
).
Parameter | Explanation |
---|---|
&rotate | Rotates the camera |
&grid | Applies an rule-of-thirds grid overlay to the self-preview |
&hideheader | Hides just the top header-bar |
&hidemenu | Hides the VDO.Ninja-branded menu and header bar |
&tally | Will make the tally sign larger and colorize the background of the page |
&tallyoff | Disables the Tally Light's visibility for that particular guest |
You have to add them to the viewer side (&view
or &scene
).
Parameter | Explanation |
---|---|
&cleanviewer | Hides many of the UI elements and pop-ups that may cause unwanted visual elements |
&obsoff | Disables the tally light effects |
&pip | Auto PIP the first loaded video |
General Option! (&push
, &room
, &view
, &scene
)
&round
Example: &rounded=100
Value | Description |
---|---|
(no value given) | 50 px |
(positive integer value) | the higher the number, the more aggressive the curve |
This is a stylistic effect; it attempts to apply rounded edges to videos (crop-based).
The default value is 50-pixels. You can pass other integer values to customize the amount of curving; the higher the number, the more aggressive the curve.
This works great for solo-video streams where the video fits the window fully, but may not round the edges of videos that do not fit their container area. To compensate for this, using the &cover
command as well can force the video to fit the window, and hence, have the rounded edges applied correctly.
An example of an aggressive rounded effect is with the following parameters:
https://vdo.ninja/?view=streamID123&cover&rounded=1000
{% content-ref url="../view-parameters/cover.md" %} cover.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&showlabel
&sl
There are some preset style options, which can be passed to the parameter as a value. You can also choose to just edit the label's style with CSS, as discussed lower on this page.
Example: &showlabels=ninjablue
Value | Description |
---|---|
(no value given) | Generic styled display names |
fire | Fire looking display names |
ninjablue | VDO.Ninja styled display names |
skype | Skype styled display names |
teams | Microsoft Teams styled display names |
toprounded | Top-center rounded display names |
zoom | Zoom styled display names |
rounded | Rounded lower-right names; bold |
This parameter will display the user's display name or label on screen, as a text overlay. The label can be set either via the URL using the &label
parameter, or the room's director can set it dynamically via the "Add a label" option.
This parameter can be used on guest links, view links, or scene links. It will be sticky to each individual video and not the browser window as a whole.
Underscores "_" used in label values will be replaced by spaces, allowing for word separation.
HTML5 Emojis 🎈 and some non-Latin characters are supported.
For example: https://vdo.ninja/?showlabels=fire
If no preset option is passed, a default generic style is used:
You can change the font-size without using CSS, using the &fontsize
parameter. CSS is also supported though.
Font-size of labels will adjust slightly based on the window size.
CSS of the styles can be set via the OBS browser source stylesheet window.
The CSS class name you can customize is called video-label
.
You can copy the below code, modifying it as you desire, as a starting point. You'll still need to use &showlabels
to trigger the labels to display though.
.video-label {
color: red;
bottom: 2vh;
left: 50%;
transform: translateX(-50%);
background: rgba(0, 0, 0, .8);
pointer-events:none;
border-radius: 5px;
font-size: 0.8em;
}
Below is another example, this time we target the video tile class, creating a margin above the video elements. We can then move the display label into that space, creating a label that is not overlaying the video itself, but still attached.
.tile {
margin-top: 10vh !important;
max-height: 90vh!important;
}
.video-label {
bottom:unset;
top:0;
text-align:middle;
left:unset;
background:unset;
text-shadow : 0 0 10px #035;
font-size: 7vh!important;
}
{% content-ref url="../../general-settings/label.md" %} label.md {% endcontent-ref %}
{% content-ref url="../../newly-added-parameters/and-screensharelabel.md" %} and-screensharelabel.md {% endcontent-ref %}
{% content-ref url="../view-parameters/fontsize.md" %} fontsize.md {% endcontent-ref %}
{% content-ref url="css.md" %} css.md {% endcontent-ref %}
{% content-ref url="../setup-parameters/and-labelsuggestion.md" %} and-labelsuggestion.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&st
Example: &style=2
Value | Description |
---|---|
0 | shows the audio-control bar with a little person as a background silhouette, if the stream is an audio-only. This lets you control the volume and mute and get some feedback that the stream is present |
1 | (no value given) | hides audio-only windows from appearing. The default is for guests to see audio-only boxes for guests that do not have a video feed; the director is excluded |
2 | just shows an animated audio waveform of the speaker's voice, although I made the quality HD now |
3 | shows the audio meter, which you can customize using &meterstyle . You can conversely just use &meterstyle on its own, and mix it with a different style, and it will still work |
4 | will just show a black background for any audio-only source |
5 | will show a random color for a background, instead of just black |
6 | will show the first letter of the guest's display name, in a colored circle, with a black background. If no display name is provided, it will just be a colored circle on a black background |
7 | will include non-media-based push connections as video elements in a group room. This can include guests that joined without audio/video, directors, or a data-only connection, like maybe MIDI-output source |
&style
lets you select how media elements are displayed in OBS and for guests; audio-only elements in particular.
Styles are experimental and will undergo change, tweaks, and likely there are more to come.
The default style depends on numerous factors; the intent is to predict the most desirable for a given situation. Manually setting the style will override the default. Defaults may be changed from time to time, based on user feedback.
There is a toggle in the director's room which adds &st
to the guest's invite link.
{% content-ref url="meterstyle.md" %} meterstyle.md {% endcontent-ref %}
{% content-ref url="and-bgimage.md" %} and-bgimage.md {% endcontent-ref %}
{% content-ref url="and-showall.md" %} and-showall.md {% endcontent-ref %}
Sender-Side Option! (&push
)
¬ally
&disabletally
&to
Disables the Tally Light's visibility for that particular guest.
{% content-ref url="and-obsoff.md" %} and-obsoff.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&tally
will make the tally sign larger and colorize the background of the page, for added emphasis when the feed is added to OBS.
{% content-ref url="tallyoff-1.md" %} tallyoff-1.md {% endcontent-ref %}
{% content-ref url="and-obsoff.md" %} and-obsoff.md {% endcontent-ref %}
description: >- Will let you specify the default for whether to transfer a guest from room to room in broadcast mode or not
Director Option! (&director
)
&bct
&broadcasttransfer
will let you specify the default for whether to transfer a guest from room to room in broadcast mode or not. Mainly useful for when using &rooms
, since there isn't a transfer menu option when using it, since its more of a hotkey option.
If a director clicks "transfer", there is a checkmark to enable "covert user into broadcast mode when transferred". This URL option enables it by default. It also then is enabled by default when using the quick-transfer feature used by &rooms
.
{% content-ref url="../view-parameters/broadcast.md" %} broadcast.md {% endcontent-ref %}
{% content-ref url="../../director-settings/rooms.md" %} rooms.md {% endcontent-ref %}
{% content-ref url="../../getting-started/rooms/transfer-rooms.md" %} transfer-rooms.md {% endcontent-ref %}
Director Option! (&director
)
&hidedirector
&hd
&hidecodirectors
will hide the co-directors from appearing in the director's room. You might have a few co-directors join you, but they might be taking up space, so this is a way to prevent that. It simply hides the boxes; they are still there at a code level.
Changed the logic so it stops the video/audio/IFrame/widget data from any director loading.
This is a bit like the opposite of &showdirector
, but only viewer side.
Another change is that it works with more than just one codirector hiding another codirector, but can be used with scenes, view links, or guests.
Lastly, this is not like &exclude
, as it still allows the data-connection to happen between the two peers, allowing chat and two codirectors to sync their dashboards/commands. Keeping data connections active is important for directors, who rely on them to issue commands, so exclude is a bit to harsh in some cases.
{% content-ref url="../../director-settings/codirector.md" %} codirector.md {% endcontent-ref %}
{% content-ref url="../../viewers-settings/director.md" %} director.md {% endcontent-ref %}
description: >- An ordered array of layouts, which can be used to switch between using the API layouts action
Director Option! (&director
)
Example: &layouts=[[{"x":0,"y":0,"w":100,"h":100,"slot":0}],[{"x":0,"y":0,"w":100,"h":100,"slot":1}],[{"x":0,"y":0,"w":100,"h":100,"slot":2}],[{"x":0,"y":0,"w":100,"h":100,"slot":3}],[{"x":0,"y":0,"w":50,"h":100,"c":false,"slot":0},{"x":50,"y":0,"w":50,"h":100,"c":false,"slot":1}],[{"x":0,"y":0,"w":100,"h":100,"z":0,"c":false,"slot":1},{"x":70,"y":70,"w":30,"h":30,"z":1,"c":true,"slot":0}],[{"x":0,"y":0,"w":50,"h":50,"c":true,"slot":0},{"x":50,"y":0,"w":50,"h":50,"c":true,"slot":1},{"x":0,"y":50,"w":50,"h":50,"c":true,"slot":2},{"x":50,"y":50,"w":50,"h":50,"c":true,"slot":3}],[{"x":0,"y":16.667,"w":66.667,"h":66.667,"c":true,"slot":0},{"x":66.667,"y":0,"w":33.333,"h":33.333,"c":true,"slot":1},{"x":66.667,"y":33.333,"w":33.333,"h":33.333,"c":true,"slot":2},{"x":66.667,"y":66.667,"w":33.333,"h":33.333,"c":true,"slot":3}]]
Value | Description |
---|---|
[layout1,layout2,...] | (URL-encoded ordered array) |
&layouts=[[{xxxxxx}]]
is a URL parameter option, where you can pass a set of different layouts (as a URL-encoded ordered array) to VDO.Ninja.
This is akin to using the vdo.ninja/mixer, to visually set layouts, but instead you are just manually setting all the available layouts directly, bypassing the mixer app.
Once you have set the layouts, the "layout" API feature becomes a bit more useful, as you can remotely activate any of those layouts with a simple API command.
I documented the 'layout' API option a bit here, but the tl;dr; is that you can either use this API call to set a layout from within the array of layouts that are set, or you can pass a full-fledge layout-object, for on-the-fly custom layouts.
ie: {action:'layout',value':5}
or {action:'layout',value':[{xxxx.layout-stuff-here.xxxx]]}
fyi, the layout and the API in general work with the vdo.ninja/mixer page, so you can use it to create the layouts, and then manually switch between them via the API. The API is streamdeck-friendly.
{% embed url="https://github.com/steveseguin/Companion-Ninja/blob/main/README.md#custom-layout-switching-" %}
You can assign guests to custom slots when using &slotmode
on the director's URL.
&layouts=[
Layout1:
[{"x":0,"y":0,"w":100,"h":100,"slot":0}],
Layout2:
[{"x":0,"y":0,"w":100,"h":100,"slot":1}],
Layout3:
[{"x":0,"y":0,"w":100,"h":100,"slot":2}],
Layout4:
[{"x":0,"y":0,"w":100,"h":100,"slot":3}],
Layout5:
[{"x":0,"y":0,"w":50,"h":100,"c":false,"slot":0},{"x":50,"y":0,"w":50,"h":100,"c":false,"slot":1}],
Layout6:
[{"x":0,"y":0,"w":100,"h":100,"z":0,"c":false,"slot":1},{"x":70,"y":70,"w":30,"h":30,"z":1,"c":true,"slot":0}],
Layout7:
[{"x":0,"y":0,"w":50,"h":50,"c":true,"slot":0},{"x":50,"y":0,"w":50,"h":50,"c":true,"slot":1},{"x":0,"y":50,"w":50,"h":50,"c":true,"slot":2},{"x":50,"y":50,"w":50,"h":50,"c":true,"slot":3}],
Layout8:
[{"x":0,"y":16.667,"w":66.667,"h":66.667,"c":true,"slot":0},{"x":66.667,"y":0,"w":33.333,"h":33.333,"c":true,"slot":1},{"x":66.667,"y":33.333,"w":33.333,"h":33.333,"c":true,"slot":2},{"x":66.667,"y":66.667,"w":33.333,"h":33.333,"c":true,"slot":3}]
]
You need to add &api=xxx
to the director's URL to control the layouts via Streamdeck.
HTTP Get | Description |
---|---|
https://api.vdo.ninja/xxx/layout/0 | Disables the layouts -> Auto-mixing |
https://api.vdo.ninja/xxx/layout/1 | Select Layout 1 |
https://api.vdo.ninja/xxx/layout/2 | Select Layout 2 |
https://api.vdo.ninja/xxx/layout/[{"x":0,"y":0,"w":50,"h":100,"c":true,"slot":0},{"x":50,"y":0,"w":50,"h":100,"c":false,"slot":1}] * | Select specified layout |
*If you use the HTTP Get like this, you don't need to add &layouts
to the director's URL.
Using these URLs change the layout of your scene in OBS. The URL you should use in OBS is the default one:
https://vdo.ninja/?scene&room=roomname
https://docs.google.com/spreadsheets/d/1cHBTfni-Os3SAITsXrrNJ3qVCMVjunuW3xugvw1dykw/edit#gid=151839312
Download it and save it as .xlsx - then you can edit it and create custom layouts for the &layouts
parameter.
{% content-ref url="and-slotmode.md" %} and-slotmode.md {% endcontent-ref %}
{% content-ref url="../../general-settings/api.md" %} api.md {% endcontent-ref %}
{% content-ref url="../mixer-scene-parameters/and-layout.md" %} and-layout.md {% endcontent-ref %}
Director Option! (&director
)
&maindirpass
Example: &maindirectorpassword=SomePassword123
Value | Description |
---|---|
(alphanumeric-characters only) | the password you want to set for the main director |
&maindirectorpassword
lets you set a pseudo 'master room password' as a director. It helps avoid getting locked out as the director, if someone else tries to claim the director-role first. ie:
https://vdo.ninja/?director=ROOMNAME&maindirectorpassword=MASTERPASS
This will add a &token
value to the invite/scene links.
This token is used by the guests to check a remote database server to see who currently 'owns' the token; it persists though, even if the director is not connected.
When using &maindirectorpassword
as a director, it tells this database that you are the owner, and it will persist even if you aren't connected to VDO.Ninja. The &token
tells the guest to ignore other logic about who the director is, instead using the info provided by the token-lookup to determine whose the director.
I may change or revoke this feature, depending on how testing goes this week, as it's rather experimental.
{% content-ref url="../setup-parameters/and-password.md" %} and-password.md {% endcontent-ref %}
{% content-ref url="../../director-settings/codirector.md" %} codirector.md {% endcontent-ref %}
{% content-ref url="../settings-parameters/and-token.md" %} and-token.md {% endcontent-ref %}
Director Option! (&director
)
&novice
hides some advanced guest items in the director's control center.
{% content-ref url="../../viewers-settings/director.md" %} director.md {% endcontent-ref %}
Director Option! (&director
)
There is a new button in the director's room. It lets you toggle between a Preview layout and the normal Director layout; the Preview layout will mirror what a basic &scene=0
link would look like.
Useful if you want to switch to a guest-like mode as a director, and then switch back as needed to the director's room to make adjustments. To enter this mode by default,&previewmode
can be used by the director.
{% content-ref url="../view-parameters/scene.md" %} scene.md {% endcontent-ref %}
{% content-ref url="../../viewers-settings/director.md" %} director.md {% endcontent-ref %}
Director Option! (&director
)
Adding &slotmode
to a director's URL gives you the possibility to assign slots to the connected guests. While the layout switching options of the Video Mixer will be missing when doing this as a normal director, you can still specify &layout
via the URL for multiple scenes that will obey the slot assignments (might interest advanced users or inspire user suggestions).
{% content-ref url="../../steves-helper-apps/mixer-app.md" %} mixer-app.md {% endcontent-ref %}
{% content-ref url="../settings-parameters/and-slot.md" %} and-slot.md {% endcontent-ref %}
{% content-ref url="../mixer-scene-parameters/and-layout.md" %} and-layout.md {% endcontent-ref %}
{% content-ref url="../../viewers-settings/director.md" %} director.md {% endcontent-ref %}
Parameters specified for the director's control panel; have to be used together with the &director
parameter.
Parameter | Explanation |
---|---|
&director | Enters a room as the director, instead of a guest and have full control |
&codirector | Allows assistant directors to have access to the director's room, with a subset of control |
&blindall | It allows the director 'blinding' all the guests at a time with a new button |
&cleandirector | Hides the invite URL options in the Director's room |
&hidesolo | Lets you hide the solo links from showing |
&hidecodirectors | Hides the co-directors from appearing in the director's room |
&minidirector | Default mini director stylesheet |
&orderby | Orders guest's by their stream ID in the director's room |
&queue | A basic guest queuing system |
&rooms | Quick director access to a list of rooms for transfering guests |
&broadcasttransfer | Will let you specify the default for whether to transfer a guest from room to room in broadcast mode or not |
&showdirector | Lets the director perform alongside guests, showing up in scene-view links |
&slotmode | Gives you the possibility to assign slots to the connected guests |
&previewmode | Activates the Preview layout for the director's room by default |
&novice | Hides some advanced guest options in the director's control center |
&layouts | An ordered array of layouts, which can be used to switch between using the API layouts action |
&maindirectorpassword | Lets you set a pseudo 'master room password' as a director |
Parameter | Explanation |
---|---|
&totalroombitrate | The total bitrate the guests in a room can view video streams with |
&limittotalbitrate | Limits the total outbound bitrate |
¬ify | Audio alerts for raised hands, chat messages and if somebody joins the room |
&mutespeaker=0 | Can be used to have the director join unmuted |
&showconnections | Displays the total number of p2p connections of a remote stream |
&widget | Will load a side-bar for guests with an IFrame embed, with support for YouTube / Twitch / Social Stream |
Sender-Side Option! (&push
, &room
)
&queue3
&hold
added, with the alias &queue3
, which is like &queue
, except the guest gets a message telling them they need to wait until approved by the director. They don't see the director until activated, and the director doesn't see the guest's video/audio either - just their control box with any label. Once activated, the director will see the guest's video/audio, and vice versa.
This mode do not apply when you have &queue
also on the director's link, however, rather just when added to the guest-invite link only.
Transferring the guest to another room will also automatically activate the guest. You don't need to press the pink 'activate' button if you just intend to transfer them and don't want to talk to the guest you are screening.
{% content-ref url="../../general-settings/queue.md" %} queue.md {% endcontent-ref %}
{% content-ref url="and-holdwithvideo-alpha.md" %} and-holdwithvideo-alpha.md {% endcontent-ref %}
{% content-ref url="and-screen-alpha.md" %} and-screen-alpha.md {% endcontent-ref %}
description: >- Just like &hold, except the director does see the guest's video and audio before the guest is activated
Sender-Side Option! (&push
, &room
)
&queue4
&holdwithvideo
added, with the alias &queue4
, which is just like &hold
, except the director does see the guest's video and audio before the guest is activated. The guest can't see the director until activated, but does get a message telling them they are waiting to be activated.
This mode do not apply when you have &queue
also on the director's link, however, rather just when added to the guest-invite link only.
Transferring the guest to another room will also automatically activate the guest. You don't need to press the pink 'activate' button if you just intend to transfer them and don't want to talk to the guest you are screening.
{% content-ref url="../../general-settings/queue.md" %} queue.md {% endcontent-ref %}
{% content-ref url="and-hold-alpha.md" %} and-hold-alpha.md {% endcontent-ref %}
{% content-ref url="and-screen-alpha.md" %} and-screen-alpha.md {% endcontent-ref %}
description: >- Replaces the way &queue worked before, where the guest can see/hear the director, but not other guests, until activated
Sender-Side Option! (&push
, &room
)
&queue2
&screen
now replaces the way &queue
worked before, where the guest can see/hear the director, but not other guests, until activated.
&queue
was changed to not allow the guest to see the director's video, until the director activates the guest with their pink activate-guest button. Otherwise, it's the same as before.
&queue2
is given the alias &screen
, intending to imply you can use this mode to screen incoming guests by talking to them, before approving them.
This mode do not apply when you have &queue
also on the director's link, however, rather just when added to the guest-invite link only.
Transferring the guest to another room will also automatically activate the guest. You don't need to press the pink 'activate' button if you just intend to transfer them and don't want to talk to the guest you are screening.
{% content-ref url="../../general-settings/queue.md" %} queue.md {% endcontent-ref %}
{% content-ref url="and-hold-alpha.md" %} and-hold-alpha.md {% endcontent-ref %}
{% content-ref url="and-holdwithvideo-alpha.md" %} and-holdwithvideo-alpha.md {% endcontent-ref %}
Parameter | Explanation |
---|---|
&queue | A basic guest queuing system |
Parameter | Explanation |
---|---|
&screen * | Replaces the way &queue worked before, where the guest can see/hear the director, but not other guests, until activated |
&hold * | Like &queue , except the guest gets a message telling them they need to wait until approved by the director |
&holdwithvideo * | Just like &hold , except the director does see the guest's video and audio before the guest is activated |
&queuetransfer | Will transfer a guest from one room into another, but once transferred, the guest will be in Queue mode |
Meshcast Option / Sender-Side Option! (&meshcast
, &push
)
&mcaudiobitrate
&mcab
&meshcastab
Example: &meshcastaudiobitrate=128
Value | Description |
---|---|
(integer value) | publishing Meshcast audio bitrate in kbps |
&meshcastab
controls the outbound audio bitrate of the &meshcast
parameter. Without it, it will be a variable bitrate, up to 32-kbps per channel. With it added, it will be CBR, at the specified bitrate.
{% content-ref url="../../newly-added-parameters/and-meshcast.md" %} and-meshcast.md {% endcontent-ref %}
{% content-ref url="../../meshcast-settings/and-meshcastbitrate.md" %} and-meshcastbitrate.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&mccode
Example: &meshcastcode=usw2
Value | Description |
---|---|
(no value given) | Chooses the best server automatically |
(servercode) | Chooses the selected Meshcast server |
Full server list: https://meshcast.io/servers.json
&meshcastcode
lets you specify the Meshcast server to use. This was already possible with just &meshcast
, but if you wanted to specify audio/video-only modes as well as the server, this new option will let you specify the server another way, allowing both options to work.
ie: https://vdo.ninja/?meshcastcode=cae1&meshcast=video
You can select the Meshcast server via URL Parameter, if you want low-level control there.
If you don't set it, the best one will be chosen automatically. If the specified one isn't found, the next best is used.
Example: &meshcastcode=usw2
Value | Description |
---|---|
(servercode) | Meshcast server |
cae1 | Canada-East 1 |
cae2 | Canada-East 2 |
use1 | USA-East 1 |
use2 | USA-East 2 |
usw1 | USA-West 1 |
usw2 | USA-West 2 |
fr1 | France |
de1 | Germany |
usc1 | Dev-server |
Full server list: https://meshcast.io/servers.json
{% content-ref url="../../newly-added-parameters/and-meshcast.md" %} and-meshcast.md {% endcontent-ref %}
{% embed url="https://meshcast.io/" %} https://meshcast.io/ {% endembed %}
Viewer-Side Option! (&view
, &scene
, &room
, &solo
)
&nomeshcast
is a viewer-side option that tells a sender to provide a p2p stream, rather than a Meshcast stream, if they have &meshcast
active. A bit of a niche option, but might be useful if bandwidth or latency is a consideration for a specific viewer, like the director.
{% content-ref url="../../newly-added-parameters/and-meshcast.md" %} and-meshcast.md {% endcontent-ref %}
description: >- Options for the &meshcast parameter like audio filters, bitrate, screen-share, codecs etc.
Meshcast Parameters are specific to the &meshcast
parameter. They are all parameters for the publisher's side (&push
) and have to be used together with &meshcast
.
Parameter | Explanation |
---|---|
&meshcast | Triggers the service, causing the outbound audio/video stream to be transferred to a hosted server |
&meshcastaudiobitrate | Option to change outbound audio bitrate of the &meshcast parameter |
&meshcastbitrate | Option to change outbound video bitrate of the &meshcast parameter |
&meshcastcodec | Option to change codec of the &meshcast parameter |
&mcscreensharebitrate | Option to change outbound screen-share video bitrate of the &meshcast parameter |
&mcscreensharecodec | Option to change codec of the &meshcast parameter while screen-sharing |
&meshcastscale | Scales down the Meshcast video output via the URL |
&meshcastcode | Lets you specify the Meshcast server to use |
Parameter | Explanation |
---|---|
&nomeshcast | Tells a sender to provide a p2p stream, rather than a Meshcast stream |
Viewer-Side Option! (&view
, &scene
, &room
)
&fakefeeds
Example: &fakeguests=7
Value | Description |
---|---|
(integer number) | creates simulated guest videos, based on the value passed to the parameter |
(no value given) | 4 fake guests added |
&fakeguests=N
creates simulated guest videos, based on the value passed to the parameter, using real-guests where possible. The default value is 4.
You can use this feature to help position and visualize what &cover
, &portrait
, etc. looks like.
This doesn't yet support labels or layouts really, but I welcome feedback. Currently I just threw up a video of me, 16:9, of 500-kbps.
You don't actually need to create a room / scene to play with it.
Try it at: https://vdo.ninja/?room=xxxxtestxxxx&scene&cover&square&fakeguests=7
{% content-ref url="../view-parameters/cover.md" %} cover.md {% endcontent-ref %}
{% content-ref url="../view-parameters/scene.md" %} scene.md {% endcontent-ref %}
description: >- Keeps all incoming videos oriented (rotated) so that the aspect ratio is always above 1
Viewer-Side Option! (&scene
, &room
)
Example: &forceviewerlandscape=90
Value | Description |
---|---|
(value in degrees) | value, how much the video is rotated in degree |
(no value given) | 270 |
180 | locked upside down |
&forceviewerlandscape
keeps all incoming videos oriented (rotated) so that the aspect ratio is always above 1, so effectively, forces landscape mode.
ie: https://vdo.ninja/?forceviewerlandscape&view=xxx
This normally shouldn't be needed, as the sender side should control the orientation, but the native app seems to auto rotate back to portrait when the phone is locked. Until that is fixed, this can work around the issue I think, by rotating the video when it detects its been rotated.
The parameter can take a value, the default is 270
, which is how much the video is rotated. You might want to also use 90
, or in the case you want it to be locked upside down, you can technically pass 180
I guess?
{% content-ref url="../video-parameters/and-aspectratio.md" %} and-aspectratio.md {% endcontent-ref %}
{% content-ref url="../mobile-parameters/and-forcelandscape.md" %} and-forcelandscape.md {% endcontent-ref %}
description: >- Will hide the default big play button that overlays a video when auto play is not allowed
Viewer-Side Option! (&view
, &scene
, &room
)
&hpb
&hideplaybutton
will hide the default big play button that overlays a video when auto play is not allowed. This option is useful when you want to perhaps include your own playbutton as part of the poster image.
Example of the command:
https://vdo.ninja/?view=YbFmisR&poster=./media/bg_sample.webp&hideplaybutton
{% content-ref url="and-poster.md" %} and-poster.md {% endcontent-ref %}
Viewer-Side Option! (&scene
, &room
)
Example: &include=StreamID
Value | Description |
---|---|
(stream ID) | stream ID of a publisher outside of a room with a matching password |
&include
, which is like &view
, except it's for including streams that do not exist in the room you are in, assuming those streams are not in another room and have matching passwords. So, useful for adding basic push-streams that you might want to be in multiple rooms at the same time, but not actually be locked to any room. (&view
, conversely, is pretty exclusive; that or nothing.)
{% content-ref url="../view-parameters/view.md" %} view.md {% endcontent-ref %}
{% content-ref url="../view-parameters/and-exclude.md" %} and-exclude.md {% endcontent-ref %}
Viewer-Side Option! (&room
, &view
)
Adding &layout
to a guest link shows the guest a return feed of the current mixer layout when using the Mixer App.
{% content-ref url="../../steves-helper-apps/mixer-app.md" %} mixer-app.md {% endcontent-ref %}
{% content-ref url="../director-parameters/and-layouts.md" %} and-layouts.md {% endcontent-ref %}
description: >- Will force a the VDO.Ninja's mixer output keep the mixed render contained to a specific aspect-ratio, regardless of the browser's window size
Viewer-Side Option! (&scene
)
Example: &locked=portrait
Value | Description |
---|---|
landscape | (no value given) | 16:9 aspect ratio |
portrait | 9:16 aspect ratio |
square | 1:1 aspect ratio |
1.77777 | aspect ratio |
&locked
will force a the VDO.Ninja's mixer output keep the mixed render contained to a specific aspect-ratio, regardless of the browser's window size. (as seen in photo)
You'll get black bars (or whatever the background color is) as padding on the sides to force the inner video elements into the desired aspect ratio
When using &locked
, the default aspect ratio is 16:9, but you can pass a floating point value for different aspect ratios, or use landscape
(instead of 1.77777
) / portrait
/ square
as presets if needed.
Padding is centered, so the rendered video will be in the center of the screen. (tho using &widget
mode might break things though).
This &locked
option is added to the Mixer App's WHIP/Twitch publishing output option, so regardless of window size, you'll get a 16:9 video render.
{% content-ref url="../design-parameters/and-structure.md" %} and-structure.md {% endcontent-ref %}
{% content-ref url="../video-parameters/and-aspectratio.md" %} and-aspectratio.md {% endcontent-ref %}
Viewer-Side Option! (&scene
, &room
)
&motionswitch
Example: &motiondetection=40
Value | Description |
---|---|
1 to 64 | sensitivity of the motion detection trigger as a value |
(no value given) | sensitivity 15 of the motion detection trigger |
&motiondetection
does a few things when it detects motion in a video (viewer-side).
It will feature highlight the specific video where movement is detected, if more than one video is included in the mix. Using a custom &layout
will disable this feature though, and use the layout instead.
It will also trigger an IFrame API event, which might be useful if you want to use VDO.Ninja as a security camera; you could script things to auto-record the video or log data events.
It will also switch to itself in OBS as a scene, which might be how this will be mainly used. (you need to have the OBS browser source's page permission set to high to allow this to actually work)
You can adjust the sensitivity of the motion detection trigger as a value; the default I think is 15, but it can be between 1 and 64 I think.
{% content-ref url="../view-parameters/activespeaker.md" %} activespeaker.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
Example: &poster=./media/bg_sample.webp
Value | Description |
---|---|
(encoded URL) | takes an encoded URL, pointing to a CORS-accessible image file |
&poster
lets you specify a poster image for videos that have not yet started playing (using the built-in HTML poster attribute). This flag takes an encoded URL, pointing to a CORS-accessible image file.
Example of the command:
https://vdo.ninja/?view=YbFmisR&poster=./media/bg_sample.webp&hideplaybutton
{% content-ref url="and-hideplaybutton.md" %} and-hideplaybutton.md {% endcontent-ref %}
Viewer-Side Option! (&room
)
&solo
is used to bring a solo-link of a guest in a room into OBS Studio.
https://vdo.ninja/?view=streamid1&room=roomname&solo
This tells the system to only view streamid1
in the specified room. &solo
and &scene
also tells the system not to be a publisher, but a viewer.
This parameter behaves just as &scene
. The only difference is, that the system does not apply custom 'layouts' to &solo
links.
Links updates in the director's room from Version 22 onwards.
{% content-ref url="../view-parameters/scene.md" %} scene.md {% endcontent-ref %}
description: Layout and design for the mixer in rooms/scenes, preload/hidden scene bitrate
Mixer/Scene Parameters are viewer side options. You can add them to guest's URLs in rooms and scene URLs.
You have to add them to &scene
or &room
or &view
URLs to change the behaviour of the Video Mixer.
Parameter | Explanation |
---|---|
&solo | Similar to &scene , but tells the system to be a solo-link |
&view | Defines the stream(s) you are receiving, by their stream IDs |
&include | Includes streams that do not exist in the room |
&exclude | Same concept as &view , except does the opposite |
&layout | Shows the guest a return feed of the current mixer layout when using the Mixer App |
&activespeaker | Auto-hides remote guests videos when added, if those guests are not speaking actively |
&order | The order priority of a source video when added to the video mixer |
&slots | Will force the auto-mixer to have that number of slots, even if there are more or less videos available to fill them |
&fakeguests | Creates simulated guest videos |
&randomize | Random video loading order |
&cover | Has the videos fully "cover" their assigned areas, even if it means cropping the video |
&43 | Optimizes the video mixer for 4:3 videos |
&portrait | Optimizes the video mixer for 9:16 videos |
&square | Optimizes the video mixer for 1:1 videos |
&forceviewerlandscape * | Keeps all incoming videos oriented (rotated) so that the aspect ratio is always above 1 |
&animated | Videos in a group scene will slide around the screen when being re-arranged |
&manual | Disables the auto-mixer, allowing for a custom mixer to be used |
&locked | Will force a the VDO.Ninja's mixer output keep the mixed render contained to a specific aspect-ratio, regardless of the browser's window size |
&poster | Lets you specify a poster image for videos that have not yet started playing |
&hideplaybutton | Will hide the default big play button that overlays a video when auto play is not allowed |
&motiondetection * | Does a few things when it detects motion in a video |
*NEW IN VERSION 24
You have to add them to &scene
or &view
URLs.
Parameter | Explanation |
---|---|
&scene | Defines the link to be treated like a scene |
&scenetype | Shows only the last added video to a scene |
&autoadd | Auto-adds the specified stream IDs to the scene |
&hiddenscenebitrate | Can be used to force videos not added yet to a scene to run at the specified bitrate |
&preloadbitrate | Can be used to change the pre-load target bitrate for scenes |
&waitimage | You can add a custom image which shows up while waiting for the &scene or &view link |
&waitmessage | You can add a custom message which shows up while waiting for the &scene or &view link |
&waittimeout | Specifies a delay for &waitimage and &waitmessage while waiting for the &scene or &view link |
Viewer-Side Option! (&scene
)
&type
Example: &scenetype=2
Value | Description |
---|---|
1 | just shows the last guest that was added in the scene, but doesn't mute the previous guests |
2 | just shows the last guest that was added in the scene |
3 | the general idea is it will only show the video that is in a particular ordered position (default, position = 1), rather than all the videos in the scene |
You can change the behaviour of scenes a bit with this parameter.
&scenetype
can be set to 1
or 2
, which overrides the default scene state.
Scene state of 1 and 2 will only show the last video added to a group scene. &scenetype=2
will mute the other videos, while &scenetype=1
will not mute previously added videos.
&scenetype=3
- Usage is like this: &scene&room=roomname&scenetype=3&order=1
, where &order=N
is optional. This feature isn't set in stone yet, but the general idea is it will only show the video that is in a particular ordered position (default, position = 1), rather than all the videos in the scene. When someone leaves, the spots are recalculated. The order that the positions are based on is calculated via alphanumeric sorting of connection IDs, though I wish to improve this to be probably sync with the director's order. Anyways, this feature was a result of a user request.
This URL parameter option is a bit of a hack currently and may be replaced in the future.
This parameter is added to scene view links.
{% content-ref url="../view-parameters/scene.md" %} scene.md {% endcontent-ref %}
{% content-ref url="../../source-settings/order.md" %} order.md {% endcontent-ref %}
description: >- Loads the site into an "app mode" and allows you to load a new URL via the website itself
Sender-Side Option! (&push
)
&app
loads the site into an "app mode" and allows you to load a new URL via the website itself.
This parameter is enabled in the mobile native app's new website-mode option by default (the screen share option is also hidden).
Sender-Side Option! (&push
)
Example: &facing=rear
Value | Description |
---|---|
rear | environment | back | rear-facing camera |
front | user | front-facing camera |
The &facing
setting lets you specify either the front or rear facing camera as the default camera. Passing one of rear
, environment
, back
, front
, and user
are required to specify whether to select back or front.
Example usage:https://vdo.ninja/?webcam&facing=rear
&facing
takes priority over &videodevice
, but it will fail to &videodevice
or the default behaviour if the rear/front camera can't be selected automatically. If there are multiple rear or front cameras, it will use the first one. &videodevice=0
will disable the video outright.
{% content-ref url="and-forcelandscape.md" %} and-forcelandscape.md {% endcontent-ref %}
{% content-ref url="and-forceportrait.md" %} and-forceportrait.md {% endcontent-ref %}
Sender-Side Option! (&push
)
By default, iOS devices do not publish video to other guests in a group room.
{% hint style="danger" %} iOS devices can publish THREE (3) video streams at any one time, before things explode. {% endhint %}
{% content-ref url="and-notios.md" %} and-notios.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&forcedlandscape
&fl
Forces the video output to landscape mode (16:9), regardless of how the phone is rotated.
You add this flag to the sender's side, and it applies to the sender and the viewers of that video stream. There is a short sub-second delay that it takes to counter-act any system-flipping. It can be used in conjunction with &rotate
, if you need to do a 180 or something also.
{% content-ref url="and-forceportrait.md" %} and-forceportrait.md {% endcontent-ref %}
{% content-ref url="../mixer-scene-parameters/and-forceviewerlandscape.md" %} and-forceviewerlandscape.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&forcedportrait
&fp
Forces the video output to portrait mode (9:16), regardless of how the phone is rotated.
You add this flag to the sender's side, and it applies to the sender and the viewers of that video stream. There is a short sub-second delay that it takes to counter-act any system-flipping. It can be used in conjunction with &rotate
, if you need to do a 180 or something also.
{% content-ref url="and-forcelandscape.md" %} and-forcelandscape.md {% endcontent-ref %}
Sender-Side Option! (&push
)
¬ios
, as in "not iOS", just tells the system that it's not an iOS device, or iPad, even if it is. This might change the behavior of the phone in certain ways, mainly for the purposes of debugging.
{% content-ref url="and-forceios.md" %} and-forceios.md {% endcontent-ref %}
All these options are for push links and guest invite links in a room (&push
/ &room
)
Parameter | Explanation |
---|---|
&facing | Lets you specify either the front or rear facing camera as the default camera |
&forcelandscape | Forces the video output to landscape mode, regardless of how the phone is rotated |
&forceportrait | Forces the video output to portrait mode, regardless of how the phone is rotated |
&forceios | Forces iOS devices to publish video to this room |
¬ios | Just tells the system that its not an iOS device, or iPad, even if it is |
&flagship | Will optimize the mobile experience for more capable smartphones |
&mobile | Optimizes a guest/push link for a mobile device to help reduce CPU issues |
¬mobile | Optimizes a guest/push link for a mobile device to improve video quality |
&app | Loads the site into an "app mode" and allows you to load a new URL via the website itself |
General Option! (&push
, &room
, &view
, &scene
)
&controls
Example: &videocontrols=false
Value | Description |
---|---|
(no value given) | Shows the video control bar |
0 | false | off |
Hides the video control bar |
&videocontrols
will show the video control bar (provides access to full screen on mobile). You can also show the control bar with Right-Click
-> Show control bar
.
{% hint style="warning" %} This is not the same control bar as the user control bar. Also, be sure to not accidentally unmute yourself -- echo feedback galore. {% endhint %}
{% content-ref url="../buttons-and-control-bar-parameters/and-hands-1.md" %} and-hands-1.md {% endcontent-ref %}
{% content-ref url="../settings-parameters/and-nocontrols.md" %} and-nocontrols.md {% endcontent-ref %}
{% content-ref url="../../parameters-only-on-beta/and-autohide.md" %} and-autohide.md {% endcontent-ref %}
description: >- You can add a custom image which shows up while waiting for the &scene or &view link
Viewer-Side Option! (&scene
, &view
)
Example: &waitimage=https%3A%2F%2Fvdo.ninja%2Fmedia%2Flogo_cropped.png
Value | Description |
---|---|
(encoded URL) | Specifies a custom image |
This is for when waiting for the &scene
or &view
link to load. You can add a custom image which shows up while waiting for the &scene
or &view
link.
It fits to the screen, and &cover
will have it 'cover' the screen.
When using &waitimage
, the specified 'waiting to connect' image will appear after all connections end.
It overrides &cleanoutput
.
You can encode the URL here:
https://www.urlencoder.org/
{% content-ref url="and-waitmessage.md" %} and-waitmessage.md {% endcontent-ref %}
{% content-ref url="and-waittimeout.md" %} and-waittimeout.md {% endcontent-ref %}
{% content-ref url="../design-parameters/and-bgimage.md" %} and-bgimage.md {% endcontent-ref %}
{% content-ref url="../design-parameters/and-background.md" %} and-background.md {% endcontent-ref %}
description: >- You can add a custom message which shows up while waiting for the &scene or &view link
Viewer-Side Option! (&scene
, &view
)
Example: &waitmessage=hello
Value | Description |
---|---|
(string) | Specifies a message |
This is for when waiting for the &scene
or &view
link to load. You can add a custom message which shows up while waiting for the &scene
or &view
link.
It overrides &cleanoutput
.
{% content-ref url="and-waitimage.md" %} and-waitimage.md {% endcontent-ref %}
{% content-ref url="and-waittimeout.md" %} and-waittimeout.md {% endcontent-ref %}
description: >- Specifies a delay for &waitimage and &waitmessage while waiting for the &scene or &view link
Viewer-Side Option! (&scene
, &view
)
Example: &waittimeout=3000
Value | Description |
---|---|
(integer value) | Delay in ms |
This is for when waiting for the &scene
or &view
link to load. It specifies a delay for &waitimage
and &waitmessage
while waiting for the &scene
or &view
link.
It overrides &cleanoutput
.
{% content-ref url="and-waitimage.md" %} and-waitimage.md {% endcontent-ref %}
{% content-ref url="and-waitmessage.md" %} and-waitmessage.md {% endcontent-ref %}
description: >- If the total bitrate drops below the specified bitrate, the viewer will auto-hide the audio and video for that stream
Viewer-Side Option! (&view
, &scene
, &room
)
&bitcut
Example: &bitratecutoff=500
Value | Description |
---|---|
(no value given) | video cuts off under 300-kbps |
(integer value) | cut off bitrate in kbps |
&bitratecutoff
is a viewer-side parameter. If the total bitrate drops below the specified bitrate (default value of 300), the viewer will auto-hide the audio and video for that stream. It will un-hide once the average bitrate returns above 300-kbps.
{% hint style="info" %} There is a 3-second delay in calculating the average bitrate. Won't work with viewers that are Firefox/Safari; just Chrome/Chromium, so OBS, vMix, Electron Capture, Chrome. This is because Firefox/Safari lack the stats in VDO.Ninja needed to trigger this. {% endhint %}
When using &bitratecutoff
on a room scene, it won't trigger due to a director being in the room with no video, unless they are using &showdirector
.
{% content-ref url="../settings-parameters/and-cutscene.md" %} and-cutscene.md {% endcontent-ref %}
{% content-ref url="and-statsinterval.md" %} and-statsinterval.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
Example: &statsinterval=1500
Value | Description |
---|---|
(no value given) | stats update interval = 3000-ms |
(integer value) | stats update interval in ms |
&statsinterval
lets you change the default stats update interval from 3-seconds to something else. Changing it to 1-second or 10-seconds might suit your needs better when using &bitratecutoff
, or if you just want frequent updates. Changing the stats interval will impact the auto-keyframe fix feature, potentially breaking it, but this won't be an issue with OBS 27.2 and onwards.
{% content-ref url="and-bitratecutoff.md" %} and-bitratecutoff.md {% endcontent-ref %}
{% content-ref url="../../general-settings/and-stats.md" %} and-stats.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
)
Example: &autorecord=1500
Value | Description |
---|---|
0 | No video recorded; audio tentatively recorded as 32bit PCM lossless. |
(negative integer) | No video recorded; audio recorded as {integer} kbps OPUS file. eg: -120 - Audio only at 120 kbps. |
(positive integer) | Recorded video bitrate in kbps. |
&autorecord
will record the local and remote videos automatically on their initial load. This applies to the director, guest, scenes, and whatever really.
You can stop/restart recordings as needed via the right-click menu per each video for now, until I can design a nicer UI for managing multi-recording state at least.
You can pass the default recording bitrate as a value to the parameter, like you might if using &record
.
Update in v23
There are buttons in the room settings of the director to start/stop all recordings; both remote/local.
{% content-ref url="and-record.md" %} and-record.md {% endcontent-ref %}
{% content-ref url="and-autorecordlocal.md" %} and-autorecordlocal.md {% endcontent-ref %}
{% content-ref url="and-autorecordremote.md" %} and-autorecordremote.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
)
Example: &autorecordlocal=2000
Value | Description |
---|---|
0 | No video recorded; audio tentatively recorded as 32bit PCM lossless. |
(negative integer) | No video recorded; audio recorded as {integer} kbps OPUS file. eg: -120 - Audio only at 120 kbps. |
(positive integer) | Recorded video bitrate in kbps. |
&autorecordlocal
will record the local video automatically on their initial load. This applies to the director, guest, scenes, and whatever really.
You can stop/restart recordings as needed via the right-click menu per each video for now, until I can design a nicer UI for managing multi-recording state at least.
You can pass the default recording bitrate as a value to the parameter, like you might if using &record
.
Update in v23
There are buttons in the room settings of the director to start/stop all recordings; both remote/local.
{% content-ref url="and-record.md" %} and-record.md {% endcontent-ref %}
{% content-ref url="and-autorecord.md" %} and-autorecord.md {% endcontent-ref %}
{% content-ref url="and-autorecordremote.md" %} and-autorecordremote.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
)
Example: &autorecordremote=1500
Value | Description |
---|---|
0 | No video recorded; audio tentatively recorded as 32bit PCM lossless. |
(negative integer) | No video recorded; audio recorded as {integer} kbps OPUS file. Eg: -120 - Audio only at 120 kbps. |
(positive integer) | Recorded video bitrate in kbps. |
&autorecordremote
will record the remote video(s) automatically on their initial load. This applies to the director, guest, scenes, and whatever really.
You can stop/restart recordings as needed via the right-click menu per each video for now, until I can design a nicer UI for managing multi-recording state at least.
You can pass the default recording bitrate as a value to the parameter, like you might if using &record
.
Update in v23
There are buttons in the room settings of the director to start/stop all recordings; both remote/local.
{% content-ref url="and-record.md" %} and-record.md {% endcontent-ref %}
{% content-ref url="and-autorecord.md" %} and-autorecord.md {% endcontent-ref %}
{% content-ref url="and-autorecordlocal.md" %} and-autorecordlocal.md {% endcontent-ref %}
Sender-Side Option! (&push
)
Video recordings will be saved as Video + PCM audio format.
WebM is a universal container of sorts when used within a Chromium browser, but it doesn't always work well for VLC or popular video editors. FFmpeg can be used to convert to other formats though, including MP4 and WAV, typically without transcoding.
To make converting from WebM to other formats easier, a version of FFmpeg is hosted within VDO.Ninja for this. It can be located here at https://vdo.ninja/convert, with several of the most common conversion options ready to go, such as WebM-PCM to WAV-PCM.
Due to memory limits and other browser limitations, this FFmpeg tool can only process files under about 2-gigabytes in size. For larger files, you may need to download and use a desktop version of FFmpeg instead.
FFmpeg command lines are provided if you choose to run FFmpeg yourself locally, but if that is still to complicated, you can grab Handbrake for free; it's a GUI-based option that is fairly accessible.
{% content-ref url="and-record.md" %} and-record.md {% endcontent-ref %}
Sender-Side Option! (&push
)
Example: &record=1000
Value | Description |
---|---|
0 | No video recorded; audio tentatively recorded as 32bit PCM lossless |
(negative integer) | No video recorded; audio recorded as {integer} kbps OPUS file. Eg: -120 - Audio only at 120 kbps |
(positive integer) | Recorded video bitrate in kbps |
false | off | Will disable the user from being able to record a video. Buttons for recording are hidden/deleted and the recording function is disabled when used; so the director won't even be able to trigger it remotely |
File format
``- WebM.
File Codec:
``H264 or VP8 for video; OPUS or PCM for audio.
Usually up to the browser.
Default bitrate will record at around 4000 kbps, but it will still prompt still for value if not set.
The Director of a room will be notified if a user is recording and they can start/stop the recording.
The Director of a room can trigger the record function remotely, even if the &record parameter has not been added.
The video/audio will be saved in real-time to the guest's local download folder.
Do not force-close the browser or turn off the computer while it is recording; you may lose the file or have a partial capture.
The recording should stop automatically when the guest hangs-ups manually. I try my best to do the same when the browser is closed, but it's best to still purposefully stop recording first.
It will automatically capture with stereo audio and echo cancellation off, if available.
You can use https://isolated.vdo.ninja/convert to convert from WebM file formats to OPUS or WAV file formats, without transcoding and without downloads. More about converting from WebM to MP4 or WAV here.
When recording as the director, the button and option to record each guest is available by default. It's hidden behind Advanced controls. You have the option to record locally, to your own disk, or record remotely, directly to the remote guest's local storage.
When recording to the guest's local storage, quality should be near pristine, given as its not being sent via the Internet first. Recording locally, the video may have dynamic resolutions and varying quality, due to the low latency transmission. (&chunked
-mode excepted)
Anyone can also access the recording options via right-clicking a video. This option is available as of VDO.Ninja v22.
Threshold | Inbound Audio | Recorded audio |
---|---|---|
4000 | 128 kpbs | 128 kpbs |
2500 | 80 kbps | 128 kpbs |
Less than 2500 | 32 kbps | 32 kbps |
When using &chunked
mode
When the sender of a stream is using the &chunked
mode, recording their video will save the inbound video directly to disk without transcoding. Not needing to transcode the saved video in the browser is only possible with the &chunked
mode. Of course, you also don't have the option to increase the bitrate or change codecs when using this mode; at least not as the viewer.
The chunked mode (as of June 2022) is still a maturing feature. Please report any issues and provide feedback.
WebM is a universal container of sorts when used within a Chromium browser, but it doesn't always work well for VLC or popular video editors. FFmpeg can be used to convert to other formats though, including MP4 and WAV, typically without transcoding.
To make converting from WebM to other formats easier, a version of FFmpeg is hosted within VDO.Ninja for this. It can be located here at https://vdo.ninja/convert, with several of the most common conversion options ready to go, such as WebM-PCM to WAV-PCM.
Due to memory limits and other browser limitations, this FFmpeg tool can only process files under about 2-gigabytes in size. For larger files, you may need to download and use a desktop version of FFmpeg instead.
FFmpeg command lines are provided if you choose to run FFmpeg yourself locally, but if that is still to complicated, you can grab Handbrake for free; it's a GUI-based option that is fairly accessible.
Lastly, sometimes a video recorded by VDO.Ninja will have a variable resolution or/and frame rate, which can cause problems with some video editors. For example, the quality might be stuck low, or it might freeze after a few seconds. In these cases, you may need to transcode the video to a fixed resolution and frame rate using FFmpeg (or Handbrake) first, before using.. Transcoding is very slow in the browser, so I'd recommend you download Handbrake or FFmpeg for this task.
{% embed url="https://vdo.ninja/convert" %} FFmpeg in the browser; up to 4-gb file sizes {% endembed %}
{% hint style="info" %}
When recording with PCM, (&pcm
) the inbound audio bitrate will be at 256-kbps. (regardless of video bitrate)
{% endhint %}
{% hint style="warning" %}
- If recording with an Nvidia/AMD graphics card installed on your computer, ensure your drivers are up to date or try recording with VP8-codec instead. Hardware-encoding might reduce CPU load, but it can also result in discolored video if the driver is buggy.
- Safari browsers and iOS devices may struggle with media recording.
- Enabling Safari's MediaRecorder under E_xperimental webKit Features_ may be needed. As well, users may be asked to download a file once the recording ends, for the webM media file to be saved correctly to disk. {% endhint %}
{% content-ref url="and-recordcodec.md" %} and-recordcodec.md {% endcontent-ref %}
{% content-ref url="and-autorecord.md" %} and-autorecord.md {% endcontent-ref %}
{% content-ref url="and-pcm.md" %} and-pcm.md {% endcontent-ref %}
Sender-Side Option / Director Option! (&push
, &director
)
&rc
Example: &recordcodec=h264
Value | Description |
---|---|
h264 | request the h264 codec |
vp8 | request the VP8 codec |
vp9 | request the VP9 codec |
av1 | request the AV1 codec |
Adding &recordcodec
to a source or director link lets you set the video recording codec (saving to disk mode; aka &record
). The container format is still WebM, and not all codecs are going to be supported, but things will fail back to vp8 if not supported. Main reason for this is because vp8 on chrome for android kinda stinks, so at least you have an option to tinker with things now.
As a guest or source side don't forget to add &record
to the URL to get the record button.
{% content-ref url="and-record.md" %} and-record.md {% endcontent-ref %}
{% content-ref url="../view-parameters/codec.md" %} codec.md {% endcontent-ref %}
{% content-ref url="and-pcm.md" %} and-pcm.md {% endcontent-ref %}
description: >- Takes a video snapshot and saves it to disk whenever there is motion detected in a video
General Option! (&push
, &room
, &view
, &scene
, &solo
)
&motionrecord
Example: &recordmotion=15
Value | Description |
---|---|
(integer value) | will control the sensitivity of the motion capture |
&recordmotion
takes a video snapshot and saves it to disk as a PNG file whenever there is motion detected in a video.
- Auto saves (to download folder) one photo per second, max.
- It can take values, such as
&recordmotion=15
, which will control the sensitivity of the motion capture - It's primarily designed for the sender-side, but I think it should work if a viewer also
- I don't think this will work within OBS, so Chrome/Chromium is recommended instead
- I guess the point of this is to allow for basic security camera operation, but also as a source of inspiration for other ideas
- File name of the saved file contains the timestamp
Parameter | Explanation |
---|---|
&record | Record functionality for guests |
&autorecord | Records the local video and the remote video(s) automatically on their initial load |
&autorecordlocal | Records just the local video automatically on their initial load |
&autorecordremote | Records just the remote video(s) automatically on their initial load |
&recordcodec | Lets you set the video recording codec |
&pcm | PCM audio recordings |
&recordmotion * | Takes a video snapshot and saves it to disk whenever there is motion detected in a video |
&chunked | Does not use webRTC's video streaming protocols; rather it uses a custom-made protocol |
*NEW IN VERSION 24
Sender-Side Option! (&push
)
Example: &displaysurface=monitor
Value | Description |
---|---|
monitor | Will pre-select "display-share" |
browser | Will pre-select "tab-share" |
window | Will pre-select "window-share" |
&displaysurface
will pre-select "display-share", rather than tab-share, when screen-sharing. You can pass monitor
, browser
, or window
as options to customize this though.
For more details on these new features see here:
https://developer.chrome.com/docs/web-platform/screen-sharing-controls/
(Chrome/chromium-browsers only)
{% content-ref url="../../source-settings/screenshare.md" %} screenshare.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&prefercurrenttab
will have the current tab as the default screen-share source.
For more details on these new features see here:
https://developer.chrome.com/docs/web-platform/screen-sharing-controls/
(Chrome/chromium-browsers only)
{% content-ref url="../../source-settings/screenshare.md" %} screenshare.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&ssar
Example: &screenshareaspectratio=landscape
Value | Description |
---|---|
(no value given) | overrides &aspectratio and sets the screen-share to the default aspect ratio |
(decimal number) | sets the screen-share aspect ratio |
landscape | screen-share aspect ratio of 16:9 (1.777777) |
portrait | screen-share aspect ratio of 9:16 (0.5625) |
square | screen-share aspect ratio of 1:1 (1) |
1.33333 | screen-share aspect ratio of 4:3 |
&screenshareaspectratio
sets the aspect ratio for screen-shares on the publisher side.
&aspectratio
works with screen-shares, so you can force crop an incoming screen-share to be a certain aspect ratio. If &screenshareaspectratio
is used it will apply to just screen-shares. If &screenshareaspectratio
does not have a value passed, it's assumed to be set as "default", which overrides &aspectratio
option, if used also.
{% content-ref url="../video-parameters/and-aspectratio.md" %} and-aspectratio.md {% endcontent-ref %}
description: >- =motion prioritizes screen-share frame rate; =detail prioritizes screen-share resolution
Sender-Side Option! (&push
)
&sscontenthint
&screensharecontenttype
&sscontent
&sshint
Example: &screensharecontenthint=detail
Value | Description |
---|---|
detail | will prioritize screen-share resolution over frame rate |
motion | will prioritize screen-share frame rate over resolution |
Depending on browser and version, there may be additional values you can pass, such as text
. Please see the following link for possible options that your browser may offer:
https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack/contentHint
&screensharecontenthint
can customize how you want VDO.Ninja to balance screen-share resolution vs screen-share frame rate, specifically when bitrate or CPU is insufficient to offer both at the same time.
The two options are detail
or motion
. Screen-shares generally tend towards detail
by default, and camera sources are tend towards motion
by default. detail
will try to prioritize resolution over frame rate, so the frame rate may drop a lot used. motion
will try to maximize frame rate, but may drop the resolution a lot. There's no way to force both on as there's no magic bullet if your CPU or network cannot keep up.
For more information on how to lock or maximize the resolution of a video feed, please see the following guide:
{% content-ref url="../../guides/how-do-i-lock-the-resolution.md" %} how-do-i-lock-the-resolution.md {% endcontent-ref %}
There is &contenthint
if you want the parameter to affect all kinds of video sources. You can also use both, &screensharecontenthint
will override &contenthint
for just screen-shares if set also.
{% hint style="info" %}
If using &codec=vp9
on the viewer side, the frame rate may drop as low as even 5-fps.
{% endhint %}
{% hint style="warning" %} This parameter has been tested on Chrome, but other browsers may vary in behavior. Safari seems to just ignore things, for example. {% endhint %}
{% content-ref url="../video-parameters/and-contenthint.md" %} and-contenthint.md {% endcontent-ref %}
Sender-Side Option! (&push
)
Example: &selfbrowsersurface=include
or &selfbrowsersurface=exclude
Value | Description |
---|---|
(no value given) | Excludes the current tab as a screen-share source option |
include | Includes the current tab as a screen-share source option |
exclude | Excludes the current tab as a screen-share source option |
&selfbrowsersurface
excludes the current tab as a screen-share source option. You can pass include
or exclude
as a value to control this though.
For more details on these new features see here:
https://developer.chrome.com/docs/web-platform/screen-sharing-controls/
(Chrome/chromium-browsers only)
{% content-ref url="../../source-settings/screenshare.md" %} screenshare.md {% endcontent-ref %}
Viewer-Side Option! (&scene
, &room
, &view
, &solo
)
As an alternative to &sharper
, I've also added &sharperscreen
, which sets &scale=100
, but only for screen-shares (virtual cameras not included). This is probably even more efficient than &scale=100
or &sharper
, and it's designed for when screen-sharing a lot of text. Text looks a bit soft when streaming video at 1:1 pixel resolution.
It's recommended to only use these parameters within the context of a scene link, and not on guest links, due to the higher CPU / bandwidth it may use.
{% content-ref url="../video-parameters/and-sharper.md" %} and-sharper.md {% endcontent-ref %}
{% content-ref url="../view-parameters/dpi.md" %} dpi.md {% endcontent-ref %}
{% content-ref url="../view-parameters/scale.md" %} scale.md {% endcontent-ref %}
Sender-Side Option! (&push
)
Viewer-Side Option! (&scene
, &room
, &solo
) *on alpha
&smallshare
makes the screen share behave like a webcam share. ie: not larger in size vs other windows, for the publisher or the viewers. This is a push-side parameter. This is useful if a VR guests screen sharing an app of themselves, versus using a virtual camera. It can also be useful for gaming, where a larger screen share might bog down the system of the sender more than needed.
Layout if NOT using &smallshare
:
Update on v23
&smallshare
will work on the scene-side now also, which disables the automixer's larger screen-share layout, and instead just uses an equal-sized video layout for all videos.
{% content-ref url="../../source-settings/screenshare.md" %} screenshare.md {% endcontent-ref %}
{% content-ref url="../../newly-added-parameters/and-screensharetype.md" %} and-screensharetype.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&suppresslocalaudio
will disable local audio playback of a Chrome tab while screen-sharing it. This can be used with the new WHIP output of VDO.Ninja to publish a VDO.Ninja scene directly to Twitch, without having to deal with any audio feedback issues while having that scene tab open.
For more details on these new features see here:
https://developer.chrome.com/docs/web-platform/screen-sharing-controls/
(Chrome/chromium-browsers only)
{% content-ref url="../whip-parameters/and-whip.md" %} and-whip.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&systemaudio
excludes the system-audio as an audio source when display sharing. Tab audio is still available though. (can help prevent accidental audio feedback loops)
For more details on these new features see here:
https://developer.chrome.com/docs/web-platform/screen-sharing-controls/
(Chrome/chromium-browsers only)
{% content-ref url="../../source-settings/screenshare.md" %} screenshare.md {% endcontent-ref %}
Screen-share Parameters are separated in general options, source side (push) options and viewer side (view) options.
You can add them to both, source (&push
) and viewer (&view
or &scene
) sides.
Parameter | Explanation |
---|---|
&screensharestereo | Sets the audio mode for screen-shares to stereo and changes default audio settings to improve audio quality |
You can add them to both, source (&push
) and viewer (&view
or &scene
) sides.
Parameter | Explanation |
---|---|
&screenshare | Disables camera-sharing as an option |
&screenshare2 | Will show the "Share your Screen" button before asking the user to select screenshare options |
&screenshareaec | Turns automatic echo-cancellation filter for screen-shares ON or OFF |
&screenshareautogain | Turns audio auto-normalization filter for screen-shares ON or OFF |
&screensharecursor | Attempts to show the mouse cursor on screen shares |
&screensharedenoise | Turns audio noise reduction filter for screen-shares ON or OFF |
&screensharefps | Set a target FPS for your screenshare (secondary stream) |
&screensharehide | Hides the local screen-share sub-window that appears when screen sharing in a room |
&screenshareid | Pre-sets the screenshare stream id for a screen share if its a secondary stream |
&screensharelabel | The screen-share of the guest will have the same label as the guest |
&screensharequality | Set a custom screenshare quality |
&screensharecontenthint | =motion prioritizes screen-share frame rate; =detail prioritizes screen-share resolution |
&screenshareaspectrati | Changes the screen-share aspect ratio on the publisher side |
&screensharestereo | Sets the audio mode for screen-shares to stereo and changes default audio settings to improve audio quality |
&screensharetype | Defines how webcam and screenshare of a guest in a room interacts which each other |
&smallshare | Makes the screen share behave like a webcam share |
&screensharevideoonly | Lets you disable the option to select audio when screen sharing |
&screensharebutton | Forces the screen-share button to appear for guests |
&suppresslocalaudio | Will disable local audio playback of a Chrome tab while screen-sharing it |
&prefercurrenttab | Will have the current tab as the default screen-share source |
&selfbrowsersurface | Excludes the current tab as a screen-share source option |
&systemaudio | Excludes the system-audio as an audio source when display sharing |
&displaysurface | Will pre-select display-share, rather than tab-share, when screen-sharing |
You have to add them to the viewer side (&view
or &scene
).
Parameter | Explanation |
---|---|
&screensharebitrate | Lets you manually set the video bitrate for screen-shares |
&sharperscreen | Sets &scale=100 , but only for screen-shares |
&sspaused | Starts any screen-share paused |
General Option! (&push
, &room
, &view
, &scene
, &solo
)
Example: &allowedscenes=Scene1,Scene2
Value | Description |
---|---|
(comma separated OBS scene names) | filter which OBS scenes a remote guest has access to controlling when using &controlobs |
&allowedscenes
filters which OBS scenes a remote guest has access to controlling when using &controlobs
. Uses CSV to split up the scenes (avoid special characters in your scene names if there are issues)
Example: vdo.ninja/?view=StreamID&remote&allowedscenes=Scene1,Scene2
{% hint style="info" %} If you don't want a user to have the ability to start/stop a stream, set the OBS page permissions to level 4, instead of 5. It'll disable the start/stop buttons for the user if they don't have those permissions. {% endhint %}
{% content-ref url="and-controlobs.md" %} and-controlobs.md {% endcontent-ref %}
{% content-ref url="../../general-settings/remote.md" %} remote.md {% endcontent-ref %}
description: >- Shows the battery meter for guests that are on devices with a battery that's draining/charging
Sender-Side Option! (&push
)
Example: &batterymeter=0
Value | Description |
---|---|
(no value given) | Adds a battery-meter per guest |
0 | no | off |
Disables the battery-meter |
Curtesy of @Yong.
Notes:
steveseguin/vdo.ninja#1078 (comment)
It's the same concept of &signalmeter
, except shows the battery meter for guests that are on devices with a battery that's draining/charging.
Shows blinking warning if under 25% battery life.
The battery meter was already available by default as the director, but now it can be enabled as a guest, etc.
Also supports disabling the meter with &batterymeter=0
.
{% content-ref url="../../newly-added-parameters/and-signalmeter.md" %} and-signalmeter.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&clear
&clearstorage
will clear all the saved user preferences for all sessions, including &sticky
'd data, director settings, any camera and microphone settings, and probably a couple other small things. This also includes the "default" saved stated of camera settings before adjusted.
I also added a button to manually do this via the User menu settings.\
{% content-ref url="../../general-settings/sticky.md" %} sticky.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
, &director
)
Example: &clock=5
or &clock=false
Value | Description |
---|---|
1 - 9 | Shows the current time as in the graphic below. Each option specifies where the clock will appear on the screen |
9 | (no value given) | Shows the current time in the lower right |
false | Will force-disable the clock from being remotely triggerable |
&clock
shows the current time in the lower right; this can be applied to pretty much all link types.
The director has a button that lets them enable the clock for everyone in the room (via the director's room settings button).
&clock=false
or &cleanoutput
will force-disable the clock from being remotely triggerable.
The director will see the clock also; it will just be a bit smaller on screen.
{% content-ref url="and-clock24-alpha.md" %} and-clock24-alpha.md {% endcontent-ref %}
{% content-ref url="and-timer.md" %} and-timer.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
, &director
)
Example: &clock24=5
Value | Description |
---|---|
1 - 9 | Shows the current time as in the graphic below. Each option specifies where the clock will appear on the screen |
9 | (no value given) | Shows the current time in the lower right |
false | Will force-disable the clock from being remotely triggerable |
&clock24
is the same as the existing &clock
option, (which shows a clock) except it uses 24-hour time for the display (vs. am/pm).
If the director uses &clock24
on their URL, and then enables the room clock, it will be 24-hour time for all guests, matching the director's settings.
Shows the current time in the lower right; this can be applied to pretty much all link types.
The director has a button that lets them enable the clock for everyone in the room (via the director's room settings button).
The director will see the clock also; it will just be a bit smaller on screen.
{% content-ref url="and-clock.md" %} and-clock.md {% endcontent-ref %}
{% content-ref url="and-timer.md" %} and-timer.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&captions
&cc
This command will display the incoming transcribed text-data as an overlay. You will need to use this on the VIEW link, while also using the &transcribe
command on the PUSH link.
See video for a walk-thru:
{% embed url="https://www.youtube.com/embed/3eo85WAXeuk" %}
Overlay text data is pulled from the source with &transcribe
added.
&fontsize={percent}
can be used to adjust the overlay font-size. 100% is default;
Use can use &css=somecssfile.css
to further customize the CSS style, or do so in the OBS Browser source style sheet area. You can also set the CSS via a base64 encoded string in the URL, via the &base64css
parameter.
An example of a custom stylesheet for OBS that changes the font-family of the overlay text is the is the following:
body {
background-color: rgba(0, 0, 0, 0); margin: 0px auto; overflow: hidden;
}
@font-face {
font-family: 'opendyslexic';
src: url('https://vdo.ninja/examples/OpenDyslexic-Regular.otf');
font-style: normal;
font-weight: normal;
}
#overlayMsgs {
font-family: "opendyslexic", opendyslexic, serif;
}
Another example of limiting the captioning-text to only use a fixed height of space when used as an overlay to OBS browser source. Just replace the OBS browser style with this code snippet instead:
body { background-color: rgba(0, 0, 0, 0); margin: 0px auto; overflow: hidden; }
#overlayMsgs{
overflow: auto!important;
display: flex!important;
flex-direction: column-reverse!important;
height: 240px!important;
}
#overlayMsgs span {
text-align: left!important;
}
If not using OBS, you can still add the above CSS via the URL using the &base64css
parameter. For example, instead of the above CSS, you can append the following to the URL:
&base64css=I292ZXJsYXlNc2dzew0KICAgIG92ZXJmbG93OiBhdXRvIWltcG9ydGFudDsNCiAgICBkaXNwbGF5OiBmbGV4IWltcG9ydGFudDsNCiAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uLXJldmVyc2UhaW1wb3J0YW50Ow0KICAgIGhlaWdodDogMjQwcHghaW1wb3J0YW50Ow0KfQ0KDQojb3ZlcmxheU1zZ3Mgc3BhbiB7DQogICAgdGV4dC1hbGlnbjogbGVmdCFpbXBvcnRhbnQ7DQp9
Feedback and user requests are welcomed.
https://vdo.ninja/?transcribe
https://vdo.ninja/?view=abc123&closedcaptions
https://meyerweb.com/eric/tools/dencoder/
https://vdo.ninja/examples/rainbow.css
https://vdo.ninja/?css=https%3A%2F%2Fvdo.ninja%2Fexamples%2Frainbow.css
{% content-ref url="../design-parameters/css.md" %} css.md {% endcontent-ref %}
{% content-ref url="../../source-settings/transcribe.md" %} transcribe.md {% endcontent-ref %}
Sender-Side Option! (&push
, &room
)
&controlbarspace
forces the bottom control bar to be in its own dedicated space, regardless of screen size.
The control bar is not overlapping the video feed
{% content-ref url="../../parameters-only-on-beta/and-autohide.md" %} and-autohide.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
)
&obscontrols
&remoteobs
&obsremote
&obs
Example: &controlobs=0
Value | Description |
---|---|
(no value given) | #remotely-control-obs-studio |
0 | false | off | will hide the control option on the sender side, regardless of the OBS browser source page permissions |
Added the ability for VDO.Ninja to Remotely Control OBS Studio while streaming/directing. It may be useful for IRL streaming?
The menu button to control OBS auto-shows in the director's view or push-mode, if OBS Studio is set to give VDO.Ninja "full" permissions.
The menu button can also be added manually, for even guests, using &controlobs
. &obsoff
can be used to set permissions to fully off (also disables tally light and scene optimizations tho) when added to the OBS browser source link.
The OBS instance still needs &remote=optional-passcode-here
added to the URL for remote commands to work. If &remote
is left blank, it gives anyone permissions to control it. If a value is passed to &remote
, the sender needs to have a matching &remote
value or they need to manually enter the passcode in the pop up control menu.
If the OBS browser source has its permissions set to something other than full (lower than level 5), the control menu will still show what info it has -- current scene, recording/streaming state, etc; depending on level. The lower the level, the less info is available to show. It can't remotely change anything though.
It supports multiple OBS instances and will label them according to the &label=xxx
value set on the scene/view link, or whatever the unique connection ID is.
1. Add a browser source to OBS Studio with this URL:
https://vdo.ninja/?view=streamid12345&remote&controlobs
2. Give page permissions to the browser source (Full access to OBS) like on the image below
3. Open this Push Link: https://vdo.ninja/?push=streamid12345&wc&as&controlobs&remote
5. Control OBS Studio remotely via VDO.Ninja
Setting &controlobs=0
or to false
/off
, will hide the control option on the sender side, regardless of the OBS browser source page permissions.
As well, setting the OBS browser source to low or no page permissions will also not show the controls, which is how it is by default. You can force show the controls of course, but they won't work if the browser source doesn't have the right permissions.
{% content-ref url="../../general-settings/remote.md" %} remote.md {% endcontent-ref %}
{% content-ref url="and-cutscene.md" %} and-cutscene.md {% endcontent-ref %}
{% content-ref url="../design-parameters/and-obsoff.md" %} and-obsoff.md {% endcontent-ref %}
{% content-ref url="and-allowedscenes.md" %} and-allowedscenes.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&lowbitratescene
Example: &cutscene=ObsSceneName
Value | Description |
---|---|
(OBS scene name) | The name of the OBS scene |
You can use the IRL-related command called &cutscene
to specify an OBS cut scene to switch to when the bitrate drops below a threshold and return to the original scene when the bitrate recovers. (assuming the cut scene is active; it won't switch back from a scene that isn't the cut away scene)
The default bitrate threshold is 300-kbps, but you can use the existing &bitratecutoff=N
option to specify a custom one. Using &cutscene
with &bitratecutoff
will override the behaviour of &bitratecutoff
's other features. It won't start triggering until the bitrate has hit at least the threshold once. to use:
https://vdo.ninja/?push=XXX
https://vdo.ninja/?view=XXX&controlobs&bitratecutoff=300&cutscene=FML&remote
You can of course use this with &controlobs
&remote
, to have the publisher change the scenes dynamically, and see what the current OBS scene is (if still connected).
{% hint style="warning" %} Note that the OBS browser source needs the permissions to be set to high, to give VDO.Ninja permissions to change scenes. {% endhint %}
{% hint style="warning" %} Do not set the OBS browser source to "Shutdown" when not visible, as this will prevent things from being able to switch back. {% endhint %}
When using &cutscene
on a room scene, it won't trigger due to a director being in the room with no video, unless they are using &showdirector
. &cutscene
wasn't intended really for a group scene; just a solo link or view link, but this fix makes it at more usable with a group scene.
{% content-ref url="../parameters-only-on-beta/and-bitratecutoff.md" %} and-bitratecutoff.md {% endcontent-ref %}
{% content-ref url="and-controlobs.md" %} and-controlobs.md {% endcontent-ref %}
{% content-ref url="../../general-settings/remote.md" %} remote.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&disablehotkeys
disables hotkeys (like CRTL + M
).
{% content-ref url="../../guides/hotkey-support/" %} hotkey-support {% endcontent-ref %}
Sender-Side Option! (&push
)
&fsb
&fullscreenbutton
adds a full-screen button to the control bar. It essentially just mimics F11, with added support for detecting the Escape button to exit full screen.
Also while using &fullscreenbutton
, the previous little 'full window' button in the top-right of videos (if in a group room) will also auto-F11 and isolate that video, rather than just isolate the video.
You can still right-click and select "full-window" on any video to isolate it without going full screen, if you need that.
You can test by opening two such guest links:
https://vdo.ninja/?fsb&room=test123123123&webcam&autostart
Ultimately I'd like to override the native video full screen button with this behaviour, when &fullscreenbutton
is used, but I'm still working on that aspect.
Update in v23
&fullscreenbutton
is improved, so that even when there is a single video on the page, it will show. It also shows more reliably, without needing to move the mouse around a bit to re-show the button after going full screen. Lastly, when used, it now hides the native full-screen button, so users have to use it.
Unlike the native full screen button, this full screen mode alternative keeps the chat and control bar overlays visible (like press F11). Since this is probably the preferred way most users will want to full screen to work, I may make it the default mode at some point, after some more testing/feedback. (not supported on iOS/iPhone tho)
Testing at https://vdo.ninja/?fullscreenbutton (join a room as a guest to trigger)
{% content-ref url="../../source-settings/fullscreen.md" %} fullscreen.md {% endcontent-ref %}
Viewer-Side Option! (&scene
, &room
, &view
, &solo
)
&pushfaces
&getfaces
on the viewer link will request a continuous stream of face bounding boxes, for all inbound videos and all faces contained within. The data is transmitted to the parent IFRAME, and this data can be used for moving the IFrame window around, if you wish to make your own custom face-tracker or whatever else.
{% hint style="warning" %}
&getfaces
requires the use of the Chromium experimental face detection API, as I'm using the built-in browser face-tracking model for this. You can enable the API flag here: chrome://flags/#enable-experimental-web-platform-features
My hope is that this feature will eventually be enabled by default within Chromium, as loading a large ML model to do face detection otherwise is a bit heavy; you may need to enable this within the OBS CLI if wishing to use it there?
{% endhint %}
General Option! (&push
, &room
, &view
, &scene
, &solo
, &director
)
&hidehome
hides the VDO.Ninja homepage and many links that lead to it. You can also enable at a code level with session.hidehome=true;
, which is useful if doing a self-deployment, where you don't want anyone to stumble onto the site and start using it. You'll still be able to join push links and create rooms via URL parameters, but that's about it.
{% content-ref url="../design-parameters/and-hidemenu.md" %} and-hidemenu.md {% endcontent-ref %}
{% content-ref url="../design-parameters/and-hideheader.md" %} and-hideheader.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
)
&hidetranslate
hides the button at the bottom right of VDO.Ninja to select a different language. If you want to change the language via URL you can use &language
.
{% content-ref url="and-language.md" %} and-language.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&ln
Example: &language=fr
Value | Language |
---|---|
cn | Chinese |
cs | Czech |
de | German |
en | English (default if &ln not present) |
es | Spanish |
eu | Basque |
fr | French |
it | Italian |
ja | Japanese |
nl | Dutch |
pig | Pig Latin |
pt | Portuguese |
ru | Russian |
tr | Turkish |
uk | Ukrainian |
(no value given) | Less verbose interface |
You can contribute new or update existing translations.
You can also change the language of VDO.Ninja dynamically on the bottom right.
{% content-ref url="and-hidetranslate.md" %} and-hidetranslate.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&nocaptionlabel
&nocclabels
&nocclabel
&nocclabels
disables showing the names when using the &closedcaptions
feature, as you might want to only show labels on the video themselves, and not in the transcription text.
{% content-ref url="and-closedcaptions.md" %} and-closedcaptions.md {% endcontent-ref %}
{% content-ref url="../../general-settings/label.md" %} label.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &solo
)
&nochunk
If a VDO.Ninja guest has &chunked
added, the viewer or another guest can use &nochunked
to ignore the chunked version, and use the low-latency version. In this way, guests in a room can still use the low latency streams to chat, but publish chunked video to OBS for (delayed) high quality video.
{% content-ref url="../../newly-added-parameters/and-chunked.md" %} and-chunked.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&controls=0
&nocontrols
will force hide the video control bar. You can also hide the control bar with Right-Click
-> Hide control bar
.
{% hint style="warning" %} This is not the same control bar as the user control bar. Also, be sure to not accidentally unmute yourself -- echo feedback galore. {% endhint %}
This is the video control bar:\
{% content-ref url="../newly-added-parameters/and-videocontrols.md" %} and-videocontrols.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&nohub
This option hides the hang-up button, so it can't be accidentally clicked.
{% content-ref url="../../viewers-settings/nomicbutton.md" %} nomicbutton.md {% endcontent-ref %}
{% content-ref url="../../viewers-settings/and-novideobutton.md" %} and-novideobutton.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
)
&noseed
&viewonly
&viewmode
To help avoid some types of connections showing up when using &showall
, I've also added a &nopush
mode, which blocks outbound publishing connections. This acts a bit like a &scene=1
link, so unless &showall
is added, you'll need to use the IFRAME API to show/hide videos in it.
{% content-ref url="../design-parameters/and-showall.md" %} and-showall.md {% endcontent-ref %}
Sender-Side Option! (&push
)
Example: &postimage=https%3A%2F%2Ftemp.vdo.ninja%2F
Value | Description |
---|---|
https%3A%2F%2Ftemp.vdo.ninja%2F |
URL-encoded URL |
Added an option to post a snapshot of your local camera to a HTTPS/POST URL (blob/jpeg).
https://vdo.ninja/?postimage=URL_TO_POST_IMAGE_TO_AS_BLOCK&postinterval=INTERVAL_IN_SEC
So, for example:
https://vdo.ninja/?postimage=https%3A%2F%2Ftemp.vdo.ninja%2F&postinterval=30&push&wc
posts to a sample test server I have up. The URL is URL encoded, but not always necessary. If posting to my test server, the image can be accessed at https://temp.vdo.ninja/images/STREAMID.jpg
.
There's caching enabled mind you, so you'll want to post-fix the current timestamp to the URL to disable that per request.
For example: https://temp.vdo.ninja/images/yiMkpMg.jpg?t=3412341234
This feature could be useful to checking out a stream before actually connecting to it, as that's my intent with it, but it is also something you can use with Octoprint, where you need an IP camera jpeg source as input.
{% content-ref url="and-postinterval.md" %} and-postinterval.md {% endcontent-ref %}
{% content-ref url="../video-parameters/and-slideshow.md" %} and-slideshow.md {% endcontent-ref %}
Sender-Side Option! (&push
)
Example: &postinterval=20
Value | Description |
---|---|
(value) | time in seconds |
Added an option to post a snapshot of your local camera to a HTTPS/POST URL (blob/jpeg).
https://vdo.ninja/?postimage=URL_TO_POST_IMAGE_TO_AS_BLOCK&postinterval=INTERVAL_IN_SEC
So, for example:
https://vdo.ninja/?postimage=https%3A%2F%2Ftemp.vdo.ninja%2F&postinterval=30&push=testID1&wc
posts to a sample test server I have up. The URL is URL encoded, but not always necessary. If posting to my test server, the image can be accessed at https://temp.vdo.ninja/images/STREAMID.jpg
.
There's caching enabled mind you, so you'll want to post-fix the current timestamp to the URL to disable that per request.
For example: https://temp.vdo.ninja/images/yiMkpMg.jpg?t=3412341234
This feature could be useful to checking out a stream before actually connecting to it, as that's my intent with it, but it is also something you can use with Octoprint, where you need an IP camera jpeg source as input.
{% content-ref url="and-postimage.md" %} and-postimage.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&slides
&pptcontrols
&ppt
Adds a built-in basic controller to control PowerPoint.
Detailed information on how to control PowerPoint remotely:
{% content-ref url="../../guides/how-to-control-powerpoint-remotely-with-vdo.ninja.md" %} how-to-control-powerpoint-remotely-with-vdo.ninja.md {% endcontent-ref %}
{% content-ref url="../../guides/how-to-control-powerpoint-remotely-with-vdo.ninja.md" %} how-to-control-powerpoint-remotely-with-vdo.ninja.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&approve
&validate
After a new peer viewer connection is established, but before the video/audio streams start getting sent to that new viewer, a prompt will appear asking the publisher if they wish to send their stream to that viewer. If they say no, the remote viewer is disconnected and no video/audio is sent to them. If they have &label=xxx
added to their view link, that label will appear as the display name. Otherwise, if no label is available, a random ID representing that connection is shown.
There's nothing stopping a disconnected viewer from re-joining and re-asking, causing some grief, and spoofing an identify isn't too hard, but it gives you some control and warning to block unexpected viewers.
In the future, I can add this control to the director, rather than just the senders, and add additional ways to check identities. For now though, it's a start.
{% content-ref url="../setup-parameters/and-password.md" %} and-password.md {% endcontent-ref %}
{% content-ref url="../../newly-added-parameters/and-hash.md" %} and-hash.md {% endcontent-ref %}
description: >- Will transfer a guest from one room into another, but once transferred, the guest will be in Queue mode
Sender-Side Option! (&push
, &room
)
&qt
&queuetransfer
will transfer a guest from one room into another, but one transferred, the guest will be in Queue mode. So they won't share their video with anyone by the director.
{% content-ref url="../../general-settings/queue.md" %} queue.md {% endcontent-ref %}
description: >- Will relay the incoming 'chunked' media stream to others connected to you, without transcoding
Sender-Side Option! (&push
)
Added a new experimental option called &retransmit
; it will relay the incoming 'chunked' media stream to others connected to you, without transcoding. In a way, this enables a form of peer to peer to peer broadcasting.
-- It only works with incoming &chunked
data streams, however trying to forward more than one chunked stream will break things currently.
-- It will disable your own mic/camera from being streamed; when &retransmit
is used it configures itself as a viewer in a sense.
-- Chunked mode has a default play out buffer delay of about 1-second still, but that buffer time does not get passed down to the relayed viewer. There is still some transmission delay that gets introduced though, but it can be very low latency on a series of good computers/network.
https://vdo.ninja/?chunked&push=PUBLISHER123
This is the source. Notice they are publishing in chunked mode.
https://vdo.ninja/?view=PUBLISHER123&retransmit&push=RESTREAMER123
This person is both viewing the video, but also relaying.
https://vdo.ninja/?view=RESTREAMER123
This person is viewing the stream from the relayed chunked stream; p2p2p. They don't know they are getting a relayed stream.
{% hint style="info" %} This feature is just for fun at the moment. It's does not do automatic p2p2p broadcasting, as you still need to manually customize who sees what, and chunked mode isn't compatible with all browsers/devices yet. {% endhint %}
{% content-ref url="../../newly-added-parameters/and-chunked.md" %} and-chunked.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&ssb
Forces the screen-share button to appear for guests.
The screen share button will show even if they are on an incompatible device, using &nosettings
, or using &webcam
.
{% content-ref url="../../source-settings/screenshare.md" %} screenshare.md {% endcontent-ref %}
{% content-ref url="../../source-settings/and-nosettings.md" %} and-nosettings.md {% endcontent-ref %}
{% content-ref url="../../source-settings/and-webcam.md" %} and-webcam.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&sensorsfilter
&filtersensor
&filtersensors
Example: &sensorfilter=gyro
Value | Description |
---|---|
gyro | gyroscopic |
lin | - |
acc | accelerometer |
mag | magnetometer |
pos | - |
ori | - |
Added a new option to explicitly list what sensor data you want to capture and transmit, when using &sensor
&sensorfilter=gyro,lin,acc,mag,pos,ori
. For the above demo, you can use &sensorfilter=pos,lin
to just send the data you need, reducing the load on the phone/network.
{% content-ref url="../../source-settings/sensor.md" %} sensor.md {% endcontent-ref %}
Viewer-Side Option! / Director Option! (&scene
, &room
, &view
, &solo
, &director
)
&showconnections
will display the total number of p2p connections of a remote stream. Works with the director's room and the automixer. Might help give comfort over privacy/security during a stream.
Total number of p2p remote connections (viewers) of a stream source will also appear in the stats menu, even without &showconnections
. Could be useful for debugging CPU/bandwidth issues.
Connections may represent video/audio streams, or just a data-connection. Meshcast-hosted streams might not be accounted for, depending on how the viewer is connecting.
{% content-ref url="../../source-settings/and-maxconnections.md" %} and-maxconnections.md {% endcontent-ref %}
Sender-Side Option! (&push
, &room
)
Example: &slot=4
Value | Description |
---|---|
(integer value) | the slot guest should be assigned to |
&slot=N
is a guest side property (sender side). It just tells the director (Mixer App / &slotmode
) which slot the guest should prefer to be in, if slots are being auto-assigned. If the desired slot is already taken, then that guest will then not be assign a slot. If the guest was assigned a slot by the director, refreshing will keep the assign slot, and the URL-specified slot preference will be ignored.
{% content-ref url="../director-parameters/and-slotmode.md" %} and-slotmode.md {% endcontent-ref %}
{% content-ref url="../../steves-helper-apps/mixer-app.md" %} mixer-app.md {% endcontent-ref %}
{% content-ref url="../../newly-added-parameters/and-slots.md" %} and-slots.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
, &director
)
Example: &timer=5
Value | Description |
---|---|
1 - 9 | Shows the current countdown timer as in the graphic below. Each option specifies where the countdown timer will appear on the screen |
2 | (no value given) | Shows the countdown timer in the top center |
&timer=N
can be used to position where the countdown timer is positioned on a guest's window. Default is still center top but a value of 1 to 9 can be be passed to change positions.
You can enable the countdown as a director via the room settings.
The director has a button that lets them also enable a global count-down timer. Holding CTRL + click
will let the director pause the timer. If someone joins the room or reloads, the timer will also be reloaded, in sync. Button also in the room settings menu.
This count down timer is the same concept as the per-guest timer the director already has, and will actually conflict with it if both are used, since it uses the same state/variable to keep track of time remaining.
The director will see the global count down timer also; it will just be a bit smaller on screen.
{% content-ref url="and-clock.md" %} and-clock.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
)
Example: &token=5eb5e63ee4d9ba06
Value | Description |
---|---|
(alphanumeric-characters only) | a token for invite/scene links to determine whose the director of a room |
When using &maindirectorpassword
as a director, it will add &token=xxx
to the invite/scene links.
This token is used by the guests to check a remote database server to see who currently 'owns' the token; it persists though, even if the director is not connected.
When using &maindirectorpassword
as a director, it tells this database that you are the owner, and it will persist even if you aren't connected to VDO.Ninja. The &token
tells the guest to ignore other logic about who the director is, instead using the info provided by the token-lookup to determine whose the director.
I may change or revoke this feature, depending on how testing goes this week, as it's rather experimental.
{% content-ref url="../director-parameters/and-maindirectorpassword.md" %} and-maindirectorpassword.md {% endcontent-ref %}
description: >- Will load a side-bar with an IFrame embed, with support for YouTube / Twitch / Social Stream
General Option! / Director Option! (&director
, &push
, &room
, &view
, &scene
)
Example: &widget=https%3A%2F%2Fwww.youtube.com%2Flive_chat%3Fis_popout%3D1%26v%3DORBwkXsUNEs
Value | Description |
---|---|
(URLComponent-encoded URL value) | load a side-bar with that page as an IFRAME embed |
&widget
lets you pass a URLComponent-encoded URL value. It will load a side-bar with that page as an IFrame embed, with support for YouTube/Twitch specifically added.
This was designed for Twitch / YouTube / Social Stream chat, but could in theory work with any CORS-friendly site, such as a third-party web tool.
The director of a room also has the option to enable/disable the widget function for everyone in the room via the room settings menu.
You can encode the URL here:
https://www.urlencoder.org/
If the director uses &widget
, it will auto sync that with all guests as they connect. I'll try to find ways to make it easier to resize/minimize in the future.
{% content-ref url="../../general-settings/chatbutton.md" %} chatbutton.md {% endcontent-ref %}
{% content-ref url="../../steves-helper-apps/social-stream-ninja/" %} social-stream-ninja {% endcontent-ref %}
description: >- Language, save cookies, remote access, chat widget, chunked mode, raise hands, notify, transcription, closed captions
They are separated in three groups: general options (push and view), source side (push) options and viewer side (view) options.
You can use them for publisher, viewer and director URLs.
Parameter | Explanation |
---|---|
&language | Sets the interface language |
&remote | Allows remote operation of the zoom and focus, and access to statistics |
&controlobs | The ability for VDO.Ninja to Remotely Control OBS Studio while streaming/directing |
&allowedscenes | Option to filter which OBS scenes a remote guest has access to controlling when using &controlobs |
&stats | Shows the connection/media stats window by default |
&sticky | Allows a user to save and then later restore their streaming session settings |
&clearstorage | Will clear all the saved user preferences for all sessions |
&disablehotkeys | Disables hotkeys (like CRTL + M ) |
&showlist | Shows list of hidden guests |
&nopush | Blocks outbound publishing connections |
&hidehome | Hides the VDO.Ninja homepage and many links that lead to it |
&hidetranslate | Hides the option to translate VDO.Ninja |
&clock | Shows the current time |
&clock24 * | The same as &clock option, except it uses 24-hour time for the display |
&timer | Positions the countdown timer |
&powerpoint | Adds a built-in basic controller to control PowerPoint |
&widget | Will load a side-bar with an IFrame embed, with support for YouTube / Twitch / Social Stream |
&token | A token for invite/scene links to determine whose the director of a room |
*NEW IN VERSION 24
Source Settings, which are settings specific to publishing. The parameters can be added to a publishing link, like for example a guest, a director or just a basic push link.
Parameter | Explanation |
---|---|
&transcribe | Enables transcription and closed captioning |
&signalmeter | Visualizes the packet loss of a guest |
&batterymeter | Shows the battery meter for guests that are on devices with a battery that's draining/charging |
&consent | Will ask the user for content to remote change their camera or microphone |
&prompt | Another security option, for those concerned about random spying of their streams |
&hands | Enables a "Raise Hand" button for guests |
¬ify | Audio alerts for raised hands, chat messages and if somebody joins the room |
&r2d2 | Easter egg ¬ify sound |
&directorchat | Message ONLY the director |
&maxconnections | Limits total of view and push connections |
&maxviewers | Limits the number of viewers allowed |
&chunked | Does not use webRTC's video streaming protocols; rather it uses a custom-made protocol |
&retransmit * | Will relay the incoming 'chunked' media stream to others connected to you, without transcoding |
&rampuptime | When a guest connects, this tries to load video from that guest for a few seconds, even if not yet added to a scene |
&sensor | Access device sensor data at given rate |
&sensorfilter | An option to explicitly list what &sensor data you want to capture and transmit |
&postimage | Post a snapshot of your local camera to a HTTPS/POST URL |
&postinterval | Time interval in seconds for &postimage |
&slot | Tells the director which slot the guest should prefer to be in |
*NEW IN VERSION 24
Viewer's Settings, which are aspects that are controllable by the viewer's side. These parameters are mostly added to &room
(viewing other guests), &view
and &scene
or &solo
links, but some of them can also be added to the director's URL.
Parameter | Explanation |
---|---|
&closedcaptions | Enables displaying of closed captioning text |
&nocaptionlabels * | Disables showing the names when using the &closedcaptions feature |
&enhance | Tells the remote source that you would like them to prioritize the audio stream over other streams |
&bitratecutoff | If the total bitrate drops below the specified bitrate, the viewer will auto-hide the audio and video for that stream |
&cutscene | Specifies an OBS cut scene to switch to when the bitrate drops below a threshold |
&statsinterval | Lets you change the default stats update interval from 3-seconds to something else |
&keyframerate | This tells the remote publishers to send keyframes at a specified rate |
&maxpublishers | Limits the number of remote peer connections that are publishers |
&showconnections | Displays the total number of p2p connections of a remote stream |
&obsfix | Disables or adjusts the sensitivity of the VP8/VP9 Codec packet loss 'fix' for OBS |
&streamlabs | Tells VDO.Ninja to not block VDO.Ninja from attempting to run when using Streamlabs for MacOS |
&getfaces | Will request a continuous stream of face bounding boxes |
&nochunked | Will ignore the chunked version and use the low-latency version |
*NEW IN VERSION 24
General Option! (&push
, &room
, &view
, &scene
)
&outputdevice
&od
Example: &audiooutput=Cable_Input
Value | Description |
---|---|
(string value) | partial string that matches the device's label/name |
Cable_Input | will match against "CABLE Input" (VB-Audio Virtual Cable). Use any other string to match against other device names. |
(no value given) | hides the option to change the output device, including under the settings cog |
&audiooutput
lets you set the default audio output device, based on its name.
Matches on "string contains", so a partial string of the device name is enough. Use lower case, with underscores replacing special characters or spaces.
&sink
takes priority, if used, and &sink
is more strict in matching. While &audiooutput
matches on the device name, &sink
matches on the device ID.
&audiooutput=labelname
is consistent across domains / cookie sessions, while &sink=deviceid
isn't.
If the parameter's value is left blank, it hides the option to change the output device, including under the settings cog.
{% hint style="info" %} Visit vdo.ninja/devices to find the available device IDs and device names on your system.
Device IDs are specific to VDO.Ninja's domain, while device names are not.
This web-based tool will also auto-create links for you, just by clicking on the respective device. {% endhint %}
You can change the audio output device dynamically via the settings menu.
In Version 22 of VDO.Ninja you can change the audio output device of each video feed individually via Right-Click -> Audio Destination
on the video feed.
You can specify an audio output device via the Electron Capture app's command line using this URL parameter (when used in conjunction with VDO.Ninja).
Example:
electron.exe --url="https://vdo.ninja/?view=guest1&outputdevice=mixer_usb"
{% content-ref url="../view-parameters/and-sink.md" %} and-sink.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &director
)
There is support for something called "end to end encryption" using "insertable streams" to VDO.Ninja. To use, add &e2ee
to both the viewer and sender side links. Can be used in conjunction with &password
to specify a cipher.
More technical details about it:
- VDO.Ninja is already end to end encrypted by default (in peer to peer mode), so this isn't anything of much value to most users.
- In p2p mode, this will double up the encryption on the video/audio stream, which might be useful if your system was compromised by a state actor.
- Uses the browser's built-in AES algo, but there is dedicated JS file for the encryption logic, so you can custom-code to use your own encryption I guess.
- Does NOT work with Meshcast, as I don't have insertable streams working server-side there yet, so there is no E2EE with Meshcast still.
- It can be used with compatible WHIP/WHEP services, but most WHIP/WHEP services won't support insertable streams. Still, some do, and that's probably the main reason why I bothered to add this all in.
- The default crypto key used will be hard coded, public, and not secure, but if you provide a
&password
it will use that as the secure cipher phrase instead. - The encoder and decoder algo will fail-safely, rather than fail-securely; I can change this if needed, but it allows for broader peer compatibility and user friendliness. I have more work to do on visually indicating the state of this all, and to allow for more customization, but I'll wait on that until there is more feedback I guess.
- Not all browsers support this, so in those cases, it may fail safely, if possible; otherwise it will just fail completely.
{% content-ref url="and-password.md" %} and-password.md {% endcontent-ref %}
Sender-Side Option! (&push
, &room
)
&groupmode
changes the way groups work when not in a group.
With &groupmode
added to your URL, when not assigned to a group, you don't hear or see anything. This also goes for remote participants who are not in a group - you will not see or hear them if they are not in a group, even if you also are not in a group.
The default normally with VDO.Ninja is that if not in a group, you see and hear everyone. This remains true if not using &groupmode
, even if others in the room are. Others may not be able to see or hear you though, if they have &groupmode
enabled, and you haven't picked a group. So, &groupmode
only impacts the local user, and will not impact remote connections.
The Comms app uses &groupmode
by default.
{% content-ref url="../../general-settings/and-group.md" %} and-group.md {% endcontent-ref %}
{% content-ref url="and-groupview.md" %} and-groupview.md {% endcontent-ref %}
{% content-ref url="../../general-settings/and-groupaudio.md" %} and-groupaudio.md {% endcontent-ref %}
description: >- The same as &group, except it lets you see those groups without actually needing to join them with your mic/camera
General Option! (&push
, &room
, &view
, &scene
)
&viewgroup
&gv
Example: &groupview=Groupname
Value | Description |
---|---|
1 | adds the guest or director to group 1 |
2 | adds the guest or director to group 2 |
3,4,5,6 | adds the guest or director to group 3, 4, 5 and 6 |
(string) | creates/adds the guest or director to a custom group |
&groupview
is the same as &group
, except it lets you see those groups without actually needing to join them with your mic/camera. (There's no button in the directors/guest view for this, since there isn't a need yet for that.)
You can change the view-only groups via the API (http/IFrame) or using the Comms app, which has been updated with buttons for this option. the HTTP documentation: https://github.com/steveseguin/Companion-Ninja/blob/main/README.md#api-commands
You can now use the HTTP/WSS API to both join and leave a group; not just toggle said state. Both the view-group function and regular group function.
{% content-ref url="../../general-settings/and-group.md" %} and-group.md {% endcontent-ref %}
{% content-ref url="../../general-settings/and-groupaudio.md" %} and-groupaudio.md {% endcontent-ref %}
{% content-ref url="and-groupmode.md" %} and-groupmode.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&hum
Example: &hangupmessage=bye<img%20src%3D".%2Fmedia%2Flogo_cropped.png">
(URL encoded string) | the message the guest will see when hanging up |
Option for a custom hang-up message. &hangupmessage
takes a URL encoded string. So it can be just "bye", or it can be some HTML, as shown in the link.
eg:
https://vdo.ninja/?hum=bye%3Cimg%20src%3D%22.%2Fmedia%2Flogo_cropped.png%22%3E&push=ZimFGxM
{% content-ref url="and-humb64-alpha.md" %} and-humb64-alpha.md {% endcontent-ref %}
{% content-ref url="../../newly-added-parameters/and-welcome.md" %} and-welcome.md {% endcontent-ref %}
{% content-ref url="and-welcomeimage.md" %} and-welcomeimage.md {% endcontent-ref %}
Sender-Side Option! (&push
)
Example: &humb64=YnllJTNDaW1nJTIwc3JjJTNEJTIyLiUyRm1lZGlhJTJGbG9nb19jcm9wcGVkLnBuZyUyMiUzRQ==
(base64 encoded string) | the message the guest will see when hanging up |
&humb64
is the same as &hangupmessage
, except this new option takes an input as a base64 encoded string. VDO.Ninja will decode the base64 on load.
Base64 values are less likely to get parsed by apps like Slack incorrectly, so safer to share. If feeling lazy, you can also just use invite.cam, and encode the entire link itself; has a similar effect.
{% content-ref url="and-hangupmessage-alpha.md" %} and-hangupmessage-alpha.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
, &solo
)
&defaultlabel
&ls
Example: &labelsuggestion=Steve
Value | Description |
---|---|
(string) | Sets the label if the user leaves the prompt blank |
(no value given) | Asks the guest for a label |
&labelsuggestion
is the same as &label
, except it asks the user still for a user name. If they leave it blank or cancel the prompt asking for a name, it will use the default label.
https://vdo.ninja/?labelsuggestion=guest&webcam
Once the user enters their label, &label=username
is added to the URL, so if they reload, they won't be asked again for the label. &label
takes priority over &labelsuggestion
.
{% content-ref url="../../general-settings/label.md" %} label.md {% endcontent-ref %}
{% content-ref url="../design-parameters/showlabels.md" %} showlabels.md {% endcontent-ref %}
{% content-ref url="../../newly-added-parameters/and-screensharelabel.md" %} and-screensharelabel.md {% endcontent-ref %}
Sender-Side Option! (&push
, &room
)
&moo
Based on user feedback, I'm testing the concept of a "join with mic-only" button. You can enable it with &miconlyoption
. It's exactly the same as join with video, except the video device is not selected by default. When used, a mic only button shows if a guest joining a room, and if &audiodevice=0
is not present. Hoping this will give more users courage to click the join button, but if it causes issues, I may revert.
For testing at https://vdo.ninja/?room=someetestroomhere&moo
{% content-ref url="../../source-settings/miconly.md" %} miconly.md {% endcontent-ref %}
{% content-ref url="../../source-settings/audiodevice.md" %} audiodevice.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &director
)
&pass
&pw
&p
Example: &password=PASSWORD123
Value | Description |
---|---|
(no value given) | prompts you to select a password |
(string) | 1 to 49-characters long: aLphaNumEric-characters; case sensitive. |
To make your stream or your room more secure, you can set a password by adding &password=xxx
to the URL.
If no password value is provided via the URL parameter, the system will prompt for one when connecting.
You will want to add the password value to the URL if loading it into OBS.
Passwords apply to both Stream IDs and Room IDs.
Please use alphanumeric-characters only; spaces or other characters may cause the mechanism to fail.
{% hint style="info" %} Passwords are CASE-SENSITIVE; mobile users should watch-out for auto-capitalization when entering them. {% endhint %}
Adding &hash=HASH_VALUE
will act as if &password=PASSWORD
was added.
Use this link to get the hash for the password:
https://vdo.ninja/examples/changepass.html
{% content-ref url="../../newly-added-parameters/and-hash.md" %} and-hash.md {% endcontent-ref %}
{% content-ref url="../../director-settings/codirector.md" %} codirector.md {% endcontent-ref %}
{% content-ref url="../settings-parameters/and-prompt.md" %} and-prompt.md {% endcontent-ref %}
{% content-ref url="../director-parameters/and-maindirectorpassword.md" %} and-maindirectorpassword.md {% endcontent-ref %}
description: >- Will save that stream ID to local storage and reuse it every time &permaid is used without a stream ID
Sender-Side Option! (&room
)
Example: &permaid=StreamID
Value | Description |
---|---|
(no value given) | creates a randomly generated stream ID |
(string) | 1 to 49-characters long: aLphaNumEric-characters; case sensitive. |
If using &permaid=streamidhere
to specify the stream ID, rather than just &push
, will save that stream ID to local storage and reuse it every time &permaid
is used without a stream ID.
You could also just use &permaid
on its own initially, which will auto assign a unique stream ID and save that generated one to local storage, which makes it easier to use one invite for many users, but have VDO.Ninja manage the stream ID assignments.
If not using &permaid
, it will just default to using &push
with a random ID. (this avoids 'stream already in use' mishaps)
{% content-ref url="../../source-settings/push.md" %} push.md {% endcontent-ref %}
Sender-Side Option! (&push
)
Example: &welcome64=SGVsbG8=
(base64 encoded string) | the message the guest will see when joining the room |
&welcome64
is the same as &welcome
, except this new option takes an input as a base64 encoded string. VDO.Ninja will decode the base64 on load.
Base64 values are less likely to get parsed by apps like Slack incorrectly, so safer to share. If feeling lazy, you can also just use invite.cam, and encode the entire link itself; has a similar effect.
eg:
https://vdo.ninja/?push=khnCsjS&wc&welcomeb64=SGVsbG8
{% content-ref url="../../newly-added-parameters/and-welcome.md" %} and-welcome.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&welcomeimg
Example: &welcomeimage=https://vdo.ninja/alpha/media/old_logo.png
Value | Description |
---|---|
(URL) | URL of the image |
&welcomeimage
lets you specify a welcome image (URL) that appears for a few seconds before fading away once a guest joins.
Example:
https://vdo.ninja/?welcomeimage=https://vdo.ninja/alpha/media/old_logo.png&webcam
{% content-ref url="../../newly-added-parameters/and-welcome.md" %} and-welcome.md {% endcontent-ref %}
{% content-ref url="and-hangupmessage-alpha.md" %} and-hangupmessage-alpha.md {% endcontent-ref %}
description: >- Stream ID, create a room, password, labels, groups, devices, auto-start, welcoming guests, sharing a website/file
They are separated in two groups: general options (push and view) and source side (push) options.
You can add them to both, source (&push
) and viewer (&view
, &scene
or &solo
) sides.
Parameter | Explanation |
---|---|
&push | The stream ID that you are publishing with will be the defined value |
&room | Sets a room ID for the session to join |
&password | Sets a password to view a stream or to join a room |
&hash | Checks the password |
&e2ee * | Support for something called "end to end encryption" using "insertable streams" |
&label | Sets a display name label |
&labelsuggestion | The same as &label , except it asks the user still for a user name |
&permaid | Will save that stream ID to local storage and reuse it every time &permaid is used without a stream ID |
&group | Puts guests into sub-groups, so they only see others in the same group |
&groupaudio | Tells the system to not filter out audio streams when using &group |
&groupview | The same as &group , except it lets you see those groups without actually needing to join them with your mic/camera |
&datamode | Combines a bunch of flags together; no video, no audio, GUI, etc. |
&audiooutput | Like &sink , but selects the audio output device |
&sink | Outputs the audio to the specified audio output device, rather than the default |
*NEW IN VERSION 24
You have to add them to the source side (&push
).
Parameter | Explanation |
---|---|
&audiodevice | Pre-configures the selected audio device |
&videodevice | Pre-configures the selected video device |
&vdo | Like &videodevice for selecting a default video device, but you can still choose to change the camera |
&device | Same as &audiodevice or &videodevice , but applies to both |
&miconly | Share audio-only; no video publishing allowed |
&miconlyoption | A mic only button shows if a guest joining a room |
&safemode | Tries to load the camera/audio with as little possible complexity as possible |
&autostart | Skips the camera/audio device or screenshare selection |
&easyexit | Won't ask the user to confirm that they wish to exit or leave the page |
&webcam | Disables screen-sharing as an option |
&webcam2 | Will show the "Share your Camera" button before asking the user to select camera options |
&screenshare | Disables camera-sharing as an option |
&screenshare2 | Will show the "Share your Screen" button before asking the user to select screenshare options |
&website | Only shares a website with viewers |
&fileshare | Allows the user to select a video or audio file as a source for streaming |
&intro | When combined with the either &webcam or &screenshare , this option won't auto-load the camera/mic selection page |
&host | Shows a pop up to invite more guests to the room |
&tips | Shows a help-screen on the guest joining |
&welcome | Adds a message the guest will see when joining the room |
&welcomeb64 * | The same as &welcome , except this takes an input as a base64 encoded string |
&welcomeimage | Lets you specify an image that appears for a few seconds once a guest joins |
&hangupmessage * | Option for a custom hang-up message |
&humb64 * | The same as &hangupmessage , except this takes an input as a base64 encoded string |
&groupmode | Added to the URL, when not assigned to a group, you don't hear or see anything |
Parameter | Explanation |
---|---|
&turn | Lets you specify a custom TURN server or disable all TURN servers |
&stun | Lets you specify a STUN server for webRTC negotiation |
&addstun | Appends an added stun server |
&icefilter | Filters ICE candidates |
&proxy | Forces your computer to try to connect to the handshake service via a different physical network end point and domain name |
&relay | Forces TURN relay server into use |
&secure | Disconnects communication with the handshake server as soon as possible and provides verbose feedback |
&tcp | Forces TCP mode |
&tz | Specifies a negative timezone value in minutes for a TURN server |
Sender-Side Option! (&push
)
https://vdo.ninja/alpha/?flagship
Been playing around a new flag called &flagship
, which will optimize the mobile experience for more capable smartphones; essentially, streaming higher quality video to other guests versus the normal mobile-performance mode.
Can be used to try to have a mobile phone push closer-to-desktop quality out, to other guests. The quality is only slightly worse than what a desktop user would push out I think. Just add &flagship
to the guest invite links to trigger.
If you don't include &flagship
, I've still made some performance tweak, such as increasing the default bitrate from 200-kbps to 350-kbps with just one other guest in the room; with two other, its 250-kbps; after that, it starts to drop down a lot again though. I need to organize my thoughts a bit more on all this, but so far I think it's an improvement.
I've also modified the non-flagship mode, for low-end mobile devices, to use the &limittotalbitrate
flag by default (500-kbps). &limittotalbitrate
hasn't been that heavily tested yet, but it's part of v22 and might be better than &totalroombitrate
; currently I'll increasingly use them together I think though. They are both the same concept, except one is viewer-side controlled, and the other is sender-side controlled; both limit the bitrate that guests in the room see based on the number of guests in the room.
{% content-ref url="and-notmobile.md" %} and-notmobile.md {% endcontent-ref %}
{% content-ref url="../mobile-parameters/and-forceios.md" %} and-forceios.md {% endcontent-ref %}
Meshcast Option! / Sender-Side Option! (&meshcast
, &push
)
&mcscale
Example: &meshcastscale=50
Value | Description |
---|---|
(percentage 1 to 100) | will scale down the video to the percentage given |
The &meshcastscale
parameter will scale down the Meshcast video output via the URL, post camera capture setup. Because of how Meshcast works, this is a sender-side parameter. You may wish to use this to lower the resolution if your camera has a fixed capture resolution.
{% hint style="info" %} Alternatively, if you need to dynamically adjust the resolution, that option already exists via camera settings via width/height slider adjustments. {% endhint %}
https://vdo.ninja/?meshcast&meshcastscale=50
{% content-ref url="../../newly-added-parameters/and-meshcast.md" %} and-meshcast.md {% endcontent-ref %}
{% content-ref url="../view-parameters/scale.md" %} scale.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&mobile
will optimize a guest/push link for a mobile device. It might help reduce CPU issues.
There are &flagship
and &forceios
as two options to configure mobile devices, but &mobile
and ¬mobile
are more generic options.
¬mobile
might be able to improve video quality (in case you want to override the automatic defaults, which already detects if a device is mobile or not).
{% content-ref url="and-notmobile.md" %} and-notmobile.md {% endcontent-ref %}
{% content-ref url="and-flagship.md" %} and-flagship.md {% endcontent-ref %}
{% content-ref url="../mobile-parameters/and-forceios.md" %} and-forceios.md {% endcontent-ref %}
Sender-Side Option! (&push
)
¬mobile
might be able to improve video quality (in case you want to override the automatic defaults, which already detects if a device is mobile or not).
&mobile
will optimize a guest/push link for a mobile device. It might help reduce CPU issues.
There are &flagship
and &forceios
as two options to configure mobile devices, but &mobile
and ¬mobile
are more generic options.
{% content-ref url="and-flagship.md" %} and-flagship.md {% endcontent-ref %}
{% content-ref url="and-mobile.md" %} and-mobile.md {% endcontent-ref %}
description: >- Allows a guest to control their total room video bitrate dynamically from the settings panel (under video settings)
Sender-Side Option! (&push
)
&crb
Allows a guest to control their total room video bitrate dynamically from the settings panel (under video settings).
A slider appears in the guest’s settings menu.
This feature could be useful for guests that have limited CPU or Network bandwidth to self-regulate.
Lowering this slider will reduce the video bitrate of incoming video streams.
It will not allow the guest to increase the room bitrate's limits; only lower them.
You need to be a publisher to access this value (as the settings button is needed).
Consider using &totalroombitrate
if you wish to increase the bitrate higher than the default max of ~ 500-kbps.
{% content-ref url="roombitrate.md" %} roombitrate.md {% endcontent-ref %}
{% content-ref url="totalroombitrate.md" %} totalroombitrate.md {% endcontent-ref %}
Sender-Side Option! (&push
)
Example: &maxbandwidth=80
Value | Description |
---|---|
(percentage 1 to 100) | the connection never uses more than that amount of the available reported bandwidth |
Made a new bitrate option called &maxbandwidth
, which differs from other commands as it leverages a chromium (chrome/edge/brave/electron) feature to judge the available bandwidth of a sender's connection. Passing a value to it as the sender (a percentage; 1 to 100 ideally), you can try to ensure the connection never uses more than that amount of the available reported bandwidth.
So the notion is, if you want to set the invite link bitrate to 50-mbps, but one guest only has only a 20-mbps connection, &maxbandwidth=80
will try to limit the bitrate to around 16-mbps. I sometimes will tell people to set the bit rate to about 80% of what their connection can allow, as higher than that can result in some frame stutter when there is packet loss, since the connection lacks headroom to recover. This command will try to do it automatically, for all the viewers of a stream.
My goal here is to use it with the Mixer App or Versus.cam, so eSports users can crank out high bitrates with less tinkering per guest. I have no idea how well it will work in practice so far.
The upcoming and standalone replacement vor vdo.ninja/monitor:
https://versus.cam/
{% content-ref url="and-outboundvideobitrate.md" %} and-outboundvideobitrate.md {% endcontent-ref %}
{% content-ref url="../../source-settings/and-outboundaudiobitrate.md" %} and-outboundaudiobitrate.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&maxbitrate
&mvb
Example: &maxvideobitrate=8000
Value | Description |
---|---|
(positive integer value) | max allowed video bitrate per stream out |
Useful if you are a director and you wish to prevent guests from pulling more than 500-kbps (LQ) or 1200-kbps (HQ) when in broadcast mode.
This is NOT the same as setting the target bitrate as a publisher; this just sets a max limit that viewers can pull video streams at.
Please see &totalroombitrate
or &limittotalbitrate
, as well.
{% hint style="info" %} Set to 600-kbps, 200-kbps, or 80-kbps if the goal is to reduce CPU load also. (2x, 3x, or 4x down-scaling is applied at those bitrate limits). {% endhint %}
{% content-ref url="and-outboundvideobitrate.md" %} and-outboundvideobitrate.md {% endcontent-ref %}
{% content-ref url="limittotalbitrate.md" %} limittotalbitrate.md {% endcontent-ref %}
{% content-ref url="bitrate.md" %} bitrate.md {% endcontent-ref %}
{% content-ref url="totalroombitrate.md" %} totalroombitrate.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&ovb
Example: &outboundvideobitrate=4000
Value | Description |
---|---|
(integer value) | value will be kbps |
Target video bitrate and max bitrate for outgoing video streams.
Sets the viewer's bitrate and overrides the &videobitrate
parameter. It won't override the room's total bitrate parameter, as that's a dynamically set bitrate, so to get higher bitrate in group rooms you still need to use &totalroombitrate
.
{% content-ref url="../../source-settings/and-outboundaudiobitrate.md" %} and-outboundaudiobitrate.md {% endcontent-ref %}
Viewer-Side Option! (&scene
, &room
, &view
, &solo
)
&tb
Example: &totalbitrate=3000
Value | Description |
---|---|
(integer value) | max. video bitrate in kbps a scene/room uses |
&totalbitrate
sets both &totalscenebitrate
and &totalroombitrate
flags. Not quite sure how well it will work, but since a scene and a guest are exclusive possibilities, it's a bit of a flexible way to just learn one flag to do it all, as I realize all the options can get confusing.
&totalscenebitrate
and &totalroombitrate
limit the total incoming bitrate, dividing up the bandwidth available to each video being played back. There are nuances in differences, with the main one being &totalroombitrate
is for a guest link and &totalscenebitrate
is for a scene/view link.
{% content-ref url="and-totalscenebitrate.md" %} and-totalscenebitrate.md {% endcontent-ref %}
{% content-ref url="totalroombitrate.md" %} totalroombitrate.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&tsb
&maxtotalscenebitrate
&mtsb
Example: &totalscenebitrate=4000
Value | Description |
---|---|
(integer value) | max. video bitrate in kbps a scene uses |
Mainly added to help offer another way to optimize performance and limit inbound bandwidth used, since why not.
This is similar to &totalroombitrate
, but &totalscenebitrate
applies to scenes and faux-room scenes instead. That is, it splits the total bitrate available for playback by the number of videos in the scene. It's a way to keep the inbound bitrate below a certain threshold. If &videobitrate
is also used, &videobitrate
becomes a max limit on any individual video, so you can set &totalscenebitrate=6000
and &videobitrate=2000
, to keep all videos below 2-mbps each, but potentially go lower if more than 3 videos are present.
{% content-ref url="totalroombitrate.md" %} totalroombitrate.md {% endcontent-ref %}
{% content-ref url="and-totalbitrate.md" %} and-totalbitrate.md {% endcontent-ref %}
{% content-ref url="bitrate.md" %} bitrate.md {% endcontent-ref %}
description: >- Lets you set the target bitrate for a guest when they 'zoom in' (fullscreen) on a video
Viewer-Side Option! (&view
, &room
)
&zb
Example: &zoomedbitrate=2000
Value | Description |
---|---|
(no value given) | zoomed bitrate = 2500-kbps instead of 600-kbps |
(integer value) | zoomed bitrate in kbps |
Lets you set the target bitrate for a guest in a room when they 'zoom in' on a video using the full-window icon in the top-right of a video.
The idea is, you might want to still have a group call, but occasionally share a high resolution screen. This will increase the load a lot on the guest who is being zoomed-in on, but it's an option if increasing &totalroombitrate
is not acceptable.
Using the flag unset increases the bitrate from 600-kbps to 2500-kbps.
{% content-ref url="totalroombitrate.md" %} totalroombitrate.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&bitrate
&vb
Example: &videobitrate=6000
Value | Description |
---|---|
(integer value) | bitrate in kbps |
&videobitrate
sets the target video bitrate of a video feed in a solo link or the video feeds in a scene.
This parameter is only for scenes and solo links. Use &totalroombitrate
for example to set up the video bitrate for guests in a room.
{% hint style="info" %} Default value will target around 2500-kbps. {% endhint %}
The maximum achievable bitrate is around 60,000-kbps (60-mbps).
Lowering the bitrate can sometimes reduce CPU load, bandwidth, and stuttering issues
You might want to increase the bitrate for game streams, to ensure smooth frame rates.
{% hint style="danger" %} Not compatible with Firefox. {% endhint %}
{% content-ref url="../../guides/video-bitrate-for-push-view-links.md" %} video-bitrate-for-push-view-links.md {% endcontent-ref %}
{% content-ref url="../view-parameters/audiobitrate.md" %} audiobitrate.md {% endcontent-ref %}
Sender-Side Option! / Director Option! (&push
, &room
, &director
)
<b
Example: &limittotalbitrate=2000
or &limittotalbitrate=2000,1000
Value | Description |
---|---|
(positive integer value) | max total outbound video bitrate in kbps |
1000,500 |
Desktop bitrate, Smartphone bitrate |
Tries to limit the total outbound bitrate to some max total value, via the publisher's side. This could be useful if you are broadcasting video as a director to the room, but only have a fixed amount of upload bandwidth or CPU.
&limittotalbitrate
can now take two values; the second of which gets used if the device is a 'mobile' device, while the first gets used otherwise. ie: &limittotalbitrate=1000,500
Useful if you don't know if the guest is going to join via Desktop or via Smartphone, and you wish to avoid overloading a mobile device.
When using the &limittotalbitrate
option as a director, the room settings will include a new slider to let you dynamically change that value.
This lets the director set a maximum total bandwidth outbound from them to the guests; useful if you set the total room bitrate to something high. Combined, you can ensure the guests as high quality as possible from you, without causing your OBS RTMP output or whatever to get smashed.
When using the Mixer App (vdo.ninja/alpha/mixer), the &limittotalbitrate
value was set to 350-kbps before, but now I have it set to 1500-kbps. Guests in the Mixer App should as a result now see the director's broadcast output in 3x higher quality now, for better or worse. I may adjust the default value in the mixer based on user issue reports.
The slider doesn't appear if not using the &limittotalbitrate
value in the URL (or if not using the Mixer App). It's just too confusing to explain to include it by default.
{% content-ref url="totalroombitrate.md" %} totalroombitrate.md {% endcontent-ref %}
{% content-ref url="roombitrate.md" %} roombitrate.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
Example: &optimize=1000
Value | Description |
---|---|
(integer value) | value in kbps |
(no value given) | 600-kbps |
0 |
disables the video track when not considered visible in a scene (OBS) |
&optimize
reduces the video bitrate to 600-kbps when the video is not visible in OBS (not active in a scene). This is mainly there to help with reducing load for OBS and for guests. It can take a few seconds for the bitrate to ramp back up after it becomes active again.
{% hint style="warning" %} This does not work with iPhone-sourced video streams. {% endhint %}
{% content-ref url="bitrate.md" %} bitrate.md {% endcontent-ref %}
They are separated in two groups: source side (push) options for the sender of the video and viewer side (view) options for the viewer of the video. Some of them are especially for rooms.
You have to add them to the source side (&push
).
Parameter | Explanation |
---|---|
&outboundvideobitrate | Target video bitrate and max bitrate for outgoing video streams |
&maxvideobitrate | Limits the max video bitrate out for this publisher, per stream out |
&limittotalbitrate | Limits the total outbound bitrate |
&controlroombitrate | Allows a guest to control their total room video bitrate dynamically from the settings panel (under video settings) |
&roombitrate | Limits any guest viewer in the group chat room from pulling the video stream at more than the specified bitrate value |
&maxbandwidth | Judges the available bandwidth of a sender's connection |
You have to add them to the viewer side (&room
or &view
or &scene
or &solo
).
Parameter | Explanation |
---|---|
&videobitrate | Sets the "desired target" bitrate in kbps |
&totalscenebitrate | Max. video bitrate a scene uses |
&totalroombitrate | The total bitrate a guest in a room can view video streams with |
&totalbitrate | Sets both &totalscenebitrate and &totalroombitrate flags |
&zoomedbitrate | Lets you set the target bitrate for a guest when they 'zoom in' (fullscreen) on a video |
&optimize | Video bitrate reduced when the video is not visible in OBS (not active in a scene) |
&screensharebitrate | Lets you manually set the video bitrate for screen-shares |
{% content-ref url="../video-parameters/" %} video-parameters {% endcontent-ref %}
{% content-ref url="../../guides/video-bitrate-in-rooms.md" %} video-bitrate-in-rooms.md {% endcontent-ref %}
{% content-ref url="../../guides/video-bitrate-for-push-view-links.md" %} video-bitrate-for-push-view-links.md {% endcontent-ref %}
description: >- Limits any guest viewer in the group chat room from pulling the video stream at more than the specified bitrate value
Sender-Side Option! (&push
)
&roomvideobitrate
&rbr
Example: &roombitrate=200
Value | Description |
---|---|
0 |
disables access to your video for other guests in a group room |
(some positive integer value) | max. allowed bitrate |
Limits any guest viewer in the group chat room from pulling the video stream at more than the specified bitrate value.
Does not impact what the director sees and does not limit the quality of what OBS has access to.
This is like &maxvideobitrate
, but &roombitrate
only applies to fellow group room guests.
Practically, a guest normally won't pull more than 1200-kbps and that's only if they click the HQ full-window button.
{% hint style="info" %} Set to 600-kbps, 200-kbps, or 80-kbps if the goal is to reduce CPU load. (2x, 3x, or 4x down-scaling is applied at those bitrate limits) {% endhint %}
{% content-ref url="totalroombitrate.md" %} totalroombitrate.md {% endcontent-ref %}
{% content-ref url="and-controlroombitrate.md" %} and-controlroombitrate.md {% endcontent-ref %}
{% content-ref url="and-maxvideobitrate.md" %} and-maxvideobitrate.md {% endcontent-ref %}
{% content-ref url="../../guides/video-bitrate-in-rooms.md" %} video-bitrate-in-rooms.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
Director Option! (&director
)
&totalroomvideobitrate
&trb
Example: &totalroombitrate=4000
or &totalroombitrate=2000,1000
Value | Description |
---|---|
(integer value) | set this to be the total combined room bitrate |
1000,500 |
Desktop bitrate, Smartphone bitrate |
The total bitrate a guest in a room can view video streams with; their combined bitrate total of all inbound video streams.
{% hint style="info" %} The default value is 500-kbps. {% endhint %}
Split between the number of streams that guest is viewing.
So for example, with 6-guests in a room, the default of 500-kbps will have each guest requesting 100-kbps from each other. 5 streams x 100-kbps.
&totalroombitrate
can take two values; the second of which gets used if the device is a 'mobile' device, while the first gets used otherwise. ie: &totalroombitrate=1000,500
Useful if you don't know if the guest is going to join via Desktop or via Smartphone, and you wish to avoid overloading a mobile device.
{% hint style="info" %}
Please note the difference between &totalroombitrate
and &totalscenebitrate
. &totalroombitrate
controls what the total bitrate for guests in a room is limited to. &totalscenebitrate
, on the other hand, is what you will want if you want to do the same for a view-link, added to OBS, for example.
{% endhint %}
Total room bitrate does not override any limits other guests in the room may have set to limit their outbound bandwidth.
Mobile devices are also coded to typically refuse requests of higher bitrates by other guests, even with a high total room bitrate set. Mobile devices will quickly overheat if publishing to many guests using software-encoding, so they are treated somewhat special.
In general, setting a high total room bitrate will increase the CPU and network requirements of the group room. Higher bitrates mean higher resolution, which means higher compute loads, so some computers may become overloaded. The default of 500-kbps seems low, but it was carefully selected to reduce such issues as much as reasonable.
Consider using &broadcast
, combined with either a powerful host computer or a service like Meshcast.io if you'd like to share high quality video to a larger room. A high total room bitrate value may cause severe problems in large rooms or on slower computers.
If the director joins the room, they automatically set the default total room bitrate for every guest that joins the room; guests will match the director's value. This feature may even override the URL-parameter that any guest might have added to their URL already, depending on version of VDO.Ninja. (still being tweaked based on user feedback)
The director can also dynamically change their total room bitrate value using a slider that appears when pressing the room-settings button in the lower control bar. This will instantly change the total room bitrate value for all guests.
There is a toggle in the director's room which adds &trb=2000
to the guest's invite link.
{% content-ref url="roombitrate.md" %} roombitrate.md {% endcontent-ref %}
{% content-ref url="and-totalbitrate.md" %} and-totalbitrate.md {% endcontent-ref %}
{% content-ref url="and-controlroombitrate.md" %} and-controlroombitrate.md {% endcontent-ref %}
{% content-ref url="../../guides/video-bitrate-in-rooms.md" %} video-bitrate-in-rooms.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&ar
Example: &aspectratio=1.77777
or &aspectratio=landscape
Value | Description |
---|---|
landscape |
aspect ratio of 16:9 (1.777777) |
portrait |
aspect ratio of 9:16 (0.5625) |
square |
aspect ratio of 1:1 (1) |
1.33333 |
aspect ratio of 4:3 |
(decimal number) | aspect ratio |
&aspectratio
changes the aspect ratio on the publisher side. Floating point value; 1.777777 is common; not supported by all browsers.
https://vdo.ninja/?webcam&aspectratio=1.33333
You can also change the aspect ratio via the video settings menu.
If using &aspectratio
, it will keep the height constant, and vary width, unless &width
is set, which will then be the fixed constant.
&aspectratio
works with screen-shares, so you can force crop an incoming screen-share to be a certain aspect ratio. If &screenshareaspectratio
is used it will apply to just screen-shares. If &screenshareaspectratio
does not have a value passed, it's assumed to be set as "default", which overrides &aspectratio
option, if used also.
{% content-ref url="../screen-share-parameters/and-screenshareaspectratio.md" %} and-screenshareaspectratio.md {% endcontent-ref %}
{% content-ref url="and-quality.md" %} and-quality.md {% endcontent-ref %}
{% content-ref url="../../source-settings/and-width.md" %} and-width.md {% endcontent-ref %}
{% content-ref url="../../source-settings/and-height.md" %} and-height.md {% endcontent-ref %}
Sender-Side Option! (&push
)
* on https://vdo.ninja/beta/ and https://vdo.ninja/alpha/
Example: &avatar=default
Value | Description |
---|---|
(no value given) | adds the ability to select an image, instead of a video device |
(encoded URL) | pre-selects the chosen image as an avatar |
default | will pre-select the default avatar, rather than leaving it un-selected |
&avatar
adds the ability to select an image, instead of a video device. The image will trigger when the video is muted or no video device is selected. A default avatar image is provided, but you can select your own from disk. &avatar=default
will pre-select the default avatar, rather than leaving it un-selected.
You can toggle it for the guest's invite link in the director's room:
You can encode your URL here:
https://www.urlencoder.org/
Choosing the default avatar / placeholder image is activated for the director on default
{% content-ref url="../newly-added-parameters/and-waitimage.md" %} and-waitimage.md {% endcontent-ref %}
{% content-ref url="../design-parameters/and-bgimage.md" %} and-bgimage.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
Video playback is disabled in VDO.Ninja.
{% content-ref url="../../general-settings/deafen.md" %} deafen.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
Example: &buffer2=500
Value | Description |
---|---|
(numeric value) | delay in ms |
&buffer2=500
is the same as &buffer
, but instead also tells the system to include the round-trip-time in the buffer delay calculation. This way 500-ms of buffer on a connection that has a 200ms ping time will result in a smaller 300-ms buffer, leading to an end-to-end playout delay of ~500ms.
It won't work that well with Meshcast.
It's not super precise, but on a stable connection maybe within 20-ms of flux?
{% content-ref url="../view-parameters/buffer.md" %} buffer.md {% endcontent-ref %}
{% content-ref url="../view-parameters/sync.md" %} sync.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&hint
&contenttype
&content
Example: &contenthint=detail
Value | Description |
---|---|
detail |
will prioritize resolution over frame rate |
motion |
will prioritize frame rate over resolution |
Depending on browser and version, there may be additional values you can pass, such as text
. Please see the following link for possible options that your browser may offer:
https://developer.mozilla.org/en-US/docs/Web/API/MediaStreamTrack/contentHint
&contenthint
can customize how you want VDO.Ninja to balance resolution vs frame rate, specifically when bitrate or CPU is insufficient to offer both at the same time.
The two options for video are detail
or motion
. Screen-shares generally tend towards detail
by default, and camera sources are tend towards motion
by default. detail
will try to prioritize resolution over frame rate, so the frame rate may drop a lot used. motion
will try to maximize frame rate, but may drop the resolution a lot. There's no way to force both on as there's no magic bullet if your CPU or network cannot keep up.
For more information on how to lock or maximize the resolution of a video feed, please see the following guide:
{% content-ref url="../../guides/how-do-i-lock-the-resolution.md" %} how-do-i-lock-the-resolution.md {% endcontent-ref %}
There is &screensharecontenthint
if you want the parameter to only affect screen-shares.
If facing poor video quality, you might also want to try increasing your bitrate or improving your network's connection quality, such as moving off of WiFi and onto Ethernet. Sometimes changing codecs, such as to h264 or av1, can help improve quality depending on the cause.
If your CPU is overloaded, h264 might use less CPU than other codecs. You can also consider using &meshcast to reduce CPU usage if sharing to multiple viewers at a time. Changing browsers might also help, such as trying Chrome, Firefox, or even Safari.
{% hint style="info" %}
If using &codec=vp9
on the viewer side, the frame rate may drop as low as even 5-fps.
{% endhint %}
{% hint style="warning" %} This parameter has been tested on Chrome, but other browsers may vary in behavior. Safari seems to just ignore things, for example. {% endhint %}
{% content-ref url="../screen-share-parameters/and-screensharecontenthint.md" %} and-screensharecontenthint.md {% endcontent-ref %}
Viewer-Side Option! (&scene
, &room
, &view
, &solo
)
&directorsonly
&do
&directoronly
will show the audio and video of the director but not of the guests. It is basically the same as &broadcast
but the guests can't hear each other. It is just the same as doing &view=DirectorStreamID
, but without having to know the stream ID for the director.
It will actually connect to any director, including co-directors, not just the main one.
&view
, &include
, &exclude
have a lower priority to &directoronly
. So if there are two directors, you can do &directoronly&exclude=coDirector123
, so that the codirector doesn't connect.
I changed the toggle in the director's room for "Guests hear others" from &view=
to &directoronly
. The point of this change is that the director can now still talk to those in the room.
Purpose of change: I had a user who wanted &broadcast
, but also not have the guests hear each other. It's a bit of a hassle to do &view=DirectorStreamID
, and the toggle is labelled to be misleading by saying "guests", not "everyone".
You can use &directoronly
to replace &broadcast
if you don't want the guests hearing each other.
{% content-ref url="../view-parameters/broadcast.md" %} broadcast.md {% endcontent-ref %}
{% content-ref url="../view-parameters/view.md" %} view.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&framerate
&fr
Example: &fps=60
Value | Description |
---|---|
(some positive integer value) | Frame rate (frames per second) |
&fps
specifies a target frame rate for the video capture, in frames per second; it is specified on the sender's side. The actual frame rate that's encoded and sent to the viewers may be less than the captured frame rate, sometimes quite a bit lower.
In most cases, if the target captured frame rate isn't supported, VDO.Ninja will throw an error. As a result, &fps is considered pretty strict and isn't recommended for most normal use cases.
{% hint style="danger" %}
If the camera cannot support the targetted frame rate, it will likely fail. Use &maxframerate
instead if you are okay with the system to fallback onto a different frame rate, as it is less strict compared to &fps
.
{% endhint %}
Limiting the frame rate can reduce the CPU load and the bandwidth, as the encoded video frame rate will try to match the capture the captured frame rate. The higher the encoded frame rate, the more CPU is typically used. 30-fps is fairly standard, although VDO.Ninja targets 60-fps by default.
You can change the frame rate dynamically, as the sender, via the settings -> video options; if your browser and device supports it that is. The viewer cannot change or request a specific frame rate, but they can specify &contenthint
, which indicates whether they prefer higher resolution vs higher frame rates.
&codec=av1
on the viewer side may achieve more stable encoded frame rates than &codec=h264
or &codec=vp8
, which are normally the defaults. Higher bitrates and more stable network conditions can also help ensure more stable frame rates of the actually streamed video. The encoded frame rate is often a bit less than what is captured, especially when dealing with packet loss.
Unless using &chunked
mode or a WHIP/WHEP source, it generally isn't possible to force a specific encoded frame rate. The system will try to keep the frame rate that's encoded and sent close to the captured frame rate, but it may drop due to packet loss, CPU limitations, or during moments of insufficient bitrate.
If screen sharing, window, vs. tab, vs. display capture methods can result in different max frame rates. Refer to the screen sharing section for details, but consider experimenting with different methods and browsers to find something that works for you. If screen sharing a game, consider setting the bitrate to at least 12- to 20-mbps, to keep the encoded frame rates steady.
24-fps capture devices may fail, so it is recommended to target 30- or 60-fps is possible. If in the UK or a country that has 50-hz lights or displays, you may wish to capture at 25-fps or 50-fps to avoid flicker caused by a mismatch between your display and the lights in the room. 30-fps or 60-fps is pretty standard for modern online video though.
If your display is set to 144-hz or some other odd frame rate, it is suggested to set your display to 120-hz or some multiple of 25- or 30-hz, depending on your location, to also avoid flicker with the camera's capture rate.
Capturing video higher than 60-fps, such as 120-fps, is supported in certain situations, such as if screen sharing an entire display that has higher 120-hz set. Normally however, the video encoding is limited to 60-fps max, so capturing at a higher frame rate doesn't make sense.
If using &chunked
mode on the sender's link however, chunked mode supports higher than 60-fps encoding, such as 120-fps. Chunked mode is considered an experimental option though, but it has been tested between two Windows 11 systems on a LAN running with Chrome.
Raspberry.Ninja or using a remote WHIP/WHEP stream as a source may also unlock the option for higher than 60-fps streaming, but this isn't a suggested approach to the problem.
{% content-ref url="../../source-settings/and-maxframerate.md" %} and-maxframerate.md {% endcontent-ref %}
{% content-ref url="../../source-settings/screensharefps.md" %} screensharefps.md {% endcontent-ref %}
{% content-ref url="and-contenthint.md" %} and-contenthint.md {% endcontent-ref %}
Sender-Side Option! (&push
)
Example: &imagelist=%5B%22https%3A%2F%2Fvdo.ninja%2Fmedia%2Fold_logo.png%22%2C%22https%3A%2F%2Fvdo.ninja%2Fmedia%2Fbg_sample.webp%22%2C%22https%3A%2F%2Fvdo.ninja%2Fmedia%2Fbg_sample2.webp%22%5D
Value | Description |
---|---|
(URL) | Passes a list of images via the URL |
Added options to host your own default background images for the virtual background effect. &imagelist=xxxx
can be used to pass a list of images via the URL.
Code to generate the list properly can be found here: https://jsfiddle.net/steveseguin/w7z28kgb/ (images must be cross origin enabled) - at the base of index.html, if self-hosting VDO.Ninja, you can hard-code the list of images as well.
When selecting a background image, you'll get a gentle glow around the selected image now. There's also a horizontal scroll bar, if the number of images listed are too much to fit.
If looking for a free image host, I think Imgur.com offers free image hosting that is CORS friendly. The URLs it provides are also seemingly safe to use without URL encoding. You can just replace the XXXXXXX
in the link below, with your Imgur provided ID value, and it might get you going.
Example: &imagelist=[%22https://i.imgur.com/XXXXXXX.png%22]
By default, the image may be mirrored to the publisher, as webcam previews are by default mirrored in VDO.Ninja. The image will not be mirrored in the output however; just in the preview.
You can disable the mirroring on the preview though; use &nomirror
on the URL as a parameter.
{% content-ref url="../../source-settings/effects.md" %} effects.md {% endcontent-ref %}
Sender-Side Option! (&push
)
If you want the VDO.Ninja self-preview to not be mini-sized in broadcast mode, which might be the case on mobile, you can try using &minipreview=0
or &largepreview
. These flags will disable the mini-preview functionality, keeping the preview the same size as other videos.
{% content-ref url="../../source-settings/and-minipreview.md" %} and-minipreview.md {% endcontent-ref %}
{% content-ref url="and-minipreview-1.md" %} and-minipreview-1.md {% endcontent-ref %}
{% content-ref url="../../source-settings/and-preview.md" %} and-preview.md {% endcontent-ref %}
{% content-ref url="../../source-settings/and-nopreview.md" %} and-nopreview.md {% endcontent-ref %}
{% content-ref url="../view-parameters/broadcast.md" %} broadcast.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&mpo
Example: &minipreviewoffset=60
Value | Description |
---|---|
(no value given) | 0 | left-most side of the screen |
40 | center of the screen |
(integer value) -20 to 120 | defines the position of the mini preview |
Added &minipreviewoffset
accepts an integer value, -20
to 120
, which is used to position where the mini preview is located by default on screen. 40
would imply center of the screen, as the mini preview is about 20% of the screen size. 0
(or just &minipreviewoffset
) is the left-most side of the screen.
&minipreviewoffset=40
{% content-ref url="../../source-settings/and-minipreview.md" %} and-minipreview.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&nodirectorvideo
is just like &novideo
(disables all video playback on the local computer), except it only applies to incoming connections from room directors. So, if your are using the Mixer App with OBS, but you want to exclude the video of yourself from the OBS, this potentially could be an easy way to do that.
{% content-ref url="and-novideo.md" %} and-novideo.md {% endcontent-ref %}
{% content-ref url="../audio-parameters/and-nodirectoraudio.md" %} and-nodirectoraudio.md {% endcontent-ref %}
{% content-ref url="../../viewers-settings/director.md" %} director.md {% endcontent-ref %}
{% content-ref url="../../steves-helper-apps/mixer-app.md" %} mixer-app.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&nv
&hidevideo
&showonly
&novideo
disables all video playback on the local computer. Useful for reducing the CPU and network load on other connect peers if voice-chat is sufficient.
- Join a group-room as audio-only, to limit load on the guests.
When used together with &noaudio
(&novideo&noaudio
), prevents guest room member from seeing or hearing other member's audio or video feeds.
- Useful for directors who may wish to only issue commands or text chat, but not need to see video or audio.
You can pass a comma separated list of stream IDs that will be excluded, so that they specifically will play video. ?novideo=guest1a,guest2a
will only allow video from guest1a and guest2a to play.
Video tracks are blocked and do not form any connection when using peer-to-peer, not taking up bandwidth or system load, but they also cannot be re-enabled without reconnecting. Video tracks from WHIP-based sources, Iframes, or some non-standard sources may still allow video tracks to connect, using up bandwidth, but will not be rendered. Check the connection stats for that stream ID to confirm.
Use &broadcast
or &showonly
if you want to disable all videos except any stream IDs listed.
{% content-ref url="../view-parameters/noaudio.md" %} noaudio.md {% endcontent-ref %}
{% content-ref url="novideo.md" %} novideo.md {% endcontent-ref %}
{% content-ref url="and-nodirectorvideo.md" %} and-nodirectorvideo.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&q
Example: &quality=0
Value | Description |
---|---|
0 | (no value given) |
about 1080p60, depending on hardware |
1 |
about 720p60, depending on hardware |
2 |
about 360p30, depending on hardware |
-1 (device's default) |
useful in allowing the screen share at the same resolution as the display |
Presets the "quality" setting for a guest. Not "strict" and is less likely to give errors than explicit resolution requests.
Without using &quality
on the URL a guest can change the "quality" when setting up the camera:
Use &width
and &height
to get a higher resolution than 1920x1080.
There is a toggle in the director's room guest's invite link customization which adds &q
:
{% content-ref url="../../source-settings/screensharequality.md" %} screensharequality.md {% endcontent-ref %}
{% content-ref url="../../newly-added-parameters/and-mediasettings.md" %} and-mediasettings.md {% endcontent-ref %}
{% content-ref url="../../source-settings/and-width.md" %} and-width.md {% endcontent-ref %}
{% content-ref url="../../source-settings/and-height.md" %} and-height.md {% endcontent-ref %}
Viewer-Side Option! (&scene
, &room
, &view
, &solo
)
&sharpen
&dpi=2
&sharper
is now an alias of &dpi=2
, which should 'up to' double the amount of playback video resolution, if the dynamic resolution optimization is enabled at least, in certain cases. This is a lot like &scale=100
, but perhaps slightly more efficient in some cases. This is mainly for when you intend to have a large screen-share in a scene, where you don't want the tiny guest videos to be a 100% scale, but 50% scale is fine (up from 25% scale). &dpi
already exists on production, but by adding these aliases, I hope it's more discoverable.
As an alternative to &sharper
, I've also added &sharperscreen
, which sets &scale=100
, but only for screen-shares (virtual cameras not included). This is probably even more efficient than &scale=100
or &sharper
, and it's designed for when screen-sharing a lot of text. Text looks a bit soft when streaming video at 1:1 pixel resolution.
It's recommended to only use these parameters within the context of a scene link, and not on guest links, due to the higher CPU / bandwidth it may use.
{% content-ref url="../screen-share-parameters/and-sharperscreen.md" %} and-sharperscreen.md {% endcontent-ref %}
{% content-ref url="../view-parameters/dpi.md" %} dpi.md {% endcontent-ref %}
{% content-ref url="../view-parameters/scale.md" %} scale.md {% endcontent-ref %}
Viewer-Side Option! (&scene
, &room
, &view
, &solo
)
This option decodes incoming video (first video to load), but plays them back as series of full-window images. That is, a single image element, that gets updated 24 times a second, instead of playing the video back within an efficient video element. I have no idea why you might want this option, as it pretty crude up and uses up a lot of CPU, but you can right-click to save a single frame from the video to disk, as a PNG file. This might be useful if you need to take a lot of snap shots of some video and don't want to have to hassle with cropping a window-grab. Quality of the images is pretty high; near lossless.
{% content-ref url="../settings-parameters/and-postimage.md" %} and-postimage.md {% endcontent-ref %}
Viewer-Side Option! (&scene
, &room
, &view
, &solo
)
&vh
Example: &viewheight=1080
Value | Description |
---|---|
(value integer) | video height in pixels |
Added new viewer-side parameters that can be used in place of &scale
: &viewheight=180
and &viewwidth=320
, which effectively does the same thing as &scale
, but instead you pass a resolution.
It's important to note, that due to flexibility to request width/heights that are not aspect-ratio compatible, and due to bitrate/quality resolution limitations, these values are just 'max' target resolution values; the actual resolution you get could be still less. They also do not impact the actual capture resolution of the remote sender's camera, so its purely for requesting a specific downscaled resolution. This command applies to all video elements in a view port, and it disables the auto-scaler functionality.
Similarly, also added the option to the IFRAME API to request different down-scaled resolutions dynamically, per connection, if you want greater programmatic control vs static URL options.
{% content-ref url="and-viewwidth.md" %} and-viewwidth.md {% endcontent-ref %}
{% content-ref url="../view-parameters/scale.md" %} scale.md {% endcontent-ref %}
{% content-ref url="../../newly-added-parameters/and-noscale.md" %} and-noscale.md {% endcontent-ref %}
Viewer-Side Option! (&scene
, &room
, &view
, &solo
)
&vw
Example: &viewwidth=1920
Value | Description |
---|---|
(value integer) | video width in pixels |
Added new viewer-side parameters that can be used in place of &scale
: &viewheight=180
and &viewwidth=320
, which effectively does the same thing as &scale
, but instead you pass a resolution.
It's important to note, that due to flexibility to request width/heights that are not aspect-ratio compatible, and due to bitrate/quality resolution limitations, these values are just 'max' target resolution values; the actual resolution you get could be still less. They also do not impact the actual capture resolution of the remote sender's camera, so its purely for requesting a specific downscaled resolution. This command applies to all video elements in a view port, and it disables the auto-scaler functionality.
Similarly, also added the option to the IFRAME API to request different down-scaled resolutions dynamically, per connection, if you want greater programmatic control vs static URL options.
{% content-ref url="and-viewheight.md" %} and-viewheight.md {% endcontent-ref %}
{% content-ref url="../view-parameters/scale.md" %} scale.md {% endcontent-ref %}
{% content-ref url="../../newly-added-parameters/and-noscale.md" %} and-noscale.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&novideo
&nv
&hidevideo
Example: &showonly=streamID1,streamID2
Value | Description |
---|---|
(string value) | the stream IDs to view; can be a comma separated list |
&showonly
only shows any stream IDs that are listed. Useful for reducing the CPU and network load on other connect peers if voice-chat is sufficient.
- Useful for a large group room where you want everyone in the room to see only the OBS Virtualcam output.
- Consider using
&broadcast
option instead of this flag as it is better suited for presenting a single feed to a group than using&showonly
alone.
This is actually just an alias of &novideo
.
{% content-ref url="../view-parameters/broadcast.md" %} broadcast.md {% endcontent-ref %}
{% content-ref url="and-novideo.md" %} and-novideo.md {% endcontent-ref %}
description: >- Resolution, FPS, effects, self preview, mute video, PTZ, codec, buffer, broadcast, scale
They are separated in three groups: general options (push and view), source side (push) options and viewer side (view) options.
If you want to change the bitrate:
video-bitrate-parameters
You can add them to both, source (&push
) and viewer (&view
, &scene
or &solo
) sides.
Parameter | Explanation |
---|---|
&blind | Video playback is disabled |
You have to add them to the source side (&push
).
Parameter | Explanation |
---|---|
&quality | Presets the quality setting for a guest |
&width | Sets the maximum width of the video allowed in pixels |
&height | Sets the maximum height of the video allowed in pixels |
&aspectratio | Changes the aspect ratio on the publisher side |
&contenthint | =motion prioritizes resolution;=detail prioritizes frame rate |
&mediasettings | Adds the option to change the video and audio settings dynamically via the settings menu |
&noscale | Disables the publishing resolution from being capped |
&fps | Sets the maximum frame rate of the video in frames per second |
&maxframerate | Like &fps , except it will allow for lower frame rates if the specific frame rate requested failed |
&effects | Applies effects to the video/audio feeds |
&effectvalue | Sets the amount of blur or effect applied |
&imagelist | Can be used to pass a list of background images via the URL |
&avatar | Adds the ability to select an image, instead of a video device |
&fullscreen | The preview video will be fullscreen |
&showpreview | Forces the guest to have a self-preview |
&minipreview | Mini self-preview at the top right corner |
&minipreviewoffset | Used to position where the mini preview is located by default on screen |
&largepreview * | Will disable the mini-preview functionality |
&nopreview | Disables the local self-preview |
&hideguest | Has a guest join a room not visible to others |
&videomute | Auto mutes guest's video |
&ptz | Enables pan/tilt control of the device, if compatible |
&webp | Custom video codec for broadcasts |
&webpquality | Quality setting for the &webp option |
*NEW IN VERSION 24
You have to add them to the viewer side (&room
or &view
, &scene
or &solo
).
Parameter | Explanation |
---|---|
&scale | Scales the video resolution of the inbound video by the given percent |
&dpi | Overrides the automatically selected Device Pixel Ratio |
&sharper | Should 'up to' double the amount of playback video resolution |
&viewwidth | Does the same thing as &scale but you pass the width in pixels |
&viewheight | Does the same thing as &scale but you pass the height in pixels |
&codec | Sets the codec to encode the video |
&h264profile | OpenH264 software encoding will be used |
&buffer | Sets the video buffer |
&buffer2 | Same as &buffer , but instead includes the round-trip-time |
&fadein | Has videos fade in smoothly |
&broadcast | A useful flag to allow the director to present their own video to the group, often used in conjunction with a virtual webcam or Meshcast. It allows for larger groups rooms by reducing load on guests |
&directoronly | A useful flag to allow the director to present their own video to the group, often used in conjunction with a virtual webcam or Meshcast. It allows for larger groups rooms by reducing load on guests |
&showonly | Only shows any stream ID that is listed |
&novideo | Disables all video playback on the local computer |
&nodirectorvideo * | Disables all video playback from room directors |
&slideshow | Plays video back as a series of full-window images |
*NEW IN VERSION 24
{% content-ref url="../video-bitrate-parameters/" %} video-bitrate-parameters {% endcontent-ref %}
description: >- Auto-hides remote guests videos when added, if those guests are not speaking actively
Viewer-Side Option! (&view
, &scene
, &room
)
&sas
&speakerview
Example: &activespeaker=1
Value | Description |
---|---|
1 | (no value given) |
will only show one speaker at a time; the loudest or last-loud speaker |
2 |
will show whoever is talking; mixed together; if no one is talking, just shows yourself |
3 |
the same as 1 , but it will not switch to show audio-only sources (just video only) |
4 |
the same as 2 , but it will not switch to show audio-only sources (just video only) |
In all four cases, if someone else is talking/active, your local preview will become a mini-preview in the top right.
{% content-ref url="../mixer-scene-parameters/and-motiondetection-alpha.md" %} and-motiondetection-alpha.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
Example: &channeloffset=1
Value | Description |
---|---|
(numeric value) | Number of channels to shift the audio, starting at channel 0 |
&channeloffset
shifts audio channels 0 and 1 up channels, based on the offset value you set.
Total channels is assumed to be 8 if this is used and not otherwise specified.
Does not work with all audio output devices and may require experimentation.
Best to use this with a mono input, as stereo channel shifting can cause issues - simpler that way.
Please see here for detailed testing results with different audio devices: https://docs.google.com/spreadsheets/d/1R-y7xZ2BCn-GzTlwqq63H8lorXecO02DU9Hu4twuhuA/
{% content-ref url="../audio-parameters/and-inputchannels.md" %} and-inputchannels.md {% endcontent-ref %}
{% content-ref url="and-channels.md" %} and-channels.md {% endcontent-ref %}
{% content-ref url="../audio-parameters/and-channeloffset-1.md" %} and-channeloffset-1.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
Example: &channels=4
Value | Description |
---|---|
(integer value) | number of audio output channels |
Left and right is available for most users; channels 1 and 2
- Up to 6-channels is possible, if your output device supports it.
- On Windows, you might need to select 5.1 surround sound with your device in the Windows audio settings.
- On macOS, you might want to consider using SoundFlower, as it seems the most correct with its routing.
Designed to be used with &channeloffset
.
Please see here for detailed testing results with different audio devices: https://docs.google.com/spreadsheets/d/1R-y7xZ2BCn-GzTlwqq63H8lorXecO02DU9Hu4twuhuA/
{% hint style="info" %}
If looking to set the number of input channels, rather than output, please see &inputchannels
instead.
{% endhint %}
{% content-ref url="and-channeloffset.md" %} and-channeloffset.md {% endcontent-ref %}
{% content-ref url="../audio-parameters/and-inputchannels.md" %} and-inputchannels.md {% endcontent-ref %}
{% content-ref url="../audio-parameters/and-channeloffset-1.md" %} and-channeloffset-1.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&ex
Example: &exclude=StreamID1,StreamID2
Value | Description |
---|---|
(string value) | stream ID to view; can be a comma-separated list of IDs |
Any stream ID listed as a value will NOT be played or requested.
Example usage:
https://vdo.ninja/?room=myroom123&exclude=stream121,sidestream321
{% hint style="warning" %}
Excluding a stream ID will prevent even a peer connection.
No video, audio, or chat can be had.
{% endhint %}
Viewer-Side Option! (&view
, &scene
, &room
)
Example: &maxptime=60
Value | Description |
---|---|
(integer value) | max packet size in ms |
{% hint style="danger" %} If you do not know what this is, you definitely don't want to touch it. {% endhint %}
60-ms is common. 30-ms is reasonable.
Optimized already, but it's available for experimentation and fun if desired.
{% content-ref url="and-ptime.md" %} and-ptime.md {% endcontent-ref %}
{% content-ref url="minptime.md" %} minptime.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&mp
Example: &maxpublishers=7
Value | Description |
---|---|
(integer value) | limit number of remote peer connections |
Limits the number of remote peer connections that are publishers.
{% content-ref url="../../source-settings/and-maxconnections.md" %} and-maxconnections.md {% endcontent-ref %}
{% content-ref url="../../source-settings/and-maxviewers.md" %} and-maxviewers.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
Example: &obsfix=5
Value | Description |
---|---|
(integer value) | adjust the sensitivity of the packet loss 'fix' for OBS |
(no value given) | defaults to 15 |
0 | off |
Turns it off |
It's on by default and set to 15
if only using OBS and if using the VP8/VP9 video codec.
- There is a bug in OBS where the VP8 codec (default in most cases) does not handle packet loss events. This function attempts fixes its.
- You can disable this 'fix' by passing it the value
0
oroff
. - When on, it will trigger a key frame request to combat pixel smearing caused by packet loss and poor network conditions.
- Triggers around every 3-seconds if needed; may not activate often with very light packet loss.
- May lower video quality, or may not be desirable, so this flag lets you disable it.
- Stream pushers can open the debug/stats menu and manually send key frames also.
- VP9 is far less prone to packet loss issues, but it can still happen with heavy packet loss.
- Increasing the integer value passed to
&obsfix
will reduce the frequency and sensitivity of the key frame request.
Viewer-Side Option! (&view
, &scene
, &room
)
&pan
Example: &panning=120
Value | Description |
---|---|
(no value given) | 90 |
has the audio centered, but published as a mono-stereo stream |
(0-89) | pans the audio left |
(91-180) | pans the audio right |
-1 |
panning will be randomized |
The default, if no value is passed, is to have the audio centered, but published as a mono-stereo stream.
To pan the audio left, pass a value of 0 to 89.
To center, pass 90 or leave blank.
To pan the audio right, pass a value of 91 to 180.
0 is the most left, while 180 is the most right.
If negative 1 is passed &panning=-1
, then the panning will be randomized; center weighted a bit. This allows for a group-room experience where everyone in the room to have a different spatial position, making it easier to have larger group discussions where guests may sound similar to each other.
You may need to use &stereo
as a flag, or variants of it on the publisher and/or viewer's side, to ensure the audio is transmitted as stereo as well.
Please also note, the volume is gained up or down digitally to compensate for the value changes of mixing and panning; it attempts to retain the same loudness and avoid clipping. Please report issues or provide feedback if you encounter problems with it.
Also note, the audio can be dynamically panned left or right thereafter by the IFRAME API. For VR-applications, this could provide for some interesting user experiences.
{% content-ref url="../../general-settings/stereo.md" %} stereo.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&916
&vertical
Optimize the auto-mixer to work with video streams that are in portrait mode (versus landscape).
Can be used together with &cover
to get a better effect.
For example:
https://vdo.ninja/?scene&room=roomname&portrait&cover
{% content-ref url="cover.md" %} cover.md {% endcontent-ref %}
{% content-ref url="../../newly-added-parameters/and-square.md" %} and-square.md {% endcontent-ref %}
{% content-ref url="../design-parameters/and-rotate.md" %} and-rotate.md {% endcontent-ref %}
{% content-ref url="../../newly-added-parameters/and-43.md" %} and-43.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
Example: &ptime=40
Value | Description |
---|---|
(integer value) | audio packet size in ms |
{% hint style="danger" %} If you do not know what this is, you definitely don't want to touch it. {% endhint %}
{% content-ref url="minptime.md" %} minptime.md {% endcontent-ref %}
{% content-ref url="and-maxptime.md" %} and-maxptime.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&sr
Example: &samplerate=48000
Value | Description |
---|---|
(integer value) | sample-rate in hz |
&samplerate
sets the audio playback sample-rate in Hz (not capture or transmission sample-rate).
This is mainly for debugging audio distortion or clicking issues.
General Option! (&push
, &room
, &view
, &scene
)
Example: &sink=1dee4206f5deb75973e33f7078d4c1539782e29e255799d59b8b61a855d17bea
Value | Description |
---|---|
(string value) | device ID (https://vdo.ninja/devices) |
{% hint style="danger" %} Device IDs are tied to the browser + domain + cookie session combination. {% endhint %}
Outputs the audio to the specified audio output device, rather than the default.
Designed to be used in conjunction with https://vdo.ninja/electron.
You can find out the string value of your audio output device here: https://vdo.ninja/devices
{% content-ref url="../setup-parameters/and-audiooutput.md" %} and-audiooutput.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&animate
Example: &animated=false
Value | Description |
---|---|
(no value given) | videos in a group scene will slide around when being re-arranged |
false | 0 | no | off |
disables the animated effect |
Videos in a group scene will slide around the screen when being re-arranged, such as when a new video gets added to the scene.
{% hint style="info" %}
In the newest version of VDO.Ninja &animated
is on by default. You can disable it with &animated=0
. There is also a toggle in the director's room to disable it in the guest's invite URL.
{% endhint %}
Mobile phone users will not have this effect enabled by default, but most other guest and scene types will.
You can force enable this animation effect by adding &animated
to the URL, or you can force disable the effect by passing false, such as &animated=false
, or passing 0
, no
, or off
.
{% content-ref url="fadein.md" %} fadein.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&ab
Example: &audiobitrate=128
Value | Description |
---|---|
(integer value) | bitrate in kbps |
The default is around 32-kbps per track with a mono-channel (VBR on by default).
The audio codec used is OPUS and the target sample rate is 48khz.
510-kbps is the highest value allowed, with around 300-kbps the highest value for a mono-channel track.
For voice, the default audio bitrate is sufficient for most users, however 64- to 80-kbps may offer an audible improvement. For music, you may wish to go higher.
{% hint style="info" %} For reference, music streaming providers will use around 64- to 128-kbps as their default. {% endhint %}
When an audio bitrate is manually specified, CBR is enabled by default.
Setting the audio bitrate to be very high can sometimes cause video bitrates on weak connections to become stuck at around 30-kbps.dio on mobile devices.
If you are using the Echo-Cancellation (&aec
) and &denoise
filters, audio quality may still sound like telephone quality in some cases, even with an increased bitrate. These filters are on by default.
Filtering out echos and noise can impact the audio quality, so while these filters are effective in what they do, the harder they have to work, the more the audio will sound like a telephone call.
Finding ways to eliminate background noise, hum, and feedback can improve audio quality, as the echo/noise filters will then not need to activate or be used with such strength. You can of course disable those filters entirely, which when combined with a higher audio bitrate, will get you closer to what sounds like a raw audio recording; this assumes feedback isn't an issue of course.
{% content-ref url="../video-bitrate-parameters/bitrate.md" %} bitrate.md {% endcontent-ref %}
{% content-ref url="../../general-settings/stereo.md" %} stereo.md {% endcontent-ref %}
description: >- A useful flag to allow the director to present their own video to the group, often used in conjunction with a virtual webcam or Meshcast. It allows for larger groups rooms by reducing load on guests
Viewer-Side Option! (&view
, &scene
, &room
)
&bc
Example: &broadcast=StreamID
Value | Description |
---|---|
(no value given) | Only play-back the director's stream |
(stream ID) | You can pass an optional stream-ID to specify the stream's source manually. If no value is passed, the source will be the room's director video out feed. |
This command is like using &showonly=directorsStreamID
but with some extras tweaks that might be appropriate to a larger group room.
In essence, &broadcast
only allows the playback of video-tracks and shared-websites that originate from the main director. You may not know the stream ID of the main director ahead of time, so this parameter handles that for you automatically as well.
You can pass a stream ID as a value, which will specify the video source to be from a guest (or co-director), rather than the main director. You cannot pass multiple stream IDs to the &broadcast
flag; just one. If needing more, consider using the &showonly
flag instead.
You add &broadcast
to the guest invite links. You do not add this to the director or scene links.
{% embed url="https://youtu.be/QcFKI9q0yFs" %} Configuring VDO.Ninja in a broadcast group mode {% endembed %}
In &broadcast
mode, only the director is sharing video to the guests of the group room, so only the director has the burden of encoding multiple video streams and uploading them to guests. This is great if your guests are primarily on mobile-devices, have slow-Internet, or it is a larger room; otherwise each guest would be sharing video with each other guest as well.
When used with Meshcast, the director can reduce their own system burden even further. You can achieve fairly large group rooms with modest system requirements this way.
To ensure the guests see all that's needed, if the director selects their Virtual Camera output as their video source, then all the guests in the room will be able to see the live output of that virtual camera stream. The source of this virtual camera feed could be the main OBS output mix, or a specific custom scene mix that's design just for the guests.
- The guest's self-preview becomes a mini-preview, rather than the normal large self-preview. You can disable the preview all together by using
&nopreview
. - While
&broadcast
disables the video from other guests, it does not disable or impact their audio, so guests should still be able to hear each other. &showlist
is enabled by default for the guests, which provides a list of those in the room to the guests.&showlist=0
can hide this, when added to the guest link; useful if you want a cleaner output for the guests.- The header bar, with basic stats, is shown by default.
&noheader
can be added to the guest links, which will hide this top bar, room name and the stats. - It hides the audio-only playback elements of other guests in the room, so it's not possible to mute or control the volume, as a guest, or other guests, when
&broadcast
is set. This is akin to having&style=1
set.
You can some-what imitate the &broadcast
parameter using something like :
&showonly=DirectorStreamID&noiframe=DirectorStreamID&minipreview&style=1
While the &broadcast
flag is great for reducing the load on guests in a room, it will put all the load onto the director instead.
- Consider using NVEnc or other hardware-encoders to encode any RTMP streams in your studio software to reduce CPU load there. This frees up more CPU for VDO.Ninja.
- Make sure you have a capable computer; an AMD 5900x CPU is recommend for most users using this mode without Meshcast, allowing for medium-sized group rooms with some headroom to spare.
- A quad-core computer might only be able to support 1 or 2 guests adequately in this mode, although using Meshcast can help overcome that limitation.
- If you would like the guests to see even higher quality video, consider using
&totalroombitrate=2500
as an option to greatly improve the video quality. This also will greatly also increase the load on the director, so good internet and a powerful CPU will be needed.
- Using a service like meshcast.io, along with the
&website
sharing option, can also greatly reduce load on the director and guests. The website sharing function works with other video content delivery networks, not just Meshcast.io, so you have choices. - When the director shares a website, their own low-latency VDO.Ninja audio remains active, so audio doubling could happen if the website contains their audio also. You'll want to mute either the website's audio or the director's VDO.Ninja audio, to avoid this issue. To also avoid echo-cancellation issues and audio delays, it is recommended to mute the website audio, as VDO.Ninja's audio will have not have those issues.
- You may want to add
&novideo
to the guest invite links if you only intend to share video via the website sharing function. This ensures the director's VDO.Ninja video-track doesn't appear, as VDO.Ninja can't always tell if a website contains a video track or not, and so may show the director's video alongside the shared website in some cases otherwise. - In more recent versions of VDO.Ninja (v22), Meshcast is available built-into VDO.Ninja via the
&meshcast
parameter, which sends both audio and video over meshcast in sync, without concerns of echo cancellation or audio doubling. Just add&meshcast
to the director's URL to use this mode; the director's audio and video will auto-publish via Meshcast without needing to visit meshcast.io. - The director's ability to share a website (meshcast.io link) is via a button found in the director's control bar. The director doesn't need to use
&website
parameter since a website sharing functionality has its own dedicated button in the director's control room.
- If using meshcast.io and the website share functionality, rather than
&meshcast
, you will want to mute the Meshcast source to avoid echo cancellation or audio-doubling. The meshcast.io source page has options to do so there, but you can also add&mute
to the meshcast.io when sharing it, to have it auto-mute on playback for the guests.
{% embed url="https://youtu.be/YxduINMXw1M" %} Understanding Meshcast as a tool for VDO.Ninja {% endembed %}
{% embed url="https://www.youtube.com/watch?v=-7QsLChfdsE" %} An older video, but it gets some basics across still about &broadcast mode {% endembed %}
{% content-ref url="../video-parameters/novideo.md" %} novideo.md {% endcontent-ref %}
{% content-ref url="../video-parameters/and-largepreview.md" %} and-largepreview.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
Example: &buffer=500
Value | Description |
---|---|
(numeric value) | delay in ms |
This feature will increase the size of the audio and video playout delay by means of tweaking the webRTC jitter buffer pipeline (or a related buffer).
This can effectively be used as a way to delay the incoming video and audio by around 4-seconds. It's compatible with modern Chromium-based browsers, likely Firefox, but not Safari.
While in theory this option can also help to improve video and audio quality, as a larger playback buffer should help reduce the effects of network jitter and packet loss, it's not a miracle solution in this regard. Adding 200-ms of buffer delay using this feature is worth trying however, as some users have reported it has helped improve their connections.
The problem is that the browser doesn't fully make use of the available buffer if set high, and so it's largely used as mainly a hint. Network conditions, memory limits and other factors may impact the results as well.
Older versions of Chromium allowed upwards of 15-seconds of buffering, with recent versions of Chromium allowing up to just 4-seconds.
If using the &chunked
transfer mode, the method and function of the &buffer
option is different than normal. There is not hard coded limit on what delay you can add, as it that uses it a custom buffering solution that isn't controlled by the browser. You can set the delay to be whatever you want; minutes even, assuming you have the memory for it.
Using &buffer
with &chunked
mode can improve quality, however more than a few seconds is probably not advisable.
&buffer=0
will force the audio to be in sync with the video, with the video playing back with minimal delay.
&buffer=100
will add a 100-ms time delay to the video, on top of any existing delay.
&buffer=200
can help reduce video problems, such as frame jitter, with 200-ms of added delay.
{% hint style="warning" %}
- This feature will only work if playing the video in Chrome or Chromium-based browsers of around version 80 and newer.
- OBS v27.1.3 or older (on PC) uses v75 though, so you will need to update to OBS 27.2 or newer to use it there.
- The Electron Capture app also supports the
&buffer
command, along with vMix using a compatible Chromium version. - Using the
&buffer
command may stop Echo Cancellation from working due to the audio delay this feature produces. - Beyond 3-seconds of buffering may cause audio/video sync issues. {% endhint %}
{% hint style="info" %}
You can refer to the &sync
command if you wish to delay the audio, relative to the video. &buffer
will try to keep the audio and video in sync, which might always be desired.
{% endhint %}
When using &buffer with a stream that is being sent using chunked-mode (&chunked), the method of buffering will be different as it doesn't rely on the built-in system playout webRTC buffer delay function.
The practical benefit of using &chunked mode with &buffer is that you can have buffers that are minutes long, up to whatever your system's resources can handle.
As well, the buffering works to buffer the stream, in a way similar to HLS or RTMP buffering.
The default buffer is around 1-second actually when using &chunked mode, as it requires a buffer to avoid playback issues. If the buffer underruns, the stream may fail.
Please refer to &chunked mode for more details, but it could be an option for you if your goal is to improve the quality of streams when facing high-packet loss. It's only compatible with Chromium-based browsers; not Firefox or Safari as of yet.
Update in v23
The option to right click a remote video and add/adjust the &buffer
delay for that specific video dynamically.
{% content-ref url="../video-parameters/and-buffer2.md" %} and-buffer2.md {% endcontent-ref %}
{% content-ref url="sync.md" %} sync.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&videocodec
&codecs
Example: &codec=h264
Value | Description |
---|---|
h264 | request the h264 codec |
vp8 | request the VP8 codec |
vp9 | request the VP9 codec |
av1 | request the AV1 codec |
webp | request the webp codec |
hardware | request the h264 codec and&h264profile |
av1,h264 | Comma separated values that define the order of preferred video codecs if the primary one fails |
https://vdo.ninja/?view=abc123
&codec=h264
https://vdo.ninja/?room=xxx7654&scene&bitrate=2000
&codec=vp9
The &codec
parameter is added to the viewer-side; so the &view
or &scene
link.
Video that is captured by a camera is compressed and sent over VDO.Ninja. The default codec is left up to the peer-connection to decide on, where the viewer and the sender agree on what is best automatically.
Normally VP8 is selected, which is an older codec that uses little CPU, but isn't as efficient as some others. Some mobile devices may hardware-encoder VP8, such as Google Pixel phones, but the vast majority will use software (CPU) to encode VP8.
H264 is the second most common codec automatically selected, which is popular with Apple-devices and many Android devices. H264 is commonly hardware-encoded, which *sometimes* uses less CPU and battery power, but hardware-encoding is more fickle than software-based encoding.
VP9 and AV1 are more modern codecs, with AV1 only supported by Chromium-based browsers using Version 90 or newer, although. VP9 may not be available on older Apple devices, but is becoming more available. It is not common to find VP9 or AV1 hardware encoded currently.
Hardware-encoding has pros and cons. A device generally has limited hardware-encoders, and they are also normally more problematic, including compatibility issues.
{% hint style="warning" %} If running into problems with video distortion, switching the codec to VP9 may resolve the issue, although at the cost of higher-CPU load. {% endhint %}
H264 may offer hardware encoding for better battery life with mobile and embedded devices. In these causes, it is often used automatically by VDO.Ninja. Support for H264 on Android devices is hit and miss though, so if enabling it, be prepared for it to potentially result in no video playback.
iOS devices should generally use H264, but the max resolution supported then is 1280x720p30 with iOS 14 and under. With iOS 15, 1080p30 is supported, but I'm not entirely sure if 1080p30 is hardware-encoded as the phone will get quite warm at that resolution.
macOS systems generally prefer H264 and will sometimes hardware-encode. It seems to use less CPU resources decoding H264 versus other codecs, so give it a go if facing CPU issues on your mac.
As for Windows PCs, if using a Chromium-based browsers (Chrome/Edge), your system may choose to use hardware-encoding when using publishing via a H264. This typically happens at 360p or higher resolutions, but it may not always happen. You can check to see if you are hardware-encoding by checking your video out stats, via CTRL + Left-Click
on your video: "External Encoder" would likely indicate hardware acceleration of some sort.
If you have an Nvidia graphics card, you may be limited to two or three H264 hardware encoders, which could cause problems if you intend to use NVEnc for RTMP streaming also. AMD hardware encoders may limit bitrate.
On PC, while H264 encoding will use less CPU than other codecs, hardware-encoders may actually use more CPU than the software-based ones.
H264 doesn't seem to offer the picture quality, at least when screen sharing, but it seems more resistant to rainbow puke in OBS 27.1 and older.
Firefox on Apple M1 chips may not support H264. OperaGX may also not support H264.
Starting with VDO.Ninja v20, you can specify the flavour of H264 being used with the &h264profile
flag.
Using that parameter without specifying a particular H264 profile ID will trigger the software OpenH264 encoder to be used, blocking any hardware H264 encoder. On Windows, OpenH264 may actually use less CPU than the a hardware encoder and may side step video glitching issues.
Definitely worth trying to use this flag, in combination with &codec=h264
, if you're looking to inch out every bit of performance, but testing is needed if going this direction.
VP8 is the default codec selected in most cases, even though Apple devices may default to H264.
OBS on PC does not handle packet loss well when using VP8, while the Electron Capture app handles VP8 very well.
iOS devices can stream at 1080p30 or 720p60 when using VP8, but they get warm in doing so.
Google Pixel smartphones may default to VP8, using hardware-encoding, but may also face video distortion with some browsers as a result. Switching to VP9 may fix the issue.
VP8 generally uses more CPU than H264, but not by a lot. Maybe there's a 5 to 15% difference? You may wish to consider using H264 if CPU load is an issue as a result.
VP8 is highly compatible these days between devices and browsers.
VP9 offers better compression than VP8, but it is also more CPU-intensive to use. It might use 25 to 30% more CPU than H264, but can offer potentially a cleaner image than VP8 or H264, especially with screen-shares.
VP9 seems to reduce the chance of "rainbow puke" video problems in OBS Studio vs VP8.
Do not feel compelled to stream at HD resolutions; even 540p can look good and runs much cooler.
VP9 is often not hardware encoded, so it may solve video distortion issues that persist with H264 or even VP8.
AV1 is the most advanced codec, but also the most CPU-intensive to use.
Requires Chrome v90 or newer on both publisher and viewer to work. The Electron Capture app 2.6.0 and newer supports AV1, as well. OBS Studio v27.2 and newer *may* also support it, but as of the time of this writing, that hasn't been confirmed.
Experimental at this point in time and may not perform well, but if very bandwidth constrained, it is a worthwhile option.
{% content-ref url="webp.md" %} webp.md {% endcontent-ref %}
The parameter &codec=hardware
is Android-specific and is the same as doing &codec=h264
&h264profile
, but perhaps easier to remember. Worth trying if your android phone is struggling to publish video at a high enough quality into OBS. I may expand on this feature to be smarter.
Comma seperated - update in v23
&codec
can now accept comma separated values that define the order of preferred video codecs if the primary one fails. You might want this it you want AV1 to be the main codec, falling back to H264 rather than VP8 if not supported. ie: &codec=av1,h264
{% content-ref url="../../newly-added-parameters/and-h264profile.md" %} and-h264profile.md {% endcontent-ref %}
{% content-ref url="webp.md" %} webp.md {% endcontent-ref %}
{% content-ref url="../recording-parameters/and-recordcodec.md" %} and-recordcodec.md {% endcontent-ref %}
description: >- Has the videos fully "cover" their assigned areas, even if it means cropping the video
Viewer-Side Option! (&view
, &scene
, &room
)
Can be used to have a video be zoomed in and cropped, so it fills its window area completely. Useful if you don't want any gaps between videos.
On the left you see two video feeds in a scene without using &cover
and on the right with using &cover
:
{% content-ref url="and-portrait.md" %} and-portrait.md {% endcontent-ref %}
{% content-ref url="../../newly-added-parameters/and-square.md" %} and-square.md {% endcontent-ref %}
{% content-ref url="../design-parameters/rounded.md" %} rounded.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&dpr
Example: &dpi=2
Value | Description |
---|---|
1 |
Set Device Pixel Ratio to 1 |
2 |
Set Device Pixel Ratio to 2 |
3 |
Set Device Pixel Ratio to 3 |
(integer value X) | Set Device Pixel Ratio to X |
This allows a user to override the automatically selected Device Pixel Ratio value. It is often either 1 or 2 by default, depending on your display's DPI setting.
An accurate DPI value is important for calculating the correct requested resolution of a video. For high density displays, you'll want to have a higher resolution of video, especially in the case of the Electron Capture app, where the reported resolution isn't the same as the displayed resolution.
Changing this value can provide for higher quality or lower quality video on playback, a bit like changing the &scale
value, but dynamic to the current window-size of the video being played back.
{% content-ref url="../video-parameters/and-sharper.md" %} and-sharper.md {% endcontent-ref %}
{% content-ref url="../screen-share-parameters/and-sharperscreen.md" %} and-sharperscreen.md {% endcontent-ref %}
{% content-ref url="scale.md" %} scale.md {% endcontent-ref %}
description: >- Tells the remote source that you would like them to prioritize the audio stream over other streams
Viewer-Side Option! (&view
, &scene
, &room
)
Tells the remote source that you would like them to prioritize the audio stream over other streams.
- May not be compatible with all remote sources; depends on the browser they have
- Prioritizing audio may cause problems elsewhere, such as for other viewers or for video streams
- Prioritization applies to both encoding and networking sending of audio packets
- May override custom ptime values
- This option may be useful in reducing audio 'clicking', but likely will be just as effective as a placebo
For advanced users, this sets the following of the audio's stream: networkPriority = "high";
priority = "high";
adaptivePtime = true;
For more details, please see:
https://www.w3.org/TR/webrtc-priority/#dom-rtcrtpencodingparameters-networkpriority
Viewer-Side Option! (&view
, &scene
, &room
)
Example: &fadein=400
Value | Description |
---|---|
(no value given) | fades in video in 500-ms |
(value in ms) | value in ms for the fade in animation |
Has videos fade in smoothly in 500-ms. You can pass a custom fade in time in milliseconds.
Also available as a director's room toggle for scenes.
{% content-ref url="animated.md" %} animated.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&labelsize
&sizelabel
Example: &fontsize=70
Value | Description |
---|---|
(integer value) | font size value as a percentage |
Lets you set font-size of the guest labels or closed captions.
{% content-ref url="../settings-parameters/and-closedcaptions.md" %} and-closedcaptions.md {% endcontent-ref %}
{% content-ref url="../design-parameters/showlabels.md" %} showlabels.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&keyframeinterval
&keyframe
&kfi
Example: &keyframerate=2000
Value | Description |
---|---|
(integer value) | interval in ms |
&keyframerate
tells the remote publishers to send keyframes at a specified rate.
Could be useful if packet loss is causing a lot frame corruption.
If you make it less than 1000-ms, you will face a pretty steep drop in video quality.
Viewer-Side Option! (&view
, &scene
, &room
)
This is an advanced feature, for primarily developers, who wish to utilize their own auto-mixing code or perhaps are not using VDO.Ninja for video/audio specifically.
session.rpcs
is an object that can be queried for a list of active receiving peer sessions. session.rpcs[UUID].videoElement.srcObject
contains video/audio data if available.
{% content-ref url="../../guides/iframe-api-documentation.md" %} iframe-api-documentation.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
Example: &minptime=20
Value | Description |
---|---|
(integer value) | minimum audio packet size |
{% hint style="danger" %} If you do not know what this is, you definitely don't want to touch it. {% endhint %}
Minimum packet size of audio in ms. 10-ms is lowest that you can set in Chromium I think.
Optimized already, but it's available for experimentation and fun if desired.
{% content-ref url="and-ptime.md" %} and-ptime.md {% endcontent-ref %}
{% content-ref url="and-maxptime.md" %} and-maxptime.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
If using &proaudio
, this will retain the publishing benefits of &proaudio
, while keeping the audio as mono instead of stereo.
Audio bitrates may be reduced from 256-kbps to 128-kbps, if not explicitly stated, in some cases.
{% hint style="warning" %}
In Version 22 &mono
also works with Firefox.
{% endhint %}
To set the source to mono, see &monomic
.
{% content-ref url="../audio-parameters/and-monomic.md" %} and-monomic.md {% endcontent-ref %}
{% content-ref url="../../general-settings/stereo.md" %} stereo.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&na
&hideaudio
Delivers video only streams; audio playback is disabled for all incoming streams. &noaudio
also hides the speaker button.
You can pass a comma separated list of stream IDs that will be excluded, so that they specifically will play audio. ?noaudio=guest1a,guest2a
will only allow audio from guest1a and guest2a to play
External Iframes may or may not be muted by default if using &noaudio. While I try to mute frames when possible, like embedded Youtube videos, there may be still some Iframe sources I cannot mute.
&exludeaudio
can also be used to specify certain stream IDs that will NOT play audio, so the inverse of &noaudio
If you want to be able to unmute the speaker button during production, use &mutespeaker
instead of &noaudio
.
&deafen
also disables monitoring your own audio, then it's impossible to get any sound from VDO.Ninja.
{% content-ref url="../audio-parameters/and-nodirectoraudio.md" %} and-nodirectoraudio.md {% endcontent-ref %}
{% content-ref url="../../source-settings/and-mutespeaker.md" %} and-mutespeaker.md {% endcontent-ref %}
{% content-ref url="../../general-settings/deafen.md" %} deafen.md {% endcontent-ref %}
{% content-ref url="../video-parameters/and-novideo.md" %} and-novideo.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
&random
Viewer-Side Option! (&view
, &scene
, &room
)
Example: &scale=100
Value | Description |
---|---|
(integer value between 0 and 100) | scale the incoming video feed by this percentage |
100 |
doesn't allow the incoming video feed to scale down the resolution |
Example: If the video inbound has a resolution of 1920x1080, &scale=50
would limit the resolution to 960x540 instead.
The nice thing about this is that it doesn't matter which resolution their camera supports; the scale is software based and doesn't care about resolutions or aspect ratios.
This can help a viewer reduce frame stuttering, CPU load, and improve frame rates, without having to have the guest rejoin the stream.
Requires the publisher of the stream to support dynamic scaling; Firefox and Chrome should be supported.
There is a toggle in the director's room to add &scale=100
to the scene URL:
{% content-ref url="../video-parameters/and-sharper.md" %} and-sharper.md {% endcontent-ref %}
{% content-ref url="../screen-share-parameters/and-sharperscreen.md" %} and-sharperscreen.md {% endcontent-ref %}
{% content-ref url="dpi.md" %} dpi.md {% endcontent-ref %}
Viewer-Side Option! (&room
)
&scn
Example: &scene=2
or &scene=choosethename
Value | Description |
---|---|
0 | (no value given) |
auto-add all videos to the scene; they can't be removed |
1 |
empty by default; manually add videos in |
(string) | like &scene=1 , but videos are not preloaded |
{% hint style="info" %}
Must be used in conjunction with the &room
parameter.
{% endhint %}
By adding &scene
to a room URL, it tells VDO.Ninja that this is no &push
connection.
&scene=0
by default has all videos in the room automatically added to the scene. They cannot be removed.
-
&scene=1
by default has no videos added to the scene. Videos need to be added manually by the director. Videos not yet added to the scene are connected, and streaming at around 400-kbps, so when they become active they appear immediately. Bitrate will ramp up after a second to the target bitrate of, normally, 2500-kbps or whatever is set via the URL.
-
&scene=2
is like&scene=1
, except the video streams that are not yet added to the scene are disabled with 0-bitrate used. They are connected, but not actively streaming any video data, so it takes a moment longer for videos to appear once added. -
&scene=N
, whereN
is a string or integer - it's just like&scene=2
. There are buttons marked S3, S4, .. S8 in the director's room to control these scene types. If they are not already there, new buttons for them will be created automatically when used. See the video below.\ -
When using a scene, if you manually specify a video via the
&view
parameter, it automatically is added to the scene. -
Audio of videos in scenes can be controlled by the director: volume and mute are options.
-
In v17.2 of VDO.Ninja, if using
&view
in a scene link, the director won't be able to remotely control the scene. This applies to solo links. -
In v18, you can create custom scenes, as per the video below.
{% embed url="https://www.youtube.com/embed/axgIqPcHExQ" %}
{% content-ref url="../../general-settings/room.md" %} room.md {% endcontent-ref %}
{% content-ref url="../mixer-scene-parameters/and-solo.md" %} and-solo.md {% endcontent-ref %}
description: >- Tells VDO.Ninja to not block VDO.Ninja from attempting to run when using Streamlabs for MacOS
Viewer-Side Option! (&view
, &scene
, &room
)
Tells VDO.Ninja to not block VDO.Ninja from attempting to run when using Streamlabs for MacOS.
For normal OBS users, update to OBS 26.1.2 on MacOS to obtain native support for VDO.Ninja in OBS.
Streamlabs doesn't yet have full support for VDO.Ninja; consider the Electron Capture app if it fails to work well.
Viewer-Side Option! (&view
, &scene
, &room
)
Example: &sync=50
Value | Description |
---|---|
(integer value) | value in ms |
&sync=X
will set an offset in milliseconds for the audio stream.
&buffer=0
or &sync=0
will do the same thing: it will try to auto-sync video and audio.
Tiny negative offsets may work, like &sync=-25
is possible, but large negative offsets will not work.
No clue if it is supported in OBS or not; works in Chromium/Chrome v76 or newer tho. Useful if the video device has a large delay that needs compensating for that isn't fixed automatically.
&sync=500
without the &buffer
command also will only add an audio delay; there will be no additional video buffer or delay.
{% hint style="info" %} Using may stop Echo Cancellation from working. {% endhint %}
{% content-ref url="buffer.md" %} buffer.md {% endcontent-ref %}
{% content-ref url="../video-parameters/and-buffer2.md" %} and-buffer2.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
Sets the audio bitrate to be variable, instead of constant, but only when an audio bitrate is manually specified.
By default, Chrome uses a variable bitrate with a cap at around 32-kbps with mono-audio.
When manually specifying a bitrate, Chrome keeps the audio bitrate pretty constant, even if VBR is turned on.
{% content-ref url="audiobitrate.md" %} audiobitrate.md {% endcontent-ref %}
Viewer-Side Option! (&scene
, &room
)
&streamid
&pull
&v
Example: &view=StreamID1,StreamID2
Value | Description |
---|---|
(string value) | stream ID to view; can be a comma-separated list of IDs |
(no value given) | in a room, you don't see any other guests including the director |
&view
defines the stream or streams you are receiving, by their stream IDs.
https://vdo.ninja/?push=streamid
https://vdo.ninja/?view=streamid
Optional if you are publishing a stream using &push
.
If the &view
parameter is not added, the default behaviour will occur.
If the &view
parameter is provided, it will try to play any stream listed.
If the &view
parameter is provided, but no values are provided, no streams will play; only publishing will be allowed.
This is useful is you wish to publish a video into a group chat room, but only view video from specific known participants.
This is also useful if you wish to create ad-hoc group chat sessions without using a group room.
Videos will auto-load when they are available if not already.
You can use &view
in a room combined with &scene
or &solo
to watch one or more specified video feeds of the room:
https://vdo.ninja/?room=roomname&scene&view=streamid1,streamid2
{% content-ref url="../../getting-started/multi-person-chat.md" %} multi-person-chat.md {% endcontent-ref %}
{% content-ref url="../../source-settings/push.md" %} push.md {% endcontent-ref %}
{% content-ref url="scene.md" %} scene.md {% endcontent-ref %}
{% content-ref url="../mixer-scene-parameters/and-include.md" %} and-include.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
{% hint style="info" %}
V22: Sender-Side Option! (&push
)
{% endhint %}
&images
Example: &webp=jpeg
Value | Description |
---|---|
(no value given) | webp image format |
jpeg |
jpeg image format |
The &webp
mode has been modified a bit. Main change is that you now enable it by add &webp
to the sender's URL, and &codec=webp
to the viewer's URL (otherwise, it falls back to normal video mode). No need for &broadcast
anymore. (as a reminder, this mode sends the video as a series of low-quality images, rather than a more efficient video stream).
I've removed the toggle in the director's room for this &webp
feature, as &chunked
mode is replacing its purpose there, but you might still want to use this mode when the viewer-side does not support video playback or hardware acceleration. Specifically, this option lets you bring motion images (aka, crude video) into the streamlabs mobile app, as a browser source, where other forms of video decoding is not supported.
In Version 21 and backwards it must be used with &broadcast
on the viewer side but the director doesn't need to be the designated broadcaster.
The Electron Capture app should work to allow for webp-based broadcasting even if the tab is not visible, as tab throttling is disabled with that application.
This is essentially a stream of webp-based images sent over the webRTC data-channels.
The quality by default is limited in both frame rate and resolution, as this custom video codec is very inefficient at higher resolutions and frame-rates.
Based on my testing, the webp mode is only efficient if you are keeping the bitrates under like 2 mbps, so the higher qualities make little sense IMO outside of some niche use cases as they use up a lot of bandwidth.
If you have issues with Webp-mode, or find the quality or CPU savings not sufficient, you can check out the &meshcast
integration instead. It's a relatively new supported addition to VDO.Ninja.
Default quality is 270p @ 10-fps webp. You can change this with &webpquality
to increase resolution and max frame rate.
The default frame rate is a target, but if the connection cannot keep up, a lower frame rate will be used. This ensures the lowest latency possible.
Compression quality is set to 66% in all cases. This seems the best bang for buck.
This mode can work with audio, which uses the normal audio mode for transport. Audio and these motion images stay roughly in sync.
{% content-ref url="../../guides/iframe-api-documentation.md" %} iframe-api-documentation.md {% endcontent-ref %}
{% embed url="https://www.youtube.com/watch?v=-7QsLChfdsE" %}
{% content-ref url="webpquality.md" %} webpquality.md {% endcontent-ref %}
{% content-ref url="codec.md" %} codec.md {% endcontent-ref %}
{% content-ref url="../../newly-added-parameters/and-chunked.md" %} and-chunked.md {% endcontent-ref %}
Viewer-Side Option! (&view
, &scene
, &room
)
{% hint style="info" %}
V22: Sender-Side Option! (&push
)
{% endhint %}
&webpq
&wq
Example: &webpquality=1
Value | Description |
---|---|
0 |
1080p |
1 |
720p |
2 |
540p |
3 |
360p |
4 |
270p |
5 |
270p @ 15-fps |
6 |
270p @ 5-fps |
7 |
270p @ 2.5-fps |
8 |
360p @ 1-fps |
You add this parameter to the director (or designated broadcaster) and it then sets the quality target for the &webp
mode.
Default is 270p @ 10-fps.
Compression quality is set to 66% in all cases. This seems the best bang for buck. Unless specified, this is also webp.
{% content-ref url="webp.md" %} webp.md {% endcontent-ref %}
description: >- Accepts the special token without needing to specify the cloudflare.vdo.ninja part if using &whipout instead
WHIP Option / Sender-Side Option! (&push
)
&cft
Example: &cftoken=token
Value | Description |
---|---|
(string value) | Accepts the special token without needing to specify the cloudflare.vdo.ninja part if using &whipout instead |
If using a cloudflare.com WHIP URL on the sender side, I'll guess at the WHEP link - seems to be working so far. (built this logic into VDO.Ninja directly and works automatically). This of course still implies a unique whip URL per guest.
To make using Cloudflare easier though, I've also created the WHIP end point cloudflare.vdo.ninja
, which takes a Cloudflare API token, instead of a stream token.
This special end point will auto-create a unique WHEP URL. The official cloudflare.com whip endpoint can only be used by one sender at a time, but this API special endpoint and token approach can be used by many senders at a time. It automatically generates unique WHIP/WHEP when used, in the same way Meshcast does, so no need for unique invite urls per guest.
I've created a page to generate the required special api token; the page also provides further information on this all: https://vdo.ninja/alpha/cloudflare
&cftoken
accepts the special token without needing to specify the cloudflare.vdo.ninja part if using &whipout
instead.
I focused mainly on adding Cloudflare support first, as it has good pricing for its WHIP/WHEP service, it doesn't require deploying anything, and it has a lot of features (RTMP, SRT, recording, API). It's not 100% cooked yet though, so it's just on alpha currently for testing.
{% content-ref url="../../steves-helper-apps/whip-and-whep-tooling.md" %} whip-and-whep-tooling.md {% endcontent-ref %}
{% content-ref url="and-whipout.md" %} and-whipout.md {% endcontent-ref %}
WHIP Option / Sender-Side Option! (&push
)
&scalabilitymode
Example: &svc=L1T3
Value | Description |
---|---|
(SVC value) | Takes an SVC value, with L1T3 being the most universal option, but other options exist |
&svc
is useful for publishing to WHIP broadcast servers that support scalable video modes. Takes an SVC value, with L1T3
being the most universal option, but other options exist. You'll get an error when publishing if you use an invalid one.
There are SVC scalable options to the WHIP output option on https://vdo.ninja/whip, making it easy to select a compatible SVC mode if desired.
Experiment with this feature here:
https://webrtc.github.io/samples/src/content/extensions/svc/
{% content-ref url="../../steves-helper-apps/whip-and-whep-tooling.md" %} whip-and-whep-tooling.md {% endcontent-ref %}
{% embed url="https://vdo.ninja/whip" %}
Viewer-Side Option! (&scene
, &room
, &director
)
&whip
Example: &whipview=bearertoken
Value | Description |
---|---|
(string value) | bearer token from OBS |
Added experimental "WHIP" support to VDO.Ninja, which means in the near future you'll be able to publish directly from OBS to VDO.Ninja without a virtual camera. There's some big caveats to it all, so I don't recommend it over the normal method to most users, but we'll see how it evolves.
To publish use: https://whip.vdo.ninja/bearertoken
To view use: https://vdo.ninja/?whip=bearertoken
You can also go to https://vdo.ninja/alpha/whip for a page to help auto-generate basic VDO.Ninja WHIP links for you.
You have to use a version of OBS that contains WHIP support to get OBS to WHIP working. As of April 2023, these are some builds of OBS that support WHIP:
https://github.com/obsproject/obs-studio/suites/12263428876/artifacts/649328007 win (x64)
https://github.com/obsproject/obs-studio/suites/12263428876/artifacts/649328001 mac (arm)
https://github.com/obsproject/obs-studio/actions/runs/4711358202?pr=7926 (others here)
Hopefully WHIP support will be in OBS officially sometime soon. WHIP support is already added to many other applications and services, and VDO.Ninja will do its best to ensure compatibility as the situation evolves.
See this video for details how to set up OBS WHIP to VDO.Ninja:
{% embed url="https://youtu.be/ynSOE2d4Z9Y" %} Publishing from OBS directly to VDO.Ninja {% endembed %}
I've refined the WHIP service on vdo.ninja/alpha/?whipview=xxx
, making it as robust as I can I think, so if some third-party WHIP client/app doesn't work with it, it may not an issue with VDO.Ninja. In those cases it will be up to the client to ensure full support of the WHIP specification, else it may not work with VDO.Ninja.
{% content-ref url="../../guides/publish-from-obs-into-vdo.ninja.md" %} publish-from-obs-into-vdo.ninja.md {% endcontent-ref %}
Sender-Side Option! (&push
, &room
)
&whippush
&pushwhip
Example: &whipout=bearertoken
Value | Description |
---|---|
(string value) | bearer token from OBS |
Added experimental "WHIP" support to VDO.Ninja, which means in the near future you'll be able to publish directly from OBS to VDO.Ninja without a virtual camera. There's some big caveats to it all, so I don't recommend it over the normal method to most users, but we'll see how it evolves.
To publish use: https://whip.vdo.ninja/bearertoken
To view use: https://vdo.ninja/?whip=bearertoken
You can also go to https://vdo.ninja/alpha/whip for a page to help auto-generate basic VDO.Ninja WHIP links for you.
You have to use a version of OBS that contains WHIP support to get OBS to WHIP working. As of April 2023, these are some builds of OBS that support WHIP:
https://github.com/obsproject/obs-studio/suites/12263428876/artifacts/649328007 win (x64)
https://github.com/obsproject/obs-studio/suites/12263428876/artifacts/649328001 mac (arm)
https://github.com/obsproject/obs-studio/actions/runs/4711358202?pr=7926 (others here)
Hopefully WHIP support will be in OBS officially sometime soon. WHIP support is already added to many other applications and services, and VDO.Ninja will do its best to ensure compatibility as the situation evolves.
See this video for details how to set up OBS WHIP to VDO.Ninja:
{% embed url="https://youtu.be/ynSOE2d4Z9Y" %} Publishing from OBS directly to VDO.Ninja {% endembed %}
A goal for a while has been to allow anyone to drop-in their own Meshcast replacement, using a third-party WHIP/WHEP server/service. That is, publish to a whip-service, and have viewers of the stream get the WHEP-view link, so they can view via WHEP instead of p2p. I've achieved this finally; close enough at least.
There's a few requirements to make it work though, so either an API wrapper is needed or a set of rules needs to be followed:
-- If your WHIP server returns an exposed "WHEP" field in the POST response header, with the URL to the WHEP view link, it will use that WHEP link. You just need to then specify the &whipout
URL on the sender side then.
-- This should let you make your own Meshcast service with minimal work; the open-source WHIP API code I released the other day further makes it pretty easy.
I've refined the WHIP service on vdo.ninja/alpha/?whipview=xxx
, making it as robust as I can I think, so if some third-party WHIP client/app doesn't work with it, it may not an issue with VDO.Ninja. In those cases it will be up to the client to ensure full support of the WHIP specification, else it may not work with VDO.Ninja.
{% content-ref url="../../steves-helper-apps/whip-and-whep-tooling.md" %} whip-and-whep-tooling.md {% endcontent-ref %}
{% content-ref url="and-whip.md" %} and-whip.md {% endcontent-ref %}
WHIP Option / Sender-Side Option! (&push
)
&woab
Example: &whipoutaudiobitrate=128
Value | Description |
---|---|
(integer value) | audio bitrate in kbps |
&whipoutaudiobitrate
lets you specify the WHIP audio bitrate (kbps).
{% content-ref url="and-whip.md" %} and-whip.md {% endcontent-ref %}
{% content-ref url="../view-parameters/audiobitrate.md" %} audiobitrate.md {% endcontent-ref %}
{% content-ref url="and-whipoutvideobitrate.md" %} and-whipoutvideobitrate.md {% endcontent-ref %}
WHIP Option / Sender-Side Option! (&push
)
&woc
Example: &whipoutcodec=av1
Value | Description |
---|---|
av1 |
av1 codec |
h264 |
h264 codec |
vp8 |
vp8 |
Added &whipoutcodec=
lets you specify the WHIP video output codec. It can take multiple values; if not used, the default at the moment is open264.
{% content-ref url="and-whip.md" %} and-whip.md {% endcontent-ref %}
{% content-ref url="../view-parameters/codec.md" %} codec.md {% endcontent-ref %}
{% content-ref url="../../guides/publish-from-obs-into-vdo.ninja.md" %} publish-from-obs-into-vdo.ninja.md {% endcontent-ref %}
WHIP Option / Sender-Side Option! (&push
)
&woscale
Example: &whipoutscale=50
Value | Description |
---|---|
(percentage 1 to 100) | will scale down the video to the percentage given |
The &whipoutscale
parameter will scale down the WHIP video output via the URL, post camera capture setup. You may wish to use this to lower the resolution if your camera has a fixed capture resolution.
{% hint style="info" %} Alternatively, if you need to dynamically adjust the resolution, that option already exists via camera settings via width/height slider adjustments. {% endhint %}
{% content-ref url="../../steves-helper-apps/whip-and-whep-tooling.md" %} whip-and-whep-tooling.md {% endcontent-ref %}
{% content-ref url="and-whip.md" %} and-whip.md {% endcontent-ref %}
WHIP Option / Sender-Side Option! (&push
)
&wossbitrate
Example: &whipoutscreensharebitrate=2000
Value | Description |
---|---|
(integer value) | publishing screen share WHIP video bitrate in kbps |
&whipoutscreensharebitrate
controls the outbound screen-share video bitrate of the &whip
parameter while screen-sharing via WHIP. It will override the &whipoutvideobitrate
if the video is a screen-share.
{% content-ref url="../../steves-helper-apps/whip-and-whep-tooling.md" %} whip-and-whep-tooling.md {% endcontent-ref %}
{% content-ref url="and-whip.md" %} and-whip.md {% endcontent-ref %}
WHIP Option / Sender-Side Option! (&push
)
&wosscodec
Example: &whipoutscreensharecodec=h264
Value | Description |
---|---|
h264 | h264 codec |
vp8 | vp8 codec |
vp9 | vp9 codec |
42e01f | open h264 codec |
(xxxxxx) | h264 profile IDs |
Adding &whipoutscreensharecodec
to the publisher's side gives the option to change the publishing codec while screen-sharing via WHIP.
There's 4 codec options currently, including the default option:
- The unspecified default, which is software h264.
- There's also
h264
, which is what the browser then sets. This could include hardware encoding, but that will not work with Firefox or Safari viewers then. vp8
is pretty compatible, so if the default codec doesn't work, you can try that.vp9
is also available, which has better compression/quality, but not fully compatible with all devices.- av1 and SVC are not yet supported, but that is planned at some point.
{% content-ref url="../../steves-helper-apps/whip-and-whep-tooling.md" %} whip-and-whep-tooling.md {% endcontent-ref %}
{% content-ref url="and-whip.md" %} and-whip.md {% endcontent-ref %}
{% content-ref url="and-whipoutcodec.md" %} and-whipoutcodec.md {% endcontent-ref %}
WHIP Option / Sender-Side Option! (&push
)
&wovb
Example: &whipoutvideobitrate=6000
Value | Description |
---|---|
(integer value) | video bitrate in kbps |
&whipoutaudiobitrate
lets you specify the WHIP video bitrate (kbps).
{% content-ref url="and-whip.md" %} and-whip.md {% endcontent-ref %}
{% content-ref url="../video-bitrate-parameters/bitrate.md" %} bitrate.md {% endcontent-ref %}
{% content-ref url="and-whipoutaudiobitrate.md" %} and-whipoutaudiobitrate.md {% endcontent-ref %}
WHIP Parameters are specific to the WHIP and WHEP tooling.
Parameter | Explanation |
---|---|
&whipout | Publish directly from OBS (or other) to VDO.Ninja without a virtual camera |
&whipview | Publish directly from OBS (or other) to VDO.Ninja without a virtual camera |
&whipoutcodec | Lets you specify the WHIP video output codec |
&whipoutaudiobitrate | Lets you specify the WHIP audio bitrate (kbps) |
&whipoutvideobitrate | Lets you specify the WHIP video bitrate (kbps) |
&whipoutscale * | Scales down the WHIP video output via the URL |
&whipoutscreensharecodec * | Option to change codec of the WHIP while screen-sharing |
&whipoutscreensharebitrate * | Option to change outbound screen-share video bitrate of WHIP |
&cftoken * | Accepts the special token without needing to specify the cloudflare.vdo.ninja part if using &whipout instead |
&svc * | Useful for publishing to WHIP broadcast servers that support scalable video modes |
*NEW IN VERSION 24
Understanding stream IDs will help potentially avoid these errors in the future, but the basic notion is any media stream being published over VDO.Ninja needs to register itself with a stream ID. This is specified by using the &push
URL parameter, such as &push=STREAMID
.
The moment you connect to the system or start streaming, your stream ID gets registered to your connection, and so as long as you remain connected and online, you keep that stream ID. If you close the browser, hang up, or lose your Internet connection, then your stream ID unregisters automatically as well.
If a stream ID you are trying to claim is already in use by another stream, and that other connection is still actively online, then you'll get an error about it being already in use. In this case, you will need to wait for that other user to hang up or disconnect before you can attempt to register the stream ID yourself.
There are some subtleties to the above, such as if using passwords or self-hosted instances of VDO.Ninja, then stream IDs are isolated to their own unique realm, allowing you to use the same stream ID as someone else from a different realm. So if a stream ID is already in use, you can just change or add a password, and that will resolve the issue.
Of course, when you want to invite several people to a group room, you can't have different passwords, so you will want each guest to have their own unique stream ID still. By default with VDO.Ninja, if you do not use &push
in the URL to specify a stream ID, then VDO.Ninja will auto generate a random stream ID for the guest. The system will also auto add the &push=STREAMID
parameter to the guest's URL, so if the guest refreshes their page, they will keep the same stream ID.
The above is where there are sometimes issues, as if you join a room without a &push
value specified, and then after connecting connecting you copy/share your URL with someone else, your URL might now contain your stream ID. When you then share it with someone else, they won't be able to connect as you are already using the stream ID that is specified.
In the above case, when distributing invite URLs to guests, either ensure each guest has a unique stream ID assigned to them, or ensure that there is no &push
parameter added to the URL, allowing the system to generate a random stream ID for each guest.
Manually creating a stream ID for each guest is recommended if you want each guest to appear in the same solo-view-link every time they re-join, as otherwise they may have a random new stream ID everytime they join. Many show producers will use a spreadsheet to keep track of who has what stream ID, their settings, and the corresponding invite link. Some of these spreadsheets are pretty sophisticated, with the ability to generate obfuscated invite links based on a few parameters.
If manually creating stream IDs, please just note that they need to be alphanumeric, with no special characters, are should be ideally less than roughly 30-characters long. If using a password, the uniqueness of the stream ID doesn't matter so much, but if not using a password, please ensure you create unique values that can't be easily guessed or accidentally duplicated by someone else.
Additional tools and options are available to create and assign stream IDs, such as &permaid
, and other methods to store stream IDs via local user storage, but those options are out of the scope of this article.
This error indicates that there is already someone in a group room that has joined the room in the role of a director. The first director to join a room claims the room as theirs, and it remains theirs until they go offline or close their browser, as the room is assigned to their active connection. Another director will then be able to claim the room then, once the main director disconnects.
Claiming a room doesn't inherently mean much, other than anyone who joins the room will only acknowledge them as the main director. Acknowledging someone as a director will simply mean that director has certain privileges when requesting actions of a guest or scene. A validated director can ask a guest to hang up, for example, while otherwise such a request will be rejected.
Since VDO.Ninja is built on the concept of peer to peer connections, claiming a room is the same concept as claiming a stream ID, and those claims are tied to your active connections. Everything beyond that is really a matter of peers agreeing to a certain set of rules amongst themselves. If someone does claim a room and forgets to close their browser, you'll need to close that browser, change rooms, or change room passwords if you wish to have someone else become the main director.
In this case, it sounds like the remote guest is failing to create a WebRTC peer connection with the director.
The handshake works, so each other knows someone is trying to join, but they are unable to find themselves. The system will time out and try again, when this occurs, causing the guest's box to continually partially appear, and then go away again.
This is sometimes caused by blocked UDP traffic, where the TURN relay servers are unable to help for some reason. Security software, privacy-focused VPNs, corporate firewalls, and certain browser extensions are common causes.
Sometimes other guests in the room will see the problematic guest, and in this case, there could just be a network routing issue. Peer to peer connections across the Internet are not common, with most clients these days talking to servers instead, so residential to residential connections may occasionally fail due to bad Internet routes or caches.
Things that often work:
- Switch browsers, with Firefox being a common winner when Chrome fails. Perhaps also try Edge or even the Electron Capture app.
- Use a VPN designed for streaming, such as speedify.com. Free VPNs exist as Chrome extensions, if you need something quick.
- Switch networks; if using WiFi, switch to Cellular, and vice-versa.
- If behind a corporate firewall, have the IT administrators allow WebRTC traffic, or use a different.
- Meshcast.io is a server-based WebRTC system, and it may work in place of VDO.Ninja for simple needs.
- If nothing above works, join the Discord support community for personalized help at discord.vdo.ninja.
description: >- ATEM devices don't support HDCP, which some HDMI input devices require. Disabling HDCP with some HDMI splitters can resolve the issue.
One user reports that their ATEM extreme wasn't working with an Amazon Firestick via HDMI.
Due to HDCP, it turns out you need to use an HDMI splitter that bypasses HDCP for it to work, else you'll just get a black screen. The ATEM does not support HDCP, so you need a way to disable it, and some splitters can offer that.
{% embed url="https://www.youtube.com/watch?v=vweEwAvusfE" %} Taking a look at the Firestick HD Max and VDO.Ninja {% endembed %}
In a YouTube video, it was demonstrated that a Firestick, such as the 4K Max, can play VDO.Ninja videos at full-screen with a clean output. AV1 is even supported to some degree with the 4K Max, which offers excellent color reproduction versus VP8 or H264.
Given the price of a Firestick versus something like an SBC (ie: Orange Pi 5), it's an appealing option to use as a source for an ATEM device, like an ATEM mini. ATEMs don't have browser source support on their own, making a hack like this necessary.
Needing to disable HDCP may also apply to other HDMI input devices when paired with a Firestick, Chromecast, or other media dongle.
If using this setup with an overlay, like Social Stream, you may want to use &chroma
on the featured chat overlays to enable the green background. From there, you should be able to chroma-filter out the green in the ATEM device, providing transparency.
It's also possible to use OBS to output a source to an ATEM device, via HDMI output on your computer. You'll still need to use a green screen if wanting transparencies of course.
Lastly, you can use IFrames and the VDO.Ninja mixer app to create custom scenes and layouts with transparencies in a browser source, if you wanted to do the mixing that way, avoiding the need for Chroma keying. Just please note that a Firestick or other low-powered dongle don't seem to handle multiple videos and complex effects all that well, or even full HD video for that matter. You may want to get a NUC device or powerful SBC to do more complex mixes that feed out into an ATEM of such.
Bluetooth microphones can cause clicking/popping.
VDO.Ninja uses 48kHz audio (48000hz), so any software you are using with VDO.Ninja should ideally also use 48-KHz. If using a different sample rate, the browser or app will try to convert it as needed, but this doesn't always go smoothly. Very high sample rates are especially troublesome on some systems, so having your system be end-to-end setup in 48khz audio is suggested and reduce any additional audio processing overhead.
If using any virtual audio cables or pro audio gear, try to increase the audio buffer packet sizes, as buffer-under issues can cause audio distortion. Too small an audio buffer on some mic preamps or virtual audio cables can lead to clicking or distortion.
Having the playback audio device and the microphone capture device set to 48000hz, and no more than 24-bit, is recommended. You can adjust these settings in the Windows audio settings. Devices like a FiiO DAC can sometimes have the audio sample rate be very high, and that can cause buffer underruns and clicking problems.
Restarting OBS or addressing heavy CPU load may also help prevent buffer underruns, which sometimes appear in the OBS logs as a max buffer reached error. Make sure the computer isn't running near 100% load to ensure it's not just overloaded.
As well, starting OBS Studio in admin mode can also fix issues with audio as well, although I'm not entirely sure why this works sometimes.
Some surround sound headphones, like those by Logitech, can also cause audio problems; robotic noises, distortion, etc. Disabling surround sound mode often fixes such issues.
If using a MacOS system, ensure your computer is plugged into the power outlet and not on battery power. Systems running on batteries can sometimes have issues.
Consider reducing the resolution and bitrate of videos, as this can help free up CPU load. An overloaded system could perhaps stress the audio encoder/decoder pipeline out.
Do not use Wi-Fi if streaming high-quality music; packet loss can cause clipping. Use wired Ethernet on both ends of the connection instead.
For either the sender or viewer of a stream, make sure you are not using up more than ~80% of your total upload bandwidth. Using 100% of your bandwidth will cause packets to stall and possibly be skipped, leading to missed frames and audio clicking.
If dealing with audio distortion or robotic voices, sample rates of the system
You can also try adding some URL parameters to the viewer and sender linkes to see if it helps. A few parameters to try that might help are the following:
&noaudioprocessing
&samplerate=48000
&micsamplerate=48000
Might be caused by a Browser-source related bug in OBS.
Fully restart OBS and see if that clears the issue.
You can try to bring in audio via https://vdo.ninja/electron instead. &novideo
can be used to ingest just the audio. Route the audio to a virtual audio device and then bring that into OBS as an audio device. Should be in sync this way.
VDO.Ninja uses 48000khz sample rate for audio; using this sample rate whenever possible can help keep things in sync.
Try to avoid overloading your CPU or using too many browser source elements in OBS; OBS Browser Source can get overwhelmed.
If using OBS for audio playback, be sure that you select "Control Audio via OBS" in the browser source to capture the audio. You won't be able to hear the audio by default this way, but OBS should show the audio level meters moving, signifying the audio is being captured.
Restarting the computer or OBS can sometimes resolve issues where OBS stops capturing audio via browser sources or sometimes other audio soures.
Some users report that the audio may sound distorted or out of sync as well, but often there may be no audio at all.
Starting OBS in adminstirator mode, if using Windows, may help. Reducing the CPU load on your computer may also also help.
If however you are testing VDO.Ninja and audio isn't working at all, from browser to browser, yet you see your mic-level loudness green indicator moving in VDO.Ninja as you speak, double check your Windows audio settings. In particular, high sample rates, like 384-khz sample rates, 32-bit depth audio playback, or other professional audio device settings in Windows may cause problems with audio playback.
To avoid issues, set your audio playback devices (specifically to the audio playback device) to 24-bit or 16-bit audio, with an audio sample rate of 48,000-hz, or as close to it as possible. If you mic-source isn't working, also check to make sure your microphone is 16 or 24-bit capture mode, and isn't in ASIO mode.
Surround sound or multi-channel audio, for both the microphone and audio playback devices, can cause audio problems with the browser. Disable surround sound, limiting audio playback to stereo 2.0 channels, and try again.
If using a remote virtual desktop, such as a server-hosted version of Windows, be sure the Windows audio service is enabled; you might be able to turn this on via services.msc
, accessible via the Windows Key + R
run prompt.
Also check that the default audio device in Windows is as expected and that any select audio output device in VDO.Ninja is pointed to the right location. Bluetooth devices may sometimes be problematic, especially on mobile, so try to avoid Bluetooth if possible.
In some cases, adding &noap
to the URL for the sender or/and reciever of the audio may help, as this will disable web-audio node processing in VDO.Ninja, which may fail when using invalid sample rates of an overly stressed CPU.
Some media devices, like the Magewell Director Mini, may not support audio via VDO.Ninja, and only video. Please also ensure the video is playing, as some devices may pause a media track until there is a user-gesture, which woudl prevent audio from playing in cases.
Sometimes if there is background audio being captured, the system will remove that audio thinking it is an echo of feedback. If this background audio contains your microphone audio, your microphone audio may be removed. You can disable echo cancellation in this case, or resolve the core issue.
{% content-ref url="echo-or-feedback-issues.md" %} echo-or-feedback-issues.md {% endcontent-ref %}
If using an external audio device on mobile, like via USB, it's suggested to use a TRRS audio input adapter, with the your microphone connected to that.
https://www.youtube.com/watch?v=BBus_S8iJUE
If on Android, using Firefox might work well without the need of TRRS however.
If using the native VDO.Ninja mobile app, please note that screen sharing might only contain microphone-sourced audio -- the system audio won't be detected at the moment. This will hopefully change soon, but there is no timeline as to when it will be working.
Since 2017, Browsers have required users "interact" with a website in some way before videos will be allowed to auto-play. You can modify Chrome to allow for auto-play, but it's not super easy to do.
In OBS and the Electron Capture app, auto-play is allowed.
vMix v77 does not support auto-play, which must be an oversight on their behalf... right?? haha. A complaint has been filed regardless; voice your own request for the feature here: https://forums.vmix.com/posts/t22181-CEF-V77-browser-setting.
A full-screen-sized play button will show up to help accommodate the need for user gestures before auto playing videos.
TL;DR; you have a few options:
- use the Electron Capture app or OBS Studio to play videos; these apps have gesture-requirements disabled
- in Chrome, go to:
chrome://settings/content/sound?search=sound
and add vdo.ninja to the list of "allowed to play sound" list - add
&noaudio
to your VDO.Ninja view link, so no audio track loads -- without audio, the video should auto-play. - try adding
--autoplay-policy=no-user-gesture-required
to the Chrome/Chromium command line to have the auto-play policy changed on load (this may not work with recent versions of Chrome though) - make sure there are no Adblockers installed or other extensions install; sometimes these may interfere with auto-playing
If you are experiencing this issue and you are using MacOS, please refer to the MacOS specific section
If this happens, there could be numerous reasons.
- Check that you have hardware-acceleration turned on, within OBS, and have updated your graphic drivers.
- Ensure that you are not behind a VPN or firewall. Symmetrical firewalls may block OBS.Ninja traffic.
- If on macOS, use the Electron Capture application instead of the Browser source used by OBS (Also ensure you are running OBS v26.1.2 or newer!).
- Try using a VPN, such as Speedify, to bypass any networking firewalls that your ISP may have enabled.
- Check test.webrtc.org.
- If you are on cellular, try connecting to Wi-Fi instead.
- Ensure your are using a compatible browser (Safari on iOS or Chrome on Android).
- Older iOS devices do not work.
- Check test.webrtc.org.
Check to make sure your TURN server supports IPv6. The ones I provide should support it though. Check test.webrtc.org.
There are numerous issues with iOS devices; see the iOS help section for more info. Check test.webrtc.org.
Firewalls may be setup that block traffic of this type. Talk to your network administrator Other problems? Check test.webrtc.org and see if anything is marked as "RED". You can also try different networks and see if that helps.
In the meantime, OBS.Ninja/old is up, and will remain up until I can resolve all the issues with the new release. This may solve your issue temporarily. So if you have this problem , where you see the fullscreen video, but it is just grey and spinning, then it could be a network issue.
If your camera isn't appearing in Chrome on macOS, there are several possible reasons and solutions you can try:
Ensure that Chrome has permission to access the camera:
- Open System Preferences > Security & Privacy > Privacy.
- Select Camera from the left-hand menu.
- Ensure that Google Chrome is checked.
Make sure you're using the latest version of Chrome:
- Open Chrome and go to Settings > About Chrome.
- Chrome will automatically check for updates and install them if available.
Verify that the website has permission to use your camera:
- Open the website where you are trying to use the camera.
- Click the lock icon in the address bar.
- Ensure that Camera, and also the microphone if needed, is set to Allow.
Sometimes, a simple restart of Chrome can resolve the issue:
- Close Chrome completely.
- Open Chrome again and check if the camera works.
- Or just restart the computer to ensure Chrome has completely been restarted
Ensure no other application is using the camera:
- Close any other applications that might be using the camera (e.g., Zoom, Skype, Discord).
- A camera can only be used by one application at a time, so closing other applications may help
Resetting Chrome settings can help resolve the issue if it's due to a misconfiguration:
- Open Settings > Advanced > Reset settings.
- Click Restore settings to their original defaults and confirm.
Verify that your camera works with other applications:
- Open an application like Photo Booth or Facetime and check if the camera works.
If the above steps don't work, try reinstalling Chrome:
- Uninstall Chrome from your Mac.
- Download the latest version from Google Chrome's website and reinstall it.
Ensure your macOS is up to date:
- Open System Preferences > Software Update.
- Install any available updates.
If the camera still doesn't appear, there might be a hardware issue:
- Try connecting an external webcam if you have one.
- If the external camera works, it may indicate an issue with the built-in camera.
- Try plugging the camera into another USB port or such
- Make sure any HDMI adapter has an input that's compatible with the browser, so 8-bit, 30 or 60-fps, and not requiring special drivers to use
Disable any browser extensions that might be interfering with the camera:
- Go to chrome://extensions/ and disable extensions one by one to identify if any of them are causing the issue.
Firefox or Safari or another Chromium-based browser might work, if Chrome does not.
If your camera works with OBS, perhaps use that to load the camera and then use the OBS Virtual Camera as the camera source.
- Some cameras are only compatible with OBS, and may not work with the browser
Many virtual camera drivers on macOS are limited to 1080p30, and in fact, may only work at that specific resolution. If using a virtual camera or a pass-thru camera source, make sure it's outputting 8-bit 1080p 30fps video, to ensure maximum compatibility.
- Vertical or portrait modes are often not supported by virtual camera drivers on macOS
- Chrome and most browsers do not support higher than 60-fps, nor h264-based video devices
While a last resort, changing host hardware may work. Windows is popular with live streaming applications due to greater software and hardware compatibly, and if compelled to keep in the Apple ecosystem, you may find your device works with newer iPhones / iPads, which have a USB 3.0 port.
description: >- For those on macOS, if the camera works in Safari, but not Chrome, try the following options
Often the camera will not just fail ot load in VDO.Ninja, but fail to load with any web app in Chrome or browser.
You can confirm its not VDO.Ninja specific by going to the following page and seeing if the camera works with this simple camera app: https://webrtc.github.io/samples/src/content/devices/input-output/
If it fails only within VDO.Ninja, make sure you've enabled the Camera and Microphone permissions for VDO.Ninja.
Make sure VDO.Ninja has access to the camera and microphone
Sometimes another app is using the camera, and closing all other apps or restarting the operating system can fix it up. You cannot use your camera in OBS and in Chrome at the same time, for example.
You can try running the following from your Terminal in MacOS:
sudo killall appleh13camerad
sudo killall VDCAssistant
sudo killall AppleCameraAssistant
You can also close the camera app in MacOS via
Apple Logo > Force Quit > Select All Apps > (find 'Camera process') -> Force Quit.
In Chrome, you can turn off "Use hardware acceeleration when available" in the chrome://settings/system
page. You'll want to restart the browser after
Go to your Security & Privacy page in your MacOS settings, select the privacy tab, and make sure Google Chrome has access to your camera and microphone.
Do a full and complete uninstall of Chrome and then re-install. Perhaps try using the Chrome Beta version. Also make sure not to have any browser extensions install, as they can conflict.
Maybe your camera is not working or compatible, for whatever reason. Try a different camera and see if it works.
As a last resort, reinstalling the system fresh might be an option.
Browsers won't let you auto-start a screen share, as it will require a user's input to select the source. You can configure the screen share pop up to show certain screen share options instead of others, but you'll still need to manually select which source to capture.
There are still some other options though that might work for your use case:
- The Electron Capture app can be configured to allow for automatic screen sharing, which is useful if you want to start the screen share from command line or as a quickstart icon.
- OBS Studio can be used for screen capturing, and then when needed, you can have VDO.Ninja auto-select the OBS Virtual Camera as a source, since it can be selected automatically as a web camera.
- If you don't want to have to start OBS or are already running it, there's a virtual camera driver that will let you select screen shares as a source. See here.
Chrome only supports audio capture from a TAB or from the DESKTOP. If you would like to capture the audio from a desktop application, two popular options include VB Virtual Cable for Windows or Loopback for macOS.
Firefox and Safari only support Desktop audio capture, so Chrome (Edge/Brave) are generally recommended instead.
To capture an application's audio, and not the entire desktop, you can use a virtual audio cable.
On Windows, VB Cable is a free option, you can use it with Windows' built-in "mixer" app to push the audio from the application to the virtual cable. From there, you can bring the audio into VDO.Ninja as needed. There's also Voicemeeter, which offers more advanced routing and features for Windows users.
With macOS, Loopback is a wonderful app that makes capturing audio from an application easy, but it is non-free. For a list of free options for macOS, please see here: https://docs.vdo.ninja/platform-specific-issues/macos#capturing-audio
For a detailed guide on how to capture an application's audio, please see here: https://docs.vdo.ninja/guides/audio
If using a physical camera in OBS, or using a physical camera in VDO.Ninja, it can't be used by a second app.
If using the camera with VDO.Ninja, you can use it with other websites within the same browser though. So you can use the web version of Discord with VDO.Ninja; no issues with that.
- Open up a second OBS instance, and load your camera in that instead.
- Enable its Virtual Camera.
- Select the Virtual Camera in VDO.Ninja.
- Select the Virtual Camera now also in the first OBS instance (or other app).
Your camera *may* now be working in both apps; this has been tested with OBS and VDO.NInja on Windows 11 anyways.
Example:
Demo of it working
- Just pull your video into OBS from VDO.Ninja. It uses up a bit more CPU, but it simplifies things to just use VDO.Ninja as the source for OBS.
- You can also always use the Virtual Camera from OBS to load the VDO.Ninja camera feed into another app.
The Chrome / Edge / Chromium browsers will not allow access to media devices (camera / microphone) without SSL enabled.
Possible solutions include switching to https, accessing the site from http://localhost, or enabling the unsafely-treat-insecure-origin-as-secure
browser switch.
The browser flag, which works with Chromium-based browsers, can be accessed from: chrome://flags/#unsafely-treat-insecure-origin-as-secure. Specify the hostname and the IP address that you will be accessing, such as https://192.168.1.15:8080. Enable the option, and then restart the browser.
#unsafely-treat-insecure-origin-as-secure
More advanced users can try using openssl to generate self-signed certificates, and using them with their local webserver to enable SSL, assuming you have access to the webserver.
openssl req -nodes -new -x509 -keyout key.pem -out cert.pem
If you can access the site via http://localhost, or http://127.0.0.1, that may work also. This could be possible if hosting VDO.Ninja locally, and accessing it via a local webserver. If you have Python installed, you could get away using it to host VDO.Ninja in this way.
git clone https://github.com/steveseguin/vdoninja
cd vdoninja
python -m http.server 8000
When accessing VDO.Ninja in this way, make sure the remote computer that may also be accessing VDO.Ninja is using the same "salt". To debug this, you can try adding &salt=vdo.ninja to all the VDO.Ninja links, as that will mnually assign all the links to use the same salt. The salt is used in the encryption process for site isolation and increased privacy/security when not using the official VDO.Ninja deployment.\
If you're struggling to capture a game with VDO.Ninja using the browser, a list of options are below.
-
Disable Fullscreen Optimizations: Right-click the game's .exe file, go to Properties > Compatibility, and check "Disable fullscreen optimizations"
- Sometimes you want to even uncheck "Disable fullscreen optimizations", so try both ways
- Restart the game after applying changes.\
-
Run as Administrator: Try running both the game and your capture software as administrator.\
-
Compatibility Mode: Run the game in compatibility mode for an earlier version of Windows.\
-
Run the game in windowed or borderless windowed mode\
-
Consider using OBS Studio to capture the game with, and then output the captured video to VDO.Ninja using the OBS Virtual Camera.
- Sound can be captured with a virtual audio device in conjunction with the the OBS audio monitoring output option.\
-
If using hybrid graphics, such as two graphics cards, try to run the game on the same graphics card as the system / browser.\
-
Try window capture or full-screen capture, or try with a different browser.
- If using Window capture, you can capture the game's audio with the use of a virtual audio device, like Voicemeeter.
- Display capture tends to offer better frame rates than window capture\
-
Use an HDMI splitter and an HDMI to USB adapter to capture the output sent to your monitor.\
-
Update your graphics card drivers\
-
If using a browser such as Opera GX, it may throttle or disable VDO.Ninja when gaming.
- The Electron Capture application, or a different browser, are better choices
description: >- Some applications don't like being screen captured by Chrome; there are some options however
Disable Hardware Acceleration:
- Sometimes, hardware acceleration in either Chrome or Lightroom can cause issues. Try disabling hardware acceleration in Chrome by going to
chrome://settings
> Advanced > System > uncheck "Use hardware acceleration when available". Also, check if there's an option to disable hardware acceleration in Lightroom
Try a Different Browser:
- Test if the issue persists with other browsers like Mozilla Firefox or Microsoft Edge. This can help determine if the problem is specific to Chrome.
Use Windowed Mode:
- If Lightroom is in full-screen mode, try switching to windowed mode. Some applications don't share their display properly when in full-screen.
Use Display Capture in Chrome instead of Window Capture
- While this option may reveal more of your desktop than desired, if using a secondary screen to host the Lightroom application, it may still be a suitable solution.
Use OBS and it's Virtual Camera:
- You can use OBS to capture lightroom, and from there output it to VDO.Ninja via the OBS Virtual Camera. You would select the virtual camera in VDO.Ninjas a camera source, instead of a screen share source. OBS has more advanced screen capture options than Chrome does.
Some camera lenses are not easily accessible in native mobile applications, and many are not available at all in the browser.
The native app versions of VDO.Ninja may sometimes offer additional lens options not found in the browser, but adding all options is still a work-in-progress.
On Android, you can try Firefox Mobile as well as Chrome or other browsers to see if your camera lens appears there. Some manufacturers offer better support for their cameras than others, making lens selection more accessible to browsers and app developers.
Sometimes you can zoom in and the cameras will switch automatically, but this is rare.
There is the option to digitally zoom with VDO.Ninja, &effects=7, will allow you to adjust the digital zoom via the browser. This isn't an ideal solution, but it may work in some cases where optical zoom isn't available.
Below is a non-exhaustive short list of smartphones that appear to support more than one rear camera in the browser:
-
Samsung Galaxy S23 v13.0 supports 2 front, 2 rear
-
Samsung Galaxy S24 v14.0 supports 2 front, 2 rear
-
Samsung Galaxy S24 Ultra v14.0 supports 2 front, 2 rear
-
Samsung Galaxy S22 Ultra v12.0 supports 2 front, 2 rear
-
Samsung Galaxy A52 v11.0 supports 2 front, 2 rear
-
Huawei P30 v9.0 (/w MS Edge) supports 1 front, 4 rear
-
iPhone 15 Pro v17.0 and iPhone 15 Pro Max supports:
- back triple camera
- back dual wide camera
- back ultra wide camera
- back dual camera
- back camera
- back telephoto camera
- front camera
-
iPhone 15 v17.4 supports:
- back dual wide camera
- back ultra wide camera
- back camera
- front camera
-
iPhone 14 v16 supports:
- back camera
- back ultra wide camera
- desk view camera
- back dual wide camera
- front camera
-
iPhone 14 Pro v16 supports
- back camera
- back telephoto camera
- back ultra wide camera
- desk view camera
- front camera\
-
iPhone 13 v16 supports
- back camera
- back ultra wide camera
- desk view camera
- front camera
This list was based on results obtained using BrowserStack.com, so cloud-hosted devices. There may be errors with the results obtained, however you can check yourself on BrowserStack usually for free if a camera is supported or if the results have changed.
VDO.Ninja supports the WHIP streaming protocol, so if there is a native camera app that has proper WHIP-output support, and has the camera features you are looking for, using that can be used with VDO.Ninja.
Currently WHIP support in VDO.Ninja is a bit experimental, but the publishing URL for a WHIP-enabled device to stream to is:
https://whip.vdo.ninja/STREAMIDHERE
To view a WHIP stream then on VDO.Ninja, have open the following link in your browser:
https://vdo.ninja/alpha/?whip=STREAMIDHERE
There are camera lens adapters available for smartphones for fairly cheap; anywhere from $3 on aliexpress to $20 on Amazon. While not the best solution, it may be a solution available in a pinch that works across all mobile applications and services.
With the newest development builds of the Android native app of VDO.Ninja, many external (USB/UVC) cameras are supported.
With iPhones/iPads, USB-based models (iPhone 15 Pro) seem to support some USB video devices as well, via the USB 3.0 port.
Developments around USB/External camera support is ever evolving.
While iOS devices have so far not allowed the user to select the audio output destination of VDO.Ninja via Safari, there are some experimental options in the Advanced settings menu of Safari.
You can access such experimental option via Settings -> Safari ->Advanced -> Allow speaker device selection, as seen in the below screen capture.
There is no guarantee this will work, and maybe it will be enabled by default in the future.
There are some other experimental options as well that you can enable on iOS, such as AV1 and H265 codec support, and perhaps in the future Screen Capture will work, too. iPadOS tends to have more functionality available, such as external USB video device support (as of iPadOS 17), as least compared to the iOS 16 at time of writing.
If using a Windows PC, and you can't see one or all of your screens to share, consider setting your display's resolution to 1080p or/and disabling any HDR (high dynamic range) on that display.
If using a laptop, the display you may wish to capture needs to be on the same GPU that the capturing is happening. Some laptops with dual graphics systems will have issues. Using an HDMI to USB adapter that has an HDMI splitter built-in is a cheap hardware-solution.
If using the Electron Capture app, please consider loading that app with Elevated privilege's, which can be done via command line or via right-clicking the app and selecting the option to elevate from the context menu.
If on macOS, please be sure to give your browser system-level access in macOS to access your screen.
Chrome will let you share tabs, windows, and the entire screen, although audio capture is only available via Virtual Audio device (ie: Loopback) or tab-capture.
Safari has very limited options; it lets you capture the entire screen, and that is mostly it.
If on iOS, there isn't an option available to screen share from within the browser or native iOS app, but you can wirelessly airplay your screen to a computer, and then window capture that output.
Better than Airplay though, if you can connect your iPhone to a mac via USB, QuickTime supports USB-connected access to an iPhone's camera. This does not require any downloads and offers a high-quality stream. Using a virtual audio device, you can even capture IOS audio with this method.
Please refer to this guide for more details:
https://docs.vdo.ninja/guides/screen-share-your-iphone-ipad
For Android users, downloading the VDO.Ninja APK file will let you screen share on Android, however you can't screen share via the browser on Android.
The Android app is available here: https://docs.vdo.ninja/getting-started/native-mobile-app-versions
If using Chrome, launch Chrome from command line using the flag:
--enable-features=AllowWgcDesktopCapturer
There is an issue in some versions of Chrome where the mouse cursor can cause visual issues while screen sharing.
Another option is to use a different browser; Firefox is a safe alternative if the issue is specific to Chrome. Browsers like Edge and Opera also use Chromium, so likely you will see the same issue across Chrome, Edge, and Opera, while Firefox does not use Chromium. You might lose some audio support options when using Firefox however.
If the issue is just that the cursor shows while screen sharing, see:
{% embed url="https://docs.vdo.ninja/common-errors-and-known-issues/cursor-shows-when-screen-sharing" %}
Most browsers do not allow the mouse cursor to be hidden when screen sharing.
For gaming, this can be an obvious problem.
If you're a gamer comfortable with AutoHotKey, you can hide the cursor with it using a custom hotkey. You can download the free script to do this here: https://github.com/steveseguin/hide-cursor, which works with Windows and is preset to toggle the cursor with WinKey+Click.
You can use OBS to capture the game and use the OBS Virtual Camera to share the screen with VDO.Ninja that way. This might result in more stable game play capture, but it is added work.
You can setup the OBS Virtual Camera to output a specific scene or screen-share, rather than the current active scene, using this filter:
https://obsproject.com/forum/resources/virtual-cam-filter.1142/
If you prefer not to use OBS at all, there are numerous screen-sharing tools that can turn your screen into a virtual camera. Below is a link to a free one for Windows:
{% embed url="https://github.com/rdp/screen-capture-recorder-to-video-windows-free" %} https://github.com/rdp/screen-capture-recorder-to-video-windows-free {% endembed %}
Another paid option is to use an application that can toggle the visibility of the mouse cursor off and on. The paid app YoloMouse might be an option for gamers, as you can hotkey buttons to select different styles of cursors. If you select an invisible cursor, then you can hide the cursor on-demand with hotkeys.
Eventually cursor-visibility control will be available for Chrome, but for now, it will be a bit more hassle.
description: >- Blackmagic Decklink support isn't compatible with Google Chrome (chromium) browsers, but support is still possible.
Chrome continues to be incompatible with Blackmagic Decklink video sources, however there still are solutions.
- Someone says Firefox works for them, but not Chrome, so perhaps try Firefox with VDO.Ninja
- Bringing the Decklink into OBS, and then into Chrome via the OBS Virtual Camera seems like a popular approach.
- It's possible to bring in Decklink via OBS using WHIP webrtc output, which is compatible with VDO.Ninja if there is no NAT firewall blocking the connection.
- An option on this page (https://whip.vdo.ninja/), shows the WHIP ingestion URL and will offer a view-link.
- I also have WHIP working with https://meshcast.io/, if needed, but this may limit bitrates. Details on WHIP publishing should be available on meshcast.io.
- Raspberry Ninja as a command-line tool for VDO.Ninja that I am able to support myself, https://raspberry.ninja/, and it is compatible with a large array of input sources.
- Basic Decklink support could be added probably within a few minutes, but it's not as easy to use as the browser-based version of VDO.Ninja.
- I don't have Decklink device to actually test support with here, and Windows compatibility may be challenging, but it may be worth considering for your needs.
Please advocate to both Decklink and the Chromium development teams for proper Decklink support, as this has been a long-standing issue without either party addressing the issue yet.
Dealing with feedback is challenging, as the reasons are numerous, but not always obvious. Below are some common causes:
- Headphones are too loud. This is especially true if you've disabled echo cancellation or enabled the
&proaudio
/&stereo
modes. - Using Safari as it has poor AEC abilities; use Chrome instead. Safari struggles when a room has bad reverb issues, so changing locations might also help, if forced to use Safari.
&proaudio
or&stereo
mode is being used. This mode will disable echo-cancellation and so you must use headphones in this mode. As noted above, if using this mode, lower your headphone volume or/and use closed-back headphones.- Screen-sharing the desktop /w audio capture on, especially in the case of a group room, will create nasty feedback for others. You can add
&sstype=3
to the guest's invite link to try to prevent this issue, but otherwise you may need to use a virtual audio cable to limit what application's audio gets recorded. Details on that here: https://docs.vdo.ninja/guides/audio - Incorrect OBS configuration is common, especially if the echo is only heard in the RTMP broadcast or recording, and not by those using VDO.Ninja themselves
- Having two browser tabs open (such as one with the YouTube output playing) will cause echo. Echo cancellation only works within the same tab that the audio is played back and captured, and only if the echo is not prolonged.
You can use an experimental Chrome feature to solve this issue though. Go to chrome://flags/#chrome-wide-echo-cancellation and enable Chrome Wide Echo Cancellation, to see if it helps. - Having two devices connected to VDO.Ninja near each other, or sometimes even in the same house, can create echo. Phones have very sensitive microphones and can pick up the audio of others who might also be on the group call.
- Enabling certain advanced web-audio effects, such as per-video-specific audio output destinations can break echo cancellation.
- Playing an IFrame within VDO.Ninja (website share) may not have that IFrame's audio cancelled out by the echo-cancellation features.
- If only appearing in the OBS recording or stream, check to make sure you are not capturing the desktop's audio in OBS. This can happen if not using "Control audio via OBS" in the OBS Browser source, capturing a screen-share into OBS, or trying to record the director's room audio with OBS.
A good way to troubleshoot is to mute one person at a time in a room, seeing if muting any specific single person solves the issue for everyone else.
Normally the person who isn't hearing any echo or feedback is the cause.
If you identify that person, triple check that they are using Chrome and not Safari, make sure they are wearing headphones and that the audio is correctly playing into them, and have them close all other browser tabs and applications.
If the issue is only within OBS, this is likely an issue with OBS and not VDO.Ninja. Try disabling all global audio devices, muting audio devices in OBS one at a time, and double checking the advanced audio mixing settings.
Once camera / microphone permission have been denied, often accidentally, the browser won't let VDO.Ninja ask for it again. You'll need to manually change the permission to fix it, or use a different browser. How to change the permission depends on the browser and operation system.
I've provided links to some guides. If these guides are helpful for you, I'll offer a guide in VDO.Ninja to help future users when I detect permissions have been denied.
https://support.google.com/chrome/answer/2693767?hl=en&co=GENIE.Platform%3DAndroid&oco=0
- On your Android device, open the Chrome app
- To the right of the address bar, tap More -> Settings
- Tap Site Settings
- Tap Microphone or Camera
- Tap to turn the microphone or camera on or off; If you see the site you want to use under Blocked, tap the site -> Access your microphone -> Allow
If you’ve turned off microphone access on your device, you can control your app permissions on Android to use your mic.
If you're using a Chrome device at work or school, your network administrator can set camera and microphone settings for you. In that case, you can't change them here. Learn about using a managed Chrome device.
- Open Chrome
- At the top right, click More -> Settings
- Click Privacy and security -> Site settings -> Camera or Microphone
- Select the option you want as your default setting
- Review your blocked and allowed sites
- To remove an existing exception or permission: To the right of the site, click Delete
- To allow a site that you already blocked: Under "Not allowed," select the site's name and change the camera or microphone permission to "Allow."
If you still have issues, try a different browser; perhaps Firefox.
https://support.mozilla.org/en-US/kb/how-manage-your-camera-and-microphone-permissions
In Firefox Mobile, you can try going to Settings -> Site permissions -> exceptions (at bottom) -> VDO.Ninja, and then manually set the permissions for the camera and microphone to enabled.
If Firefox Mobile still gives you issues afterwards, try in incognito mode, try a different browser, or fully restart the device.
You can try following the same steps needed for Chrome above, however if that fails, ensure VDO.Ninja is not being loaded via an IFrame.
In the case of invite.cam for example, which loads VDO.Ninja via an IFrame, you may need to give microphone and camera permissions to both the invite.cam and VDO.Ninja domains.
You can visit invite.cam and vdo.ninja, and for each domain, ensure the microphone and camera permissions are set to allow.
On an iPhone, it's a bit more complicated:
https://gagonfamilymedicine.com/how-to-give-an-app-permission-to-access-your-microphone-on-an-iphone-or-ipad/
If the issue persists, fully close Safari and try again. Sometimes updating your version of iOS and restarting can help solve issues with camera permissions as well.
If embedding VDO.Ninja into a site as an IFrame, you'll not be allowed access to camera or microphones unless that IFRAME-element has allowed said permissions.
See the documentation for more details
{% content-ref url="../guides/iframe-api-documentation.md" %} iframe-api-documentation.md {% endcontent-ref %}
Adding &safemode
or &videodevice=0
&audiodevice=0
to the https://vdo.ninja/ link can either try the camera in safe mode or disable the camera/microphone completely.
In either mode, you might be able to bypass the initial camera selection page, or start the system with the default camera settings.
If you are able to start the session in this mode, you can go to the VDO.Ninja gear icon (settings), click on User settings, and then clear the local storage. You can then retry, refreshing the page, and try to connect again.
description: >- If screen sharing, you may see a frame rate drop once VDO.Ninja loses focus. This background app-throttling can normally be disabled
Chrome and Chromium-based browsers will sometimes throttle or limit the resources available to browser tabs that are not visible or in the background. This can result in a frame rate loss, often when using digital effects (green screen), when screen sharing, or using VDO.Ninja while gaming.
If the issue is with Windows itself throttling the tab or application, you can open the Task Process manager (Ctrl + Shift + Esc
), expand the processes for the browser application, and click on the VDO.Ninja tab process.
You can right-click it and disable efficiency mode if it is on.
Disabling throttling for Chrome can be done in different ways; the methods to control throttling seem to change every couple years however.
Some flags you can try disable in Chrome are the following:
chrome://flags/#calculate-native-win-occlusion
chrome://flags/#enable-throttle-display-none-and-visibility-hidden-cross-origin-iframes
You can also go into your browser's settings and search for "performance" or go to chrome://settings/system
, and at the bottom, you might see performance setting options.
Disable the efficiency mode, or customize as desired, and that might help with performance of VDO.Ninja when gaming with the tab in the background.
If you can't get things to improve, you can try the Electron Capture app for screen sharing or for VDO.Ninja. It's optimized to not throttle in most cases, and it can be pinned on top of other applications if occlusion is a cause of throttling.
{% embed url="https://github.com/steveseguin/electroncapture" %} Get Electron Capture here. Enable elevated privs if screen sharing with it {% endembed %}
If screen sharing is getting low frame rates still, you can try using OBS to screen capture your game or application, and use it's virtual camera output as the source for VDO.Ninja.
OBS with its Virtual Camera can maintain a higher steady frame rate than most browsers can when screen sharing. You can use a virtual audio cable to capture the games/application audio, if needed.
{% embed url="https://docs.vdo.ninja/guides/publish-from-obs-into-vdo.ninja" %}
If you get an Overconstrained error, it typically means the webcam or camera device has settings that are not compatible with VDO.Ninja code. With every camera being different, and everyone wanting high-quality video, it's a game of whack-a-mole to address each specific instance.
Some ideas though:
- You can try unplugging and reconnecting the device, and then trying again.
- You can use a different browser: Chrome, Firefox, Opera, etc.
- Do not try to specific a manual resolution; perhaps try the defaults.
- Do not use the camera in other applications at the same time.
- Try installing SnapCam or OBS virtual cam and try to select that; use it as an intermediary device.
- Uninstall NDI Tools, as it sometimes can cause issues or conflicts.
For a guide on deploying your own TURN server on a Ubuntu server, see the below link: https://github.com/steveseguin/vdo.ninja/blob/master/turnserver.md
The benefits of a turn server include Increased security when actively used (less chance of IP leaking) and better network compatibility. Without a TURN server, about 10% of remote guests will not be able to connect with each other. In some cases, at the cost of added latency, a TURN server can also provide better video quality by means of forcing TCP data transfer.
I do offer a basic TURN server for VDO.Ninja users, but it is costly to operate and maintain. Deploying your own can offer better reliability and it frees up potential resources for other VDO.Ninja users. Please do not abuse it.
Google Cloud offers a free small server for life, so it’s possible to do this for free, so long as you keep it all private. GCP also often comes with a $300 free credit tier, even though GCP is a bit expensive for heavy usage in the long-run. It doesn't support IPv6 either, but it does have a good network backbone (~20-cents per gig).
Twilio offers a paid TURN server service, which works well, but it's hard to setup for non-coders and it is twice the cost of Google to operating (40-cents per gig).
Another alternative to a TURN server is to bypass the NAT firewall that your OBS computer uses. You can do this in the network's router settings, normally by setting the DMZ to point to the IP address of your computer. This is dangerous, as it exposes you to the internet, but without a firewall you are less likely to need a STUN or TURN server.
Another option is to run OBS in the cloud on a virtual workstation, where you can open specific ports without the concern of a personal-computer hack. Some guests will still need a TURN server, but the likelihood is dramatically reduced.
You can also have remote guests who are needing a TURN server to install a VPN, like Speedify, which can bypass firewalls and other issues that might otherwise require a TURN server. Enabling TCP-mode within Speedify or other VPN service can also help combat packet loss, at the cost of added latency.
If going the VPN route, you also have the ability to secure your privacy/IP-address more securely; in some cases, more so than even a TURN server. See this article for more information there: https://www.expressvpn.com/webrtc-leak-test
The "V" in VDO.Ninja, in the top left, will go red as an indication that the client cannot talk to the VDO.Ninja server. It will NOT try to reconnect automatically, although that is a coming feature I will add eventually.
If on mobile and you tab away from the site, the server connection may be lost.
If the O is red, then you will need to REFRESH the page to reconnect. I'll fix this hassle eventually.
However, if the server goes down, the video stream will NOT stop if already start, as the video stream does not go thru the server. If the server goes down it just means that no one new can connect to the stream anymore, but if already connected, you are fine. I may also fix this in the future, but I don't see the urgency for it.
The video stream happens over a direct peer connection. This connection can be pretty unstable as cellular phones are not the most reliable things in the world. If a video stream dies, it is not the server's fault, but a failure of the peers to hold a reliable connection open.
Auto-reconnecting does depend on the server though. When connected over a high quality LAN , two devices really shouldn't see their connection fail though, but if it happens often, please let me know.
There is a backup server at https://backup.vdo.ninja if the main VDO.Ninja does ever go down.
Known issues that are most critical and up-to-date are normally listed on the main page of VDO.Ninja.
You can also refer to the #report-bugs channel on Discord, to see recently reported issues. I push bug fixes daily to beta, at https://vdo.ninja/beta, so give that a shot if you find a bug on the main release.
Below are some links to third parties, for a list of known issues that commonly will apply to VDO.Ninja as well. They might have some issues not yet reported here and are often up to date.
https://docs.agora.io/en/All/web_sdk_compatibility?platform=Web
https://github.com/twilio/twilio-video.js/blob/master/COMMON_ISSUES.md
https://support.twilio.com/hc/en-us/articles/223180908-Troubleshooting-Common-Problems-with-the-Twilio-Voice-JavaScript-SDK
https://github.com/webrtc/samples/issues
https://bugs.chromium.org/p/chromium/issues/list?q=webrtc%20type%3DBug&can=2&sort=-pri
Time fixes all wounds, even with Apple products.
Below are more possible/past issues, although the list is not often curated and can be assumed to be out of date.
-
Grey video loaded from guest in room. Try adding
&scale=100
and remove any bitrate limits set. If the issue persists, try a different video codec (&codec=vp9
, for example) or ask the guest to connect with&quality=2
(smooth and cool). -
OBS browser sources crash, turning all black. This can happen after refreshing/editing a browser source URL or just randomly. Restarting OBS can fix the issue, but to prevent the issue, try using:
"C:\Program Files\obs-studio\bin\64bit\obs64.exe" --enable-media-stream --disable-gpu-process-crash-limit
You can add `--disable-gpu-process-crash-limit`
to the OBS start up properties as a way to avoid this. There will still be an issue. You can also use the Electron Capture app instead of the OBS browser source. -
All green or all purple video from a mobile device (Pixel, Samsung Galaxy) can sometimes happen with certain resolutions or orientations. Using
&scale=100
or&scale=95
can sometimes help (viewer side), but also changing the video codec to&codec=vp8
might help. -
OBS on PC can have video become corrupted if there is moderate or heavy packet loss. Changing the video codec to vp9 or h264 can fix it for moderate packet loss, but for heavy packet loss using the Electron Capture app is suggested. You can also issue keyframes with the rainbow puke button in the Director's room or refresh the viewing page, but it's a temporary fix. Ideally, fixing the packet loss itself is the ideal solution.
-
Streamlabs (SLOBS) on macOS does not currently support VDO.Ninja directly; you'll need to use the Electron Capture app or the normal OBS version instead.
-
OBS on PC can sometimes run into a Max Buffer Limit Reached error, which can cause the audio to become delayed by seconds or simply stop being captured at all. Using the Electron Capture app to capture audio can avoid this problem.
-
Some browser-extensions will cause webRTC to fail. Try loading VDO.Ninja in incognito mode or try using the Electron Capture app instead.
-
On most modern browsers, a user will need to click the browser window before the video will play. This goes for VMIX and for Firefox/Chrome. This is not the case for OBS or the Electron Capture app, however.
-
Android 11 users using Chrome may need to push the app to the background, and then foreground it again, to unfreeze the video camera when it loads or changes camera sources.
-
iOS (iPhone) users using Safari 13 may sometimes not send audio.
-
iOS (iPhone) users sometimes cannot access their camera until they close all other Safari browser tabs. If it still does not work, using the native iOS app on the App Store may work; "Capture for VDO.Ninja".
-
Chrome on iOS only works for iOS 14.3 and newer. It will not work with VDO.Ninja on older iOS versions.
-
iOS 12 and newer is required for VDO.Ninja to work; older iPads may not work as a result.
-
Firefox on Android has numerous bugs that may cause connections to not always work; more prone to happen in larger group rooms.
-
Setting an audio bitrate to 64-kbps or higher can cause video to get stuck at near-zero bitrate. I've tried to account for this bug, but setting a higher video bitrate seems to help avoid the issue as well.
-
Bluetooth headphones on macOS, especially when using battery power, can cause audio-clicking on outbound audio.
-
Safari on macOS does not have the greatest noise or echo-cancellation, causing poor audio performance. Use a Chromium-based browser instead for the best audio quality.
The loading circle will appear in a VDO.Ninja view link if a video does not auto-load within several seconds or so.
It will be removed once the video connects, and won't re-appear unless the browser source/page is refreshed.
You can hide this loading circle by default by adding &cleanoutput
to the URL of the view link.
example: https://vdo.ninja/?view=ABC123abc&cleanoutput
This will hide other non-essentially UI elements as well, such as any error messages. In most cases, when a view link is loaded into OBS, most non-essentially elements are hidden by default.
It is also possible to customize the loading circle with other images.
Some users have reported their audio recording of VDO.Ninja stops or becomes choppy once OBS Studio is taken out of focus or minimized.
One solution is to run OBS Studio in Administrator mode. You can do this by first ensuring OBS is closed, and then holding SHIFT, right-click the OBS Studio icon; select Run as administrator
from the menu that appears.
Another option is to use the electron-capture.md to capture VDO.Ninja, instead of OBS browser source.
There are several reasons you may be experiencing low frame rates, including:
- If you are on MacOS using StreamLabs OBS, then the frame rates will be bad because of a bug in StreamLabs for Mac (consider the Electron Capture app instead).
- Try switching on "Enable Browser Source Hardware Acceleration" on in Advanced settings of OBS.
- If you are using Cellular / 4G, then the quality of the video may be poor due to the TURN server being in the USA or overloaded.
- Lights in your room are too dim maybe; try to make your room much brighter.
- Resolution is set to high, so selecting a lower resolution might help. This is especially true for H264 streams.
- Your Internet may be very slow or unstable. Try maybe Speedify.com and DO NOT use Wi-Fi.
- Make sure your CPU is not running near 100%. An overloaded computer or network will lag.
- Lower the resolution of OBS Ninja; select "Smooth and Cool" or 640x360 during camera selection.
Regardless, putting your own version of the HTML server up will not make it any faster.
To debug what the issue is, determine if it is faster when going from Chrome tab to Chrome tab on the same computer. If not, then it is nothing to do with servers.
If you are using a Mac with StreamLabs, you might be better off using the Electron Capture app instead.
One user had an issue where their microphone audio would drop out now and then; not just in VDO.Ninja, but in all browser-based web apps.
They resolved the issue by disabling certain WebRTC audio processing options in the browser
In Chrome,
From chrome://flags
we disable:
#enable-webrtc-allow-input-volume-adjustment
#chrome-wide-echo-cancellation
ℹ️ This also might be a useful option if using a USB mic that has the audio volume controls changing against your will, such as with a Blue Yeti.
In Firefox, we disable:
media.getusermedia.aec_enabled
media.getusermedia.agc_enabled
media.getusermedia.noise_enabled
media.getusermedia.hpf_enabled
iPhone 14 phones in particular have been pretty buggy with Audio, along with older versions of iOS across all iOS devices.
Make sure to update your iOS device if possible, use the newest version of VDO.Ninja (perhaps even the alpha version at https://vdo.ninja/alpha/), and disable any audio processing in VDO.Ninja by adding &noap
to the URL.
It is not recommended to use Bluetooth audio devices with VDO.Ninja. In the past, there were drop outs when using AirPods on a battery-powered Macbook, for example. Constant Bluetooth range / connectivity issues can also cause VDO.Ninja to potentially lose the connection to the microphone.
USB Hubs are not all created equal, and some may cause USB devices to drop in and out. For this reason, connect your microphone and cameras directly to computer, bypassing USB hubs if possible.
Audio captured from a microphone may be paused or stopped if there is an inbound phone calls or system notifications. I suppose this is a mobile security consideration, but after a notification alert, the microphone may sometimes not be re-activivated, either due to a system-bug or other.
For this reason, disable notifications, inbound calls, etc, while streaming on mobile with VDO.Ninja.
Computers that are running at near 100% CPU load can fail to encode audio streams, audio drop outs may occur during a call as a result. Please consider reducing the CPU load on your system to avoid this issue.
Heavy network packet loss, such as a bad WiFi connection can also cause audio drop outs. Completely connection losses are possible also, particularly if behind a corporate firewall or VPN service that is throttling or restricting WebRTC services.
If the microphone stops working in VDO.Ninja when OBS Studio is open, on MacOS, considering using Safari instead of Chrome or other browser.
One user with this issue noted the problem resolved itself when they used Safari instead of Chrome.
They also noted that opening OBS with the scene first, then launching VDO.Ninja in the Chrome browser, also resolved the issue. Safari was indifferent to order.
Some users on Google noted that they re-selected their microphone permissions in the browser to resolve the issue as well, so there may be some system-level permissions issue at play here.
It's perhaps possible a virtual audio cable might also help, if the issue is a shared device issue. Using the monitor audio output of OBS as an input to the virtual audio cable, or using an application like Loopback for MacOS, might be a way to bypass the issue.
Some microphones, like the Blue Yeti, Wave XLR, Samsun Q2U, or Scarlett Solo XLR interface, may have issues with Chrome (Chromium) and the mic's gain auto-changing on its own. This may cause clipping in certain cases or it may interfere with other applications that may also be using the microphone.
You can also add &autogain=0
to the VDO.NInja invite link to disable the auto-gain. You can also toggle the auto-gain from the VDO.Ninja settings menu, or if a guest, the room's director can remotely toggle the guest's auto-gain via: advanced options -> audio settings -> auto gain control.
Disabling the auto-gain functionality in VDO.Ninja may cause the audio level to be rather low, so it will be up to you then to manually set the gain accordingly. VDO.Ninja offers manual gain if needed.
An additional option to addressing this issue seems to be installing a browser extension that with disable auto-gain automatically within Chrome. (https://chrome.google.com/webstore/detail/disable-automatic-gain-co/clpapnmmlmecieknddelobgikompchkk)
If the above options do not work, another option perhaps is to use a single virtual audio cable for all your applications instead of access the microphone directly. In this case, you'd send the mic audio to that virtual audio device, which allows you to have a single point of control for gain. There's numerous virtual audio cables out there, including Voicemeeter and Virtual Audio Cable.
For more information on this topic, you can see discussions here, https://support.google.com/chrome/thread/7542181?hl=en&msgid=79691143, and more recently here, https://support.google.com/chrome/thread/210106028/google-chrome-constantly-auto-adjusting-microphone-levels-solved.
description: >- If you trying to add your video to OBS or Streamlabs, but instead of video you see buttons saying something like "Add camera" or "Share camera", double check your browser source links.
If see the VDO.Ninja menu, instead of a video, it is typically caused by having your PUSH link used as a VIEW link in OBS or Streamlabs's browser source.
To fix, you should be able to just replace the ?push=
part of the URL with ?view=
.
A push link is for the sender to use, so to send video from your phone or computer to OBS.
A view link is used for viewing a video in OBS or other studio software.
VDO.Ninja will respond differently to whether a push or view link is provided, as each has a different role.
If you still see the VDO.Ninja menu or website, check to make sure your link is correct. Your links should start with https://vdo.ninja/?
If you forget the ?
, or have other errors in the URL, the website might load in an error state. This error state may sometimes be the VDO.Ninja website, perhaps with no images showing, or other graphical issues.
If still having problems after, ensure the stream ID value for both the view and the push parameters of the sender and viewer links are the same. You should have only at most one push-link open per stream ID as well; more than one will show an error that the stream ID is already in use.
description: >- OBS Studio is just black in the browser source; potentially you hear audio, but nothing else.
Please be aware that OBS v24 to v26.0 does not natively support VDO.Ninja, but version 26.1.2 and newer does.
If using an Android smartphone, try using Firefox instead of Chrome, or a different browser in general.
If you're in Iran or China, WebRTC may be blocked; try using a VPN.
Use the Electron Capture app if you are using a non-compatible version of OBS. > Get it here <
Ensure that the “Enable Browser Source Hardware Acceleration” checkbox is checked in the advanced settings. If you still get just black video when it’s checked, then you can try:
- Uncheck the Hardware Acceleration checkbox -- does it work now? If so, it may be choppy and will use more CPU, but perhaps still usable. If the problem is that it's choppy, ensure that hardware-acceleration is checked.
- If using an Android mobile smartphone as a camera source, try using Firefox Mobile or a few different browsers. If that fails, try the native Android app version, if your needs are simple. This is often the case with Samsung A-series smartphones, although the Galaxy A12 especially seems to have issues.
- If you're in Iran, China or another sanctioned/censored country, WebRTC may be blocked; try using a VPN.
- If on cellular, try switching to a different network.
- If behind a corporate firewall, try using cellular instead.
- If you're using PFSense or a PiHole for home network security, try bypassing it or using a different network; most users using PFSense have security set to overkill, blocking everything.
- Updating your graphics card drivers, especially after a fresh install, can sometimes help.
- Run OBS Studio as an Administrator.
- If your computer is running at 100% CPU / GPU load, try lowering the resolution of the browser source element to 1280x720 or lower; 640x360 should use little CPU, even if hardware-acceleration is disabled. H264 as a codec will also use less CPU / GPU than other options, normally.
- Try specifying a custom frame rate of 30 in the browser source options in OBS
- Go to the windows setting for “Graphics Settings”. You may see OBS or SLOBS under programs listed for “graphics performance preference”. Make sure OBS or SLOBS is set to “high performance”. Turn on hardware accelerated GPU scheduling.
- Update OBS Studio to the newest version. When doing so, fully uninstall the old version before installing the new version. If you are up to date, try the beta release or just re-install.
- If using OBS 64-bit, try installing the 32-bit version instead of OBS.
- Switch the GPU used by OBS if using an NVidia GPU; settings in the Nvidia control center. If you can, perhaps try disabling the integrated graphics card in the BIOS and using only the discrete graphics solution.
- If using a laptop, check out this article: https://obsproject.com/wiki/Laptop-Troubleshooting#for-nvidia-based-laptops. Also consider disabling power-saving mode and plugging the power into the wall directly.
- Enable Compatibility Mode for OBS; this setting is available via right-clicking the OBS icon and clicking properties.
- Try a different video codec; perhaps
&codec=h264
or&codec=vp9
, which can be added to the view links. Android phones in particular might have problems. - In the OBS Settings -> Advanced menu, disable Browser source hardware acceleration, and then restart. If it works then, the above GPU-related options should work. Otherwise, it might be a firewall, VPN, or privacy software.
- Check to make sure you are not behind a corporate firewall or on a VPN (see Network issues below). Sometimes using a Firewall can actually help, such as if the guest is in mainland China, where a VPN service (like ExpressVPN) has been able to bypass the Great Firewall of China.
- Disable any anti-virus or other security software. If using PFSense firewall, ensure you are whitelisting the IP address of the remote camera source or allowing webRTC-related UDP traffic. While use PFSense may still work, if you do not open the correct ports, frame loss may be significant if relying on the public TURN servers for high-bandwidth data transit.
- If the video is choppy, be sure there is no packet loss. Adding
&stats
to the VDO.Ninja URL link will display the stats in the OBS Browser source, on top of the video. A high-packet loss, higher than 0.3%, can result in signifcant frame loss, while 3% packet loss is nearly unusable. - You can also download the Electron Capture app, and use that instead of OBS browser source: https://github.com/steveseguin/electroncapture
- Make sure you have not disabled webRTC with your browser; you can confirm you have webRTC disabled with your browser(s) here: https://browserleaks.com/webrtc
- As a final resort, consider using a Cloud-hosted version of OBS instead, such as on Paperspace or AWS /w Parsec installed.
If the hardware-acceleration checkbox is not checked, check it and restart. Does it work now?
We provide a speed test to see if the connection works at all, https://vdo.ninja/speedtest You should be able to see your video streamed back at you. If not, there might be a network problem.
You can visit https://browserleaks.com/webrtc or https://networktest.twilio.com/ for tools to help debug issues that might be impacting your network, such as Firewalls or incompatible browsers.
description: >- Why are the resolution and framerate sometimes not the same as my OBS output settings?
If you open an OBS Virtual Camera device in VDO.Ninja before starting the output in OBS, the OBS virtual camera will default to 1080p 30fps. If you start OBS first, it will use whatever is set as the Output resolution and framerate in OBS Studio's options, under Settings -> Video.
So, make sure the set OBS to 60-fps and then start the OBS Virtual camera before starting Chrome and/or VDO.Ninja. If you don't do this, you may be capturing at 30-fps max.
You may also have low frame rates if you are using the OBS virtual camera straight from OBS rather than by adding a filter to the video source. Filters may reduce the frame rate by 30% or so in my testing. Instead, considering opening two instances of OBS instead, if that is needed.
Of course, frame rates with VDO.Ninja can also be low if you don't have the video bitrate set high enough; for gaming, you might want to consider adding &videobitrate=20000
to the view link. You can also try different video codecs, such as &codec=h264
. If you are on a WiFi or weak Internet connection, that also can limit the frame rate of a stream due to heavy packet loss.
VDO.Ninja offers a lot of power and unconstrained video quality. Some devices however will overheat if pushed for prolonged periods though, as they were not designed necessary for professional streaming video applications in mind.
Still, there are steps you can take to minimize the heat generated by devices with software settings and configurations.
The viewer has control over the requested quality. 1080p video on a mobile device uses up a lot of power, including by data-transmission and the video encoding itself. Try using a lowering resolution, either by adding &quality=2
to the publisher's link or by adding &scale=50
to the viewer link.
The same goes for video bitrates; the default is around 2500-kbps, but perhaps try 1500-kbps instead. For example, https://vdo.ninja/?view=MYSTREAM&codec=h264&scale=50&bitrate=1500
Some mobile devices have support for hardware-based H264 video encoding. An iOS device has three 720p30 hardware encoders, for example, while Android devices are hit and miss.
To reduce heat for mobile devices, try using &codec=h264
on the viewer side to request the video has h264 format. If the mobile publishing device supports it, it will use the hardware encoder for publishing. This will increase the chance for corrupted video, such as all-green flashes of video, but it should greatly reduce heat and power consumption.
Normally H264 will be used automatically if the hardware-device has a hardware-decoder, but this might not always be the case. Just double check, as VP8, VP9, and AV1 are rarely hardware-encoded. Keep in mind iOS devices are limited to 720p30 when using H264 hardware encoding, but can do 1080p30 with VP8 in software; life is full of trade-offs it seems.
When it comes to hardware encoding on laptops, H264 encoders sometimes kick-in, but the vast majority of the the time the browser will choose to still encode H264 video using a software-encoder. For the best chance of it working, use a Chromium-browser, like Chrome.
It should be noted that hardware encoders are finite in availability -- this means that they are often not something you can rely on when in a group-video call with multiple peers requesting video streams. If using an Nvidia GPU, you might be limited to 2 or 3 hardware encoders, just like an iOS device, which doesn't work well if streaming to many viewers.
The VP9 codec offers higher quality than most default codecs, but it also uses higher CPU load. AV1 may be even worse, so sometimes H264 is best. Just something to be aware of.
Currently a web-browser does not allow a single video encoder to share video with multiple guests, at least not at low-latency. This is a limitation that will be addressed in the future, but it's a current limitation now.
VDO.Ninja is peer-to-peer-based, which works great for linking one camera to one viewer. The more viewers though, as mentioned, the more load is created on that guest. Just the act of uploading data uses power, so mobile devices are also quite poor at restreaming to multiple viewers even if encoding video wasn't already an issue. This is why the video quality on mobile devices between guests is set very low by default.
Meshcast.io is by the same creator as VDO.Ninja, but it's a server-based solution to sharing low-latency video. It has a lower-maximum video quality, it isn't peer-to-peer-based, and it has numerous other short comings, but it does allow a mobile device to encode just one video stream, upload just one video stream, and still share that video with numerous viewers. Feel free to experiment with it, it's free, and if more quality and reliability is needed, there are paid options that are similar to it available. The cost of restreaming with a server-solution is about 15-cents per GB, depending on quality of the service. This is why Meshcast.io needs to limit it's video quality to afford a free-offering; server solutions are expensive!
Every viewer of a stream adds to the heat and load experienced by the publisher of that stream. To reduce heat as much as possible, only allow one viewer of a stream to be active. Group-scenes, multiple-guests in a room, and multiple view-links each consistent as an active viewer. There are ways to optimize in these situations, but they may not be obvious. (&optimize=0
, for example).
In the case of an iOS device, since it only has 3 hardware encoders, the device will switch to VP8-software mode or just stop working all together if those get exhausted. iOS devices are rather poor at software-encoding video, especially at higher resolutions, so be careful.
You can force-limit the number of connections and viewers with the &maxconnections=1
parameter, added to the publisher's URL. If you are accidentally viewing the video stream multiple times, this will help prevent more than one viewer from having access.
Charging a mobile phone creates heat. If you start charging your device after you've already started streaming, that will increase the heat. Try starting with the phone already at a 100% full-charge to avoid even more unnecessary heat.
Professional cameras do often include a small fan inside them to reduce heat. Consider buying a heatsink that can be mounted onto the back of your smartphone, with an optional fan to turn on if it starts getting hot. These are not super common, probably not super effective, but they can be had for not much money.
Sometimes a thick protective case can insulate a smartphone, making it hotter than needed, too.
I've done a YouTube video demoing how cooling your smartphone can reduce heat and also improve performance, as a hot phone my throttle the performance. See below:
{% embed url="https://www.youtube.com/shorts/kH2Y3kAysv4" %}
It is not possible to change between apps, screen-share, or turn off the display when using a web-app, like VDO.Ninja. You can turn down the screen brightness manually on your phone though, which will be nearly as effective.
Also, If you use ?push=STREAMIDGOESHERE&cleanoutput&nopreview&chroma=000&view
as a publishing link, you can hide pretty much everything on the screen, and if using an OLED display, this should reduce power usage. This is a great option if you wanted to set your phone up as a dedicated webcam and were worried about the screen generating heat.
There are native Android and iOS app versions of VDO.Ninja, but they are very limited at the moment. They can be used to turn a phone into a dedicated webcam, and that's about the only they are good at. The Android app supports screen-sharing, which is the main advantage of using it.
Until the native apps are further developed, they are not great options for most users. They may still however use less CPU and may generate less heat though, just due to how basic they are in function.
Download the mobile app versions here: https://docs.vdo.ninja/getting-started/native-mobile-app-versions
Please contact steve at [email protected]
or via discord (discord.vdo.ninja) if you'd like to contribute to development of these native versions. The cost, time, and skill requirements for their continued development are quite steep.
Older 2011-era Apple notebooks are prone to overheating. Even newer generation Macbooks can overheat if stressed. Normally these systems throttle the CPU to be MUCH slower when they get too hot, so it may appear like there is a network issue.
Ensure you are not running a laptop at 100% CPU load, make sure it has plenty of cool ventilation, ensure the fans are clean and not full of dust, start with a full battery and keep the computer plugged in
VDO.Ninja has limited support for hardware encoders. Hardware encoders greatly reduce heat, but they are often poorly suited for low-latency video that requires tolerant packet-loss capabilities and dynamic resolutions. Green/purple/grey coloring of video, lost frames, and distorted video blocks are common when using hardware-encoders at very-low latencies.
There is support for the Raspberry Pi, both software-encoder and hardware-encoder options, but the hardware-encoded option is the most limited and challenging. The current project supporting this offering is here: https://github.com/steveseguin/raspberry_ninja
Like with the native mobile app versions, the capabilities of this option is very limited. It does not support group-rooms and it does not yet support multiple viewers. Since many are using the Raspberry Pi wirelessly, it must also be said that it has very poor support of packet loss recovery -- the video will often not be smooth, especially if the WiFi signal is not very strong.
Using a Chromium browser with a Raspberry Pi, in software-encoded mode, will probably give more reliable results, but also generate a lot of heat and limit the maximum video resolution a lot.
Just as a consideration though, the Nvidia Jetson development boards support higher resolutions and seem to have better support for dynamic video and packet loss recovery. These products are a bit more expensive, but tend to work better than a Raspberry Pi when it comes to encoding HD video. I have a support for the Hardware-encoding capabilities of a Jetson here, buried away alongside the files for the Raspberry Pi: https://github.com/steveseguin/raspberry_ninja It's pretty basic support also currently, but has a lot of potential.
In the future, more professional video-centric hardware encoding options with built-in LTE/5G transmitters will support VDO.Ninja in a basic publish-only mode. This advancement will be due to the adoption of community standards for publishing low-latency video, although don't hold your breath for progress here.
Packet loss can cause low quality video, audio distortion, clicking, and is the cause for numerous other video problems.
WiFi is often the main contributor to packet loss, but it's not the only cause. Still, eliminate WiFi as a possible culprit by removing it from your setup and from the guest's setup.
An Ethernet connection is highly recommended over WiFi.
- Make sure the guest is plugged in and powered; battery mode with some laptops can cause issues.
- Try to sit closer to the WiFi router and try to limit the traffic on the network; the more that's going through the air, the more packet loss.
- If the guest can use the 4G LTE instead of WiFi (tethered via USB), that will often be much better than WiFi.
- The guest can also Tether their 4G LTE /w their WiFi using bonding apps like Speedify or with hardware from Peplink; these services can give you more control over network settings.
- If using a smartphone, consider using a USB to Ethernet adapter instead. I have a video demonstrating how to do this here: https://www.youtube.com/watch?v=abCuANblE5w
- Some users have mentioned that reducing their network's MTU size, or the size of their packets, has helped reduce packet loss over bad WiFi. You'll need to experiment with this, but 800 to 1000 might be in the range you can try in this case.
- Improving the Wi-Fi network, such as switching network bands (5hz / 2.4ghz), buying a mesh-based multi-node access point setup for larger homes, changing network channels to account for frequency interference, updating to Wifi-6 or newer technologies, and moving the closer to the access point.
- Try to have the guest use a different browser. For example, if using Firefox, use Chrome, and vice versa. Some browsers are optimized for privacy over performance, and that may hinder video quality, and even Chrome can sometime be configured in a way that hinders VDO.Ninja from working well.
- Disable any Anti-virus software or any security software that may disable WebRTC IP leaking.
- Advanced network firewalls, like pfsense, may block UDP packets or force traffic through a TURN relay server. VDO.Ninja uses mainly UDP packets in the high port range.
- If your connection with a guest is going thru a TURN relay server, such as perhaps due to a security or privacy setting, resolving that may fix issues. VDO.Ninja offers publicly accessible and free TURN servers as part of its service, but these may introduce packet loss. You can always host your own TURN servers instead, but avoiding them if not needed is usually the best option.
- Restart your Internet router; sometimes a router or network equipment just needs a good reset or update.
- If your router is double-natted, such as if you have a router plugged into another router at home, it can cause VDO.Ninja to send video via relay servers instead of the preferred direct peer to peer. Commonly, to address this, either set the second router as an AP access point instead, or configure the first router to be in bridge mode.
Sometimes two peers just can't get a good connection, while with other peers they can. This is often largely dependent on your ISPs, and it can be challenging to fix.
- Host your OBS Studio on a premium cloud server, like Amazon AWS Workspaces or Google GCP. These providers have good networks optimized for most users to access, and hosting a VPN, TURN server, or the entire OBS Studio can help you control for network routing issues.
- Forcing the TURN relay servers into use may help at times; adding
&relay
to the links can enable this mode. It may add some latency though, as the video traffic will take a longer, but different, network routing path that may be more reliable. Hosting your own TURN server on a local premium server, and specifying VDO.Ninja to use it, has been a good solution for some. - As mentioned above, you can also use a VPN, perhaps one with the server is hosted on a local Google Cloud server or perhaps use a VPN service that offers local edge network access onto a premium network. If all guests connect via the VPN, you'll have more control over the routing quality.
- Change your ISP (Internet provider) to another provider; this maybe needed on either your end or the remote guest's end. Some network providers, especially consumer-grade residential providers, can have really bad packet loss issues, especially during the evening hours.
- Use cellular connections instead, especially if the issue is intermittent and perhaps only during peak Internet usage hours. Cellular connections are optimized for audio and live streaming, and so while they may have limited bandwidth or be expensive, they can also be the last refuge of hope sometimes. This is especially true of 5G connections.
- If your router or connection supports IPv6, but you don't have it enabled, try enabling it. Sometimes if limiting yourself to IPv4 or IPv6, your ISP may send your traffic through an IPv4<>IPv6 translation server, which could introduce delays, throttling, and packet loss.
- Some cellular providers limit and throttle UDP packets, which are used by VDO.Ninja. Using a service such as Speedify, in TCP-mode, can bypass this limitation by wrapping the UDP packets as TCP and relaying them thru servers. Check with the cellular provider before purchasing a SIM card to ensure they do not throttle UDP packets as well, if intending to travel.
- As mentioned before, sometimes the TURN relay severs get used, and this might be the case with cellular connections or corporate firewalls; hosting your own TURN server or finding a way to bypass them can sometimes help improve the quality of connections.
- Using
&chunked
mode on the sender's side can enable an alternative way of sending video data, but this option is only supported by Chrome and other Chromium-based browsers. It also is fairly CPU intensive and may require some tweaking of bitrates and buffers to have it work well for you situation - Try using
&codec=av1
on the viewer side; this won't solve packet loss issues, but the AV1 codec is more efficient than the default codecs, and so it may offer better video quality despite the packet loss. - Try adding
&buffer=500
to the viewer link, as this might allow for more time for lost packets to arrive. - Reduce the bitrate of your video streams. If your connection can only handle 30-mbps in and 10-mbps out, trying to push it to do more will cause network thrashing and packet loss. In this case, try to ensure that your connection's up and download links are not saturated by more than 80% of their tested max capacity. Leaving some headroom will reduce latency and packet loss, ultimately leading to better quality.
- Consider using Meshcast or a WHIP/WHEP server-based SFU provider, and use that with VDO.Ninja instead of a direct peer-to-peer connection. I have a guide for setting up Cloudflare to be used in this regard, but any WHIP+WHEP SFU can work. This can provide more advanced buffering and SVC options not available with direct browser to browser options.
- Use Raspberry.Ninja or OBS Studio's WHIP output as a video source, instead of the browser. Raspberry.Ninja in particular supports double redundant video streams for added error correction, and while it uses more bandwidth, it can tolerate heavy packet loss and force a specified video quality. While packet loss will still exist, you might find the outcome is more to your liking.
- If screen sharing, you can use
&contenthint=detail
, which can tell the system to prioritize frame resolution, than frame rate. While this isn't suitable for gaming, it might be a good option for screen shares, where packet loss might otherwise might text unreadable.
- Turning down the audio bitrate (
&audiobitrate=128
) will be less prone to clicking issues vs something high, like 256-kbps. The default is 32-kbps. - You can add
&enhance
on the viewer side to try to prioritize the audio over the video. This might help with audio clicking issues. - Using
&audiocodec=red
on the viewer side can increase the amount of error correction data being sent, reducing packet loss. This will double the audio bandwidth, but that shoulnd't be an issue for most modern connections.
I have a video talking about packet loss, with details on how to setup Speedify as well: https://www.youtube.com/watch?v=je2ljlvLzlYAnd
There is a speedtest that the local user can try out to give them feedback on their packet loss. This is a special speedtest, different than normal tests, as it does not test for available bandwidth, but network quality and packet loss: https://vdo.ninja/speedtest
If you'd like to remotely test a guest's connection, you can also have them perform the VDO.Ninja pre-check test. This is a comprehensive system and network test, which allows you to review the results of the guest remotely: https://vdo.ninja/check
You can also do a peer-to-peer test by just making a VDO.Ninja connection with the guest. If you hold down CTRL (cmd) and click on their video, you'll see the stats. Packet loss is a listed stat, as well as the candidate type. If a guest is connecting to you via RELAY candidate type, that implies there is a firewall or security setting blocking a direct peer to peer connection. Addressing this will likely resolve your issues.
When doing a pre-check or speed test, make sure to test during the hours of the day you intend to go live. Mornings will often have less packet loss than evenings, with around 7pm to 10pm being especially bad.
So I asked ChatGPT about improving the network quality between two peers, and its response is below.
Understanding the root causes of UDP packet loss across different network paths can be quite complex, particularly because the internet is a mesh of countless routes, and performance can be affected by a multitude of factors that are often beyond the control of end users. Here are some points to consider when trying to diagnose these issues:
- Path Specifics: Even if all users have good connections to a common server like Google's, the path packets take to reach your specific service might be vastly different. This can be due to the routing policies of ISPs, peering agreements, or simply the geographic distance the packets need to travel.
- Network Congestion: One of the most common causes of packet loss and latency is network congestion. This can occur at any point along the path and can be temporary (like peak usage times) or could indicate a more chronic issue with a particular segment of the network.
- Quality of Service (QoS): ISPs may implement QoS policies that prioritize certain types of traffic over others. For instance, UDP traffic may be deprioritized in favor of TCP traffic, which could negatively impact applications that rely on UDP.
- NAT and Firewall Configuration: Users behind strict NATs or firewalls might experience connection issues if certain ports are blocked or if the NAT type is restrictive (Symmetric NAT), which can cause problems for UDP traffic in particular.
- Hardware Issues: Problems with user hardware (like routers or modems) or even the quality of the local network (like Wi-Fi interference) can cause increased packet loss.
- ISP Issues: Issues within an ISP's network, such as faulty routing, misconfigured equipment, or even under-provisioned transit links, can lead to increased latency and packet loss.
- Server Performance: On your end, the server's performance and its connection to the internet could also affect the user experience. Overloaded servers or servers with a poor connection to the backbone can be a bottleneck.
- Packet Inspection: Some ISPs may perform deep packet inspection which can introduce latency and potentially drop packets if they are deemed to be non-essential or if they match certain patterns.
- Transit Providers: Different users may have different transit providers between them and your server, which can result in different latency and packet loss characteristics.
To diagnose these issues, you could:
- Implement more detailed logging and monitoring on your server to see if there are patterns in the connectivity issues.
- Ask users to run traceroutes and path analysis tools from their location to your server and back to determine where delays or losses are occurring.
- Use network diagnostic tools that can simulate UDP traffic and measure performance across different network paths.
- If feasible, provide alternative connection points or relay servers in different geographical locations to see if routing through these points improves performance.
Ultimately, diagnosing network performance issues often requires cooperation from ISPs and a deep dive into network performance metrics. Tools like MTR (My Traceroute) can be more informative than a simple traceroute as they provide information on packet loss at each hop and over time, which can help in pinpointing where issues are occurring.
- atem-not-working-with-firestick.md
- very-old-iphone-support.md
- cant-select-audio-output-on-ios.md
- screen-share-is-just-a-black-video.md
- mic-audio-dropping-out.md
- loss-of-audio-when-obs-minimized.md
- known-issues.md
- echo-or-feedback-issues.md
- works-on-wifi-but-not-on-4g.md
- cant-capture-an-applications-audio-when-screen-sharing.md
- cant-load-camera-both-in-obs-and-vdon.md
- cant-select-a-camera-lens-on-mobile.md
- no-video-in-obs-just-an-add-camera-button.md
- audio-over-vdo.ninja-isnt-working.md
- loading-circle-shows-in-obs-or-browser.md
- appearing-then-disappearing-guest.md
- cant-auto-start-screen-sharing.md
- audio-clicking-popping.md
- cant-share-my-screen.md
- nothing-shows-up-in-obs-or-it-is-choppy.md
- already-in-use-or-claimed-errors.md
- blue-spinning-window.md
- cursor-shows-trailing-or-artifacting.md
- packet-loss.md
- overheating.md
- audio-is-delayed-in-obs.md
- vmix-high-cpu.md
- obs-virtual-camera-low-has-fps.md
- virtual-camera-not-working-on-mac.md
- mic-stops-on-macos-when-obs-opens.md
- video-is-pixelated.md
- video-freezes-mid-stream.md
- webcam-freezes-after-a-time.md
- is-the-obs.ninja-server-down.md
- hosted-your-own-turn-server.md
- why-cant-i-screen-share-from-certain-devices.md
- cursor-shows-when-screen-sharing.md
- getting-overconstrained-camera-error.md
- autoplay-doesnt-work-in-chrome-or-vmix-v77.md
- low-frame-rates.md
- there-are-black-borders-around-the-video-in-obs..md
- virtual-camera-not-working-on-mac.md
- mics-volume-keeps-changing.md
- enable-camera-microphone-permissions.md
- fps-drop-if-app-not-in-focus.md
- surround-sound-error-when-screen-sharing-with-usb-headset.md
- relay-candidate-being-selected.md
description: >- When a relay candidate is selected, the connection is being forwarded (securely) via a hosted TURN relay server, rather than directly via peer to peer. This can add latency and limit the video quality
There's many reasons why one client might not be able to make a direct connection with another client, resulting in their connections being relayed thru a TURN server, or perhaps failing entirely. Being in relay mode can sometimes hurt quality, add latency, and use up limited Internet bandwidth.
Some common reasons, with some solutions, are listed below.
If on cellular, some cellular providers will configure the system to not support peer to peer networking or UDP-traffic. Some others will also throttle UDP-traffic, which is what VDO.Ninja uses, and they may stop the UDP-traffic entirely after a few seconds or moments.
- Use a VPN service, such as Speedify, and consider enabling TCP encapsulation mode if UDP throttling is an issue. If you host a VPN service yourself, perhaps near your studio host computer, you can minimize performance and latency concerns
- Change networks
A common cause is a browser setting or extension that is causing the issue.
- Try a different browser, such as Firefox, Chrome, or Edge
- Update your browser
- Try incognito mode
- Disable your browser extensions or disable security options; some can block WebRTC
- Allow IP leaking in your browser settings or extension
- Ensure WebRTC is not disabled in your browser
- De-Googled browsers or highly secured/privacy focused browsers can cause issues
- You are using Safari and rejected microphone permissions
These issues can be hard to judge, especially if they are issues on the remote guest's side
- Corporate firewalls blocking WebRTC or UDP traffic
- Ask your IT department for a solution, perhaps be given an isolated network space.
- Use a VPN, preferably something hosted close by to reduce performance issues
- Host your own TURN / STUN server, close to or within the corporate network, and specify it to be used within VDO.Ninja.
- pfSense firewalls will block WebRTC or UDP traffic.
- Modify your firewall settings to allow those two options.
- Symmetrical firewalls, such as with some fiber internet services, may cause issues.
- Contact your ISP if this is the case.
- You are using Safari and you have rejected the microphone permissions
- Safari, such as on iPhone, will require microphone permissions to allow private IP address sharing. Rejecting that will force the TURN servers into use.
- To avoid this, provide VDO.Ninja permissions to the microphone always, via the Safari settings.
- Strict security software installed
- Try from a different computer on the same network to see if its a local software issue
- If using WHIP / WHEP, some third party applications may not support NAT traversal, lacking STUN server support, as it can be a lot of adding coding work. In these cases, VDO.Ninja might use a TURN server to assist things along, but it's far from ideal.
- Host your own TURN server locally, and specify it in VDO.Ninja.
- Reach out to the developers / support staff and ask for help
- STUN servers are being block. The STUN servers are hosted by Google, so if they are blocked, TURN might be the fallback.
- You can specify your own STUN servers if needed via URL parameters
- Endless other reasons...
In the following example diagram. we see a Main Router, a travel router, smartphone, production laptop, and a gaming desktop.
An example diagram, for reference
The smartphone and the production laptop will be able to make a direct peer to peer connection, obtaining HOST candidates, since they are connected to the same router.
The gaming desktop however will struggle to make a peer to peer connection with the laptop on the other router, since they are on different networks. As a result, the connection might end up going thru the relay server, on the Internet, which is a disappointing result given the opportunity for a much better connection.
To fix such a scenario, some options:
- RECOMMENDED SOLUTION: Connect all devices to the main router instead.
- Or alternatively, remove the main router, and connect all devices to the travel router instead, if feasible.
- RECOMMENDED SOLUTION: Replace the travel router with an ethernet switch, and if needed, add a wireless access point for the smartphone to connect to.
- Enable and point the travel router's DMZ at the production laptop's local IP address; this makes the travel router transparent to the gaming desktop. Just be sure to disable the DMZ mode when done.
- Move all devices to the same router, using the main router or the travel router* for all devices.
*Assuming you connect the gaming laptop to the travel router instead, another issue might occur, and that is any VDO.Ninja user you try to connect to on the Internet may end up in relay mode with you. We can solve this issue potentially by putting our main router into bridge mode, which is often available as an option on cable modems in its gateway settings.
The recommended solutions have the benefit of ensuring all the clients, even clients on the Internet, can establish a peer to peer connection with any other client on the network. This wouldn't be the case for example if we simply used the DMZ mode, as the smartphone would not be able to connect to clients on the Internet in a direct p2p mode.
TCP 443 and 3478 UDP are the most important ports to have open, if behind a strict firewall. These allow for WebSockets, STUN, and TURN, but they alone will not allow for direct peer to peer traffic.
The actual media in direct peer to peer WebRTC (RTP/RTCP packets) is sent over random high-numbered UDP ports. These ports are negotiated by the ICE (Interactive Connectivity Establishment) process, which uses the STUN/TURN servers to help figure out how the peers can connect to each other.
If you want to allow peer to peer traffic, and are dealing with something more complex than a NAT firewall, like PFSense Firewall, UDP ports 49152–65535 are commonly suggested to opened to allow peer to peer traffic. You might need to open lower as well though, along with port TCP 443 and UDP 3478.
These high-numbered UDP ports used are dynamically chosen by the browser, and there isn't much control on VDO.Ninja's side to control that. Since you are also dealing with peer to peer mode, unless you know the IP address of each guest you intend to connect to, you can't easily unblock based on IP address either. This isn't the case if using a TURN relay server of course, but that's not direct p2p then.
Identifying which client is the problem can go a long way to troubleshooting.
Don't be afraid to try from different networks, computers, browsers, or other remote clients.
Advanced users can always just deploy their own TURN server locally or nearby, and specify it via VDO.Ninja. Hosting it yourself can reduce latency, improve performance, and improve security (no IP leaking). Using relay mode doesn't need to be a bad thing!
Join the Discord if still stuck and need help: https://discord.vdo.ninja
There are a variety of possible reasons for robotic audio distortion, either in OBS Studio, the browser, or with the system itself. Below is a list of different causes and solutions.
One user reported that their MyAsus-software had an AI Noise-Cancelling Speaker set to ON for default audio output device (depicted in the attached image). Switching the setting to OFF resolved the issue.
Another user found that starting OBS in Administrator mode fixed the issue. They noticed the issue more often when the OBS browser source was put into the background or minimized, so some performance / system priority setting may have been the cause.
OBS as well may have issues with the log file reporting "Max audio buffering reached!". Try to reduce your computer's CPU load, or perhaps consider upgrading to a newer computer. You can also try capturing the audio and video with the Electron Capture app instead of the OBS Browser source, which may avoid some issues with OBS browser source audio capture.\
Checking the audio sample rate on your system can help as well. High sample rates, like 384-khz for either the microphone or default system device may cause the issue. As well, a 32-bit audio sample rate, versus 16-/24-bit, may cause it as well. VDO.Ninja works best at 48-khz and either 16- or 24-bit. Users with FiiO audio DACs may encounter this issue, for example.
Very high packet loss may cause distorted audio as well. Adding &enhance&red
to the view/scene link may help, but chances are reducing the packet loss is your best bet instead. If using a VPN or behind a strict firewall that is forcing the relay servers to be used, address that if possible.
If using a virtual audio cable, or a pro-audio mixer, issues with audio buffers can cause clicking, but also perhaps audio distortion. Increasing the audio buffer with your virutal audio cable may help.
Surround sound headphones, like 5.1 / 7.1 Logitech/Corsair gaming headsets may cause disorted audio as well. Set the headphones and speakers to 2.0 stereo audio, disabing any surround sound effect, or perhaps change headsets.
Echo-cancellation can cause robotic audio effects, for example, having two tabs of VDO.Ninja open on the same computer can cause feedback loops that may be cancelling each other out. As well, having a mobile phone or a second computer near by that is also streaming into a VDO.Ninja group may create a feedback loop that also can result in echo-cancellation issues.
Some versions of VDO.Ninja may be more prone to issues than others. https://vdo.ninja/v23/ is an older version for example that you may want to try, but there are a variety of others. If you notice the robotic audio issue is version-specific, please report the issue on Discord (https://discord.vdo.ninja).\
Adding &noap
to the VDO.Ninja URL can disable web-audio processing in VDO.Ninja, and if a computer is heavily overloaded, disabling web-audio may help with robotic audio effects caused by audio buffer underruns.
Google Chrome's HWA setting
If the video preview when screen sharing is black, try disabling or enabling the browser's hardware acceleration. This can be found in the Google settings -> system menu.
If sharing a Netflix, Prime Video, or other content that is protected by content-protection, such as DRM/HDCP, the screen share may be black also. You can try screen sharing using the window, display, or tab methods to see if one works where the others fail, or you can try display grabbing with OBS Studio instead, but VDO.Ninja itself doesn't offer methods intended to bypass content copy protection.
description: >- Some surround sound headphones can cause VDO.Ninja to have audio problems, including failed screen sharing
Surround sound or multi-channel audio, for either the microphone and audio playback device, can cause audio problems with the browser. For example, screen sharing may trigger an unreadable error, mentioning surround sound as a likely cause.
Unplugging or using a different USB headset in this case can often solve the issue.
Another option is to disabling surround sound in the Windows, or typically, the Logitech/Corsair settings. By limiting audio playback to stereo 2.0 channels, you can avoid complications encountered with surround sound playback or capture not properly being converted to something the browser understands. How to do this might depend on your audio device or the driver it uses.
In one past Reddit post, someone mentioned going to chrome://flags/ and turning off Override software rendering list fixed their issue. I've not been able to test or confirm this though, since I do not have surround sound headphones.
For Logitech surround headphones specifically, the following old Reddit post mentions a fix for problematic surround sound and Chrome, along with a fix. I think this might have worked for one VDO.Ninja user in the past, but it's been a couple years now. Perhaps also update your drivers.
{% embed url="https://www.reddit.com/r/LogitechG/comments/f04vuz/logitech_g_pro_x_dts_surround_sound_is_horrible/" %}
Another possible fault is that the audio quality in Windows is too high; 384-khz or 32-bit audio may cause issues, for example. You might also have issues with ASIO-based drivers, DSD systems, and multi-channel audio systems. In these cases, set the audio output and microphone input in Windows to at most 24-bit at 48-khz stereo; VDO.Ninja doesn't typically offer better audio quality than this anyways.
Looking at the code, this error message is triggered when "NotReadableError" is reported by the browser, I think when screen sharing with audio. So, I suppose you can also screen-share without audio maybe, and then perhaps select a virtual audio device for the audio after the fact instead if you still need a window's audio. However, this is cumbersome to do.
Google or such might offer a solution as well, since this probably isn't a VDO.Ninja-specific issue. That said, you can try adding &inputchannels=2
to the guest/push links, to see if that helps at all. But beyond that, I'm not sure this can be addressed via VDO.Ninja's code itself.
If a black border appears around the video, check that the custom CSS settings in the browser source has not been modified from the default setting:
body { background-color: rgba(0, 0, 0, 0); margin: 0px auto; overflow: hidden; }
If you changed the default CSS settings, then you'll need to change them back to get rid of any background.
Also, ideally the width/height in OBS Browser source should be the same aspect ratio as the video. 1280x720 (not 800x600) This will fit the window to the video.
original issue thread: Reddit: Advice on adding to OBS
An iPhone 5s /w iOS 11 (or newer) is the technical minimum requirement for VDO.Ninja, as Apple's webKit lacks the proper webRTC support in older iOS versions. Older iPhones/iPads can't update to newer iOS versions, so they are out of luck. iPhone 3G, 3Gs, 4, 4s, and iPhone 5 are not supported as a result, and many older iPads are also not supported.
I'd strongly recommend at least iOS 16 be used either way, as older versions of iOS have serious limitations and bugs. Starting with iOS 13 things started to be at least usable though, so an iPhone 6s is the recommended minimum, but don't expect a bug-free experience.
If using the native iOS app of VDO.Ninja, while I used to support iOS 11 with it, newer releases of the native app may require a newer iOS version. If using an iPhone 6 for example then, while it may not work with the native app, it might still at least work with the Safari web-app version.
Older Android phones tend to work usually though, as I think Google added support for WebRTC earlier on than Apple did, but you might be limited in terms of maximum quality or face heat issues on such old phones.
If the stream or camera freezes after a while, there could be many reasons. Let's explore some causes and solutions below.
If cycling the camera to a different camera, or refreshing the camera via the settings menu, fixes the issue, then this normally implies the issue is with the camera or its USB connection.
As a stop-gap solution, the director has the remote control ability to toggle the camera of a guest to unfreeze it. This can be done without the guest's permission even if the &consent
flag is added to the guest's URL ahead of time. In a pinch, this can at least give the director some comfort to go live, fixing any stuck camera within a few seconds themselves, versus asking the guest to refresh their page.
If not using a group room, the publisher of a stream can also refresh their own camera via the settings menu, and clicking the refresh icon next to the camera.
To fix the problem though, a bit of troubleshooting may be needed. More often than not, if using a USB 3.x camera, the cause is a USB-related issue.
- Try a different USB 3.0 cable; ideally a short cable that conforms to the USB 3.1 specification or newer.
- Do not plug any USB camera into a USB hub, dock, or use it alongside other high-bandwidth USB devices.
- Try a different USB port; try them all if needed; a blue USB 3.0 port is normally required.
- Reduce the frame rate and/or resolution of the camera. Lowering the bandwidth over the USB connection may help. 1280x720 @ 30fps is recommend trying, if possible.
- Update the drivers on the computer, especially those for the USB controller and camera. Update the operating system as well, if needed, re-installing old drivers if possible.
- If using an AMD motherboard, update the BIOS of your motherboard, and perhaps set your PCIe lane speed to Gen3, instead of Gen4.
- If using a laptop in particular, ensure the USB port is not set to go to sleep; this would be a Windows setting. Also, enabling Performance Mode and being plugged into the wall, may help as well. See the below images:
If the issue is not fixed by toggling your camera, make sure your internet connection is stable and you're device is not overloaded. Bad connections, network firewalls, or VPNs can cause the video to lose connection and then reconnect, causing the picture to appear to freeze for several seconds or longer.
VDO.Ninja requires a solid Internet connection with no interfering services to work its best. On some networks, especially during prime-time evening hours of the day, connections can drop out for seconds at the time constantly.
Mobile devices may also have the video freeze for a few moments at a time if switching between cellular networks and WiFi networks, but in these cases things will auto-reconnect within a few seconds normally.
Services like https://speedify.com can offer a VPN with bonding, designed for streaming, and it can help avoid network issues on mobile networks, where IP addresses or wireless connections constantly are changing.
Regarding mobile, iOS users can only send video to 3 viewers at a time if using the H264 hardware encoder. Newer versions of VDO.Ninja will try to keep track of how many H264 streams are being used, and revert to VP8-software-based encoding when the hardware encoders are maxed out, however VP8 encoding can cause iPhones to get very warm. If forcing H264 with an iPhone or iPad, and you max them out, you might cause videos to freeze or go black though.
View links and scenes can sometimes can use an iPhone H264's encoder, even if the video isn't visible in OBS. If having issues, try to avoid forcing the H264 encoder or using it sparingly for only the active sources. If using &broadcast
mode, only the director and scenes could possibly contribute to using an H264 encoder; other guests won't have access to the guest's video stream, so they won't count towards this H264 encoder total.
Some Windows computers that can offer H264 hardware encoding with AMD or Nvidia GPUs run into the same limitations that an iPhone device may have. That is, if more than 2 or 3 video streams are being published that use H264 encoding, the hardware encoder on those devices may fail.
If someone if using OBS to publish H264 video via RTMP using Nvidia's NVenc, while also publishing H264 video to VDO.Ninja, conflicts may arise, and video streams may fail. This shouldn't happen really, but in theory, it's something to be aware of.
{% hint style="info" %} Update: This issue of rainbow puke impacted OBS v25 and older, but is no longer an issue for most users.
If having issues with the video being very low quality, this is often due to high packet loss caused by weak WiFi or other network issue. More info: https://www.youtube.com/watch?v=je2ljlvLzlY\
{% endhint %}
{% hint style="warning" %} DO NOT USE WIFI. Have everyone connect to stable wired Internet whenever possible. {% endhint %}
"Pixelation" (as seen here: https://imgur.com/oKEPOvu) is a difficult issue to troubleshoot as there are several potential upstream configurations which can ultimately lead to high packet loss which is the primary cause. Here are some potential fixes and configurations that may assist in lowering packet loss:
- Change the video codec or video encoder used: h264, VP8, and VP9 are options. VP9 seems to handle packet loss the best within OBS, but it also creates the most CPU load. VP8 handles packet loss the worst in OBS.
- Use Speedify.com (in AUTO or TCP mode).
- Use the Electron Capture app instead of OBS to capture video. The Electron Capture app uses a newer version of Chromium, which works far better than OBS when dealing with packet loss related issues.
- Lowering the framerate or resolution, especially for those using H264, can provide smoother video, and perhaps with less distortion.
- You can increase the jitter buffer size by using the
&buffer
URL parameter; such as "https://obs.ninja?view=abs&buffer=300". This only works if using Chrome/Chromium v76 or newer though; OBS v25 currently uses Chromium v75 and so is not yet compatible. - You connect two peers via TCP, instead of UDP, which will ensure there is no packet loss. This option is for more advanced users and requires a compatible TURN server (or VPN). Please use your own TURN servers for this option if so, as the bandwidth costs can be quite high for me.
- You can scale down the video while viewing with
&scale=50
to potentially reduce stutter and reduce the frequency of frame corruption. - Normally the video should "fix itself" after a moment of so, but if not that is likely a bug in the browser used for decoding. If in OBS you can toggle the visibility of the element to try to trigger a resolution. I've also provided a "SEND KEYFRAME" button in the hidden stats menu that lets the publish do this from their end.
- Mentioning this again, but connect over wired ETHERNET if possible and avoid wireless connections, including WiFi networks. DSL connections are also often quite poor. Do so for both OBS and the video-connected device for optimal results. Even 4G LTE is better than Wi-Fi in many cases.
- Do not watch a 4K Netflix or Youtube video while streaming; it will increase network congestion and can cause packet loss and buffer-bloat.
- If you have LOW QUALITY video, or low resolution or low bitrates, that perhaps can be adjusted. Please see below re: bitrates and resolutions
- Ensure your computer and remote computer are not maxing out their CPU power. If they are, have them lower the resolution and bitrate.
description: >- If the OBS Virtual Camera is not appearing in Chrome or your browser after installing OBS on MacOS, you may need to enable screen recording permissions
If using OBS Virtual Camera or other virtual camera on MacOS (Apple) system, please note that there are a list of applications that are not supported.
- Bluejeans Events
- Safari
- Tencent Meeting
- FaceTime
- Photo Booth
Please see the follow official guide for more details on these and other problematic apps.
{% embed url="https://obsproject.com/wiki/MacOS-Virtual-Camera-Compatibility-Guide" %} Official documentation {% endembed %}
If using Windows or if you have just installed OBS, please restart your browser fully or restart the computer first, to ensure its properly loaded and available to all applications.
The Google Chrome usually works with most virtual cameras. If you are having problems with it, you can also try another browser.
Please also be sure to START the virtual camera before selecting or opening it in VDO.Ninja. If you open it in VDO.Ninja before starting it, the resolution and/or frame rate may be wrong.
If the OBS Virtual Camera is not appearing in Chrome or your browser after installing OBS on MacOS, you may need to enable screen recording permissions.
-
Open your System Preferences; you can find this via the Apple logo in the top left corner of your desktop.\
-
Click Privacy & Security and then Screen Recording.\
-
For OBS, enable the permission.
If OBS isn't listed, click the + button, enter your system's password, and navigate to OBS in the Application settings. Select it and enable.\ -
Quit and relaunch OBS.\
If OBS isn't listed, press the + button, navigate to it, and select it
vMix is a great studio mixer, although some users find the CPU load can get a bit high at times. Below are some options that might help to reduce that load, with solutions generally targetting vMix, but could perhaps be applicable to other studio mixing software.
- Browser sized at 1920x1080 can stress vMix out; try 1280x720 or lower to reduce the total load.
- Ensure GPU hardware acceleration is enabled; particularly for the browser source.
- Using the H264 codec may reduce CPU; adding
&codec=h264
to the view link may help. - Disabling de-interlacing, sharpening, or aliasing of the browser source might free up some load.
- Electron Capture or Vingester.app can be used instead of the vMix browser source; they can use window capture, which can reduce the CPU load.
- If you have a spare computer, Vingester.app has a VDO.Ninja to NDI output option, which can perhaps help with distributing load if the browser source is causing issues.
- Lowering the frame rate of the browser source and incoming VDO.Ninja videos might help reduce CPU load.
&maxframerate=30
, for example, on the guest link can help cap the frame rate. - The director of a room can adjust settings of incoming videos via the video settings options under advanced settings. This includes the max resolution, frame rate, and aspect ratio of incoming videos.
- Updating your graphics card drivers can sometimes help.
- If acting as a VDO.Ninja director, consider hosting the director on a different computer than vMix. If not possible, consider using
&meshcast
with the director's link to use&meshcast
to help reduce the CPU load when in larger group rooms. - Try to use your local camera as a source in vMix, rather than bringing your local video into vMix with VDO.Ninja. Using a virtual camera, like Snapcamera, OBS Virtual Camera, Manycam, or such can allow a webcam to be accessed using the browser and vMix at the same time.
- Avoid using multiple group scene link, unless solo-view links. Instead, consider using the VDO.Ninja mixer app to use a single group scene link, switching between different layouts using the mixer interface. (The Mixer app is relatively new, as of May 2022, so still undergoing feature enhancements).
There are additional other options available to reduce CPU / GPU / Network load when using VDO.Ninja; this list is specific to vMix issues.
description: >- Some laptops will put the webcam to sleep for a moment to save power, causing freezing
If using a laptop with a USB camera, it's possible the the system is putting the camera to sleep for a split second; just enough to cause the video to freeze. This is definitely a possible cause if on a laptop, but might not be an issue for a desktop user. Enabling performance mode in the Windows power options might help things, but you can also disable USB power savings selectively.
One place to is in the Windows Power Options settings, which you can find in the Power and Sleep settings pane.
You can also try disabling the "Allow the computer to turn off this device to save power" options in the Windows Device Manager for each USB device/host controller. (uncheck them)
If the problem isn't resolved, you can still reload the camera with the refresh button in the VDO.Ninja settings menu when it happens. This just reloads the camera and should fix the problem until it happens again.
The director of a room can also refresh a camera remotely of a guest, when it freezes, via the video settings of the guest.
If it's a common occurrence, you can load the camera into OBS or SnapCamera and then bring the video into VDO.Ninja as a virtual camera device. While VDO.Ninja does try to automatically reconnect devices when they become disconnected, it sometimes isn't alerted by the browser that the camera has glitched. OBS or Snapcamera might handle these conditions better.
Another reason for a camera freezing randomily is that it may be a bad USB 3.0 cable or a USB 3.0 hub that is overloaded with other USB devices already. Plug any camera directly into the back of the computer, on a dedicated USB 3.0 port, with a high quality USB 3.0 or better cable. Unplug other unneeded USB devices.
If this doesn't work, it probably isn't related to your camera, and may be instead related to your network.
For more reasons why a video may freeze during a stream, see the following:
{% content-ref url="video-freezes-mid-stream.md" %} video-freezes-mid-stream.md {% endcontent-ref %}
The Screen sharing feature is highly dependent on the operating system of the device whose screen you are trying to capture.
- Chrome browser used on a PC is most compatible, fully supporting screen sharing with audio.
- Firefox on PC supports screen sharing, but it cannot screen share with audio.
- Safari on iOS does not yet support it officially, although it does support it with the "technical builds" designed for developers. Until Apple officially supports, there isn't much I can do there easily.
- Android does not support it and it is doubtful that it will in the near future.
In either case, you can use Native mobile apps to solve this problem, as the native apps let you screen share using iOS and Android. However, the native apps are pretty basic right now, and may lack many features and may even lack system-audio capture.
There's other tricks as well to get screen sharing working on mobile, such as using Quicktime via USB.
{% content-ref url="../steves-helper-apps/native-mobile-app-versions.md" %} native-mobile-app-versions.md {% endcontent-ref %}
{% content-ref url="../guides/screen-share-your-iphone-ipad.md" %} screen-share-your-iphone-ipad.md {% endcontent-ref %}
When using 4G or 5G Internet, some network providers have firewalls or network routing settings that make it very hard to establish direct peer to peer connections with others.
If a director of a room, you may see guests join and then disconnected repeatedly, with video and audio never actually showing. This means the peer connection has failed, and is constantly retrying. The issue should go away though if the guest user changes networks; switching to WiFi for example or a different ISP provider.
VDO.Ninja uses TURN servers to bypass most 4G-related network issues, offering solutions to network traversal, TCP, UDP, and IPv6 routing issues. Sometimes, in rare cares, even this isn't enough.
There are solutions usually.
- One option is to try adding
&privacy&tz=-60
or&privacy&tcp&tz=300
to the guest's URL. This attempts to force the TURN servers into action, with a couple different configurations set. Sometimes, especially in the case of active firewalls, this can fix the issue. - Using speedify.com on the mobile device often will solve the problem. It's a paid service that's free to try, but it's well worth buying if it works. It creates a VPN designed for live video that solves many issues mobile 4G devices commonly face.
- If you're an advanced user, setting up your own TURN server that is tweaked to your specific scenario and problem is an option. Please do let me know what works for you in this regard though, as I'd be keen to add such support to VDO.Ninja's TURN network also.
{% hint style="info" %} Please note, if you have self-deployed VDO.Ninja onto your own servers, it becomes your responsibility to deploy your own TURN servers or purchase TURN services from a third-party. Any TURN server access provided currently by VDO.Ninja for private deployments is out of generosity and isn't a guaranteed service. {% endhint %}
Director Option! (&director
)
&cdv
Hides the invite URL options in the Director's control center.
Allows for a cleaner looking interface. Useful if using IFrames maybe.
{% content-ref url="../viewers-settings/director.md" %} director.md {% endcontent-ref %}
{% content-ref url="../advanced-settings/design-parameters/cleanoutput.md" %} cleanoutput.md {% endcontent-ref %}
{% content-ref url="../advanced-settings/design-parameters/cleanish.md" %} cleanish.md {% endcontent-ref %}
description: >- Allows assistant directors to have access to the director's room, with a subset of control
Director Option! (&director
)
&directorpassword
&dirpass
&dp
Example: &codirector=DirectorPassword
Value | Description |
---|---|
(no value given) | the site will prompt you for a password on load |
(alpha numeric value) | password for the directors |
The basic idea is there is a URL parameter called &codirector
that you need to add to all the director links used.
For example, https://vdo.ninja/?director=MYROOMNAME&codirector=DirectorPWD123
So long as all the directors have &codirector=DirectorPWD123
added to their URLs, they all share a common director's password, and so they all treat each other as valid directors.
If the passwords don't match, the first director into the room will be the real director, and the others will be rejected.
If you don't enter a password via the URL, the site will prompt you for a password on load.
Using this flag, the director can set a director's password (or prompt the user for one). Any other director that joins the room, who also has a matching director's password set, will be granted co-director controls.
A co-director has nearly all the same controls and powers as the main director, except they cannot control the main director, nor kick them out of the room. They also have a few features unavailable to them at present, such as solo-talk, as those currently would conflict with the main director's ability to use those features.
The first director to join the room is the main director, and so their password is the 'correct' password.
A co-director cannot force-disconnect the main director.
If the main director does not have &codirector={somepassword}
in their URL, nor enabled co-director mode via the room-settings menu, then remote co-directors will not be able to join.
{% hint style="info" %} The co-director mode is still evolving, and certain things like shared-state between all the directors may still be missing.
Starting with v20 of VDO.Ninja, a co-director invite link will be available via the room settings button, along with the option to customize permissions. {% endhint %}
You can also enable the co-director mode by checking the "Add co-directors .." option in the room settings menu. This will provide you a link with the &codirector
invite link already generated.
This will only work while the check-box is selected, so be sure to re-enable it if reloading the page without &codirector
added to your own link.
Do not confuse the room password with the director's password; if they are the same, you potentially allow a mischievous guest to have access that they should not have.
Co-directors will not be able to join as co-directors unless the main director has enabled the co-director option via the room setting's checkbox or by having a matching &codirector=xxx
parameter in their own link.
If the main director leaves and re-joins, or a new director joins, all the co-directors will need to be re-checked. It's possible that a network outage could have a co-director and the main director to switch roles, depending on who re-connected.
If you copy and paste the main director's URL to a new browser/tab, be sure to remove the &push=STREAMID
portion of the URL. If you do not, you will get an error about the stream ID being already in use. Each co-director and guest needs their own unique stream ID.
If using the &queue
parameter with co-directors, you may need to use &view=STREAMID
to allow the co-director to bypass the queue, else they won't be able to be validated since they will be stuck in the queue. There is more info about this in the queue's documentation.
{% content-ref url="../viewers-settings/director.md" %} director.md {% endcontent-ref %}
{% content-ref url="../advanced-settings/director-parameters/and-hidecodirectors.md" %} and-hidecodirectors.md {% endcontent-ref %}
{% content-ref url="../advanced-settings/director-parameters/and-maindirectorpassword.md" %} and-maindirectorpassword.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&remotemidi
Example: &midiremote=4
Value | Description |
---|---|
(1 to 4 ) | reference &midi 's values |
This lets you route all MIDI messages from one computer to another computer, with the purpose of remote triggering the VDO.Ninja hotkeys.
https://vdo.ninja/beta/?midiremote=4&director=ROOMNAMEHERE
https://vdo.ninja/beta/?room=ROOMNAMEHERE&midiout=1&vd=0&ad=0&push&autostart&label=MIDI_CONTROLLER
&midiremote={reference &midi's values; 1 to 4}
See &midi
for a link to the page with more information on available hotkeys.
{% embed url="https://www.youtube.com/watch?v=rnZ8HM9FL4I" %} How to remote control with MIDI {% endembed %}
{% content-ref url="../midi-settings/midi.md" %} midi.md {% endcontent-ref %}
Director Option! (&director
)
Example: &rooms=room1,room2,room3
Value | Description | |
---|---|---|
(string value) | adds the rooms to the guest transfer buttons to the director control bar (comma separated) |
https://vdo.ninja/?director=ROOMID&rooms=ROOMID2,ROOMID3,ROOMID4
The link above would add "ROOMID2", "ROOMID3", "ROOMID4" guest transfer buttons to the director control bar.
Pressing any of these buttons will arm the transfer buttons beneath each caller with the chosen room name, allowing callers to be quickly moved from one room to another.
Arming can be disabled by clicking the room name again. If the current room is in the list it will be ignored.
{% hint style="warning" %}
If &cleanoutput
is enabled, rooms parameter is ignored.
{% endhint %}
{% content-ref url="../general-settings/room.md" %} room.md {% endcontent-ref %}
{% content-ref url="../getting-started/rooms/" %} rooms {% endcontent-ref %}
{% content-ref url="../getting-started/rooms/transfer-rooms.md" %} transfer-rooms.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&groups
Example: &group=Groupname
Value | Description |
---|---|
1 | adds the guest or director to group 1 |
2 | adds the guest or director to group 2 |
3,4,5,6 | adds the guest or director to group 3, 4, 5 and 6 |
(string) | creates/adds the guest or director to a custom group |
The idea is, you can put guests of a room into sub-groups. When added to a sub group, those guests will only be able to see and hear others in that same sub group.
Guests can be assigned to multiple subgroups. Groups can be specified via the URL using &group=1,5,6
or/and the director can dynamically assign sub-groups, as seen in the below image.
If not in a group, that guest will still see/hear everyone, regardless of which group they are in, even if a guest in another group may not be able to see/hear that guest back.
Scenes can be put into groups as well, via the URL group option, such &group=3
, but the director will not be able to dynamically change which group a scene is in. Not yet at least.
Using this group function is an alternative to transfer rooms, however it's perhaps less secure, as a guest could just tinker with their URL parameters or just refresh their page to perhaps see everyone in the room again.
&groupaudio
can be used to enable audio in-between different groups, instead of audio being group-specific. Useful for blind-dating show formats or such.
Custom groups used by remote guests now show in the director's view, just like custom scenes do. If you use &groups=group,test,vdo
, new group buttons will appear.
With &groupmode
added to your URL, when not assigned to a group, you don't hear or see anything. This also goes for remote participants who are not in a group - you will not see or hear them if they are not in a group, even if you also are not in a group.
{% content-ref url="and-groupaudio.md" %} and-groupaudio.md {% endcontent-ref %}
{% content-ref url="../advanced-settings/setup-parameters/and-groupview.md" %} and-groupview.md {% endcontent-ref %}
{% content-ref url="../advanced-settings/setup-parameters/and-groupmode.md" %} and-groupmode.md {% endcontent-ref %}
{% content-ref url="../director-settings/rooms.md" %} rooms.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&ga
This just enables the guest or scene to not filter out audio streams that are contained in other sub-groups.
By default a stream assigned to one group won't be visible or audible to those in another group. &groupaudio
prevents audio from being filtered, but keeps the video filtering in place.
{% content-ref url="and-group.md" %} and-group.md {% endcontent-ref %}
{% content-ref url="../advanced-settings/setup-parameters/and-groupmode.md" %} and-groupmode.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
Example: &icefilter=tcp
Value | Description |
---|---|
tcp | Filters TCP ICE candidates |
udp | Filters UDP ICE candidates |
host | Filters HOST ICE candidates |
Filters out ICE candidates that do not include the specified word in the candidate string.
Added for advanced use-cases and testing purposes.
{% hint style="warning" %} This is an advanced parameter that can stop your links from working correctly. {% endhint %}
General Option! (&push
, &room
, &view
, &scene
)
This does not hide the mouse cursor for Chrome-based screen capture, as Chrome does not yet support that. This feature is designed for hiding the mouse when using the Electron Capture app, to avoid mousing over the capture area by accident.
Works better in Windows than on macOS, due to OS-level limitations.
If you're looking to hide the cursor while screen-recording, consider using OBS to capture and OBS Virtual Cam as the source into VDO.Ninja. You can also check out: https://github.com/rdp/screen-capture-recorder-to-video-windows-free as an option to turn a screen into a virtual camera without needing OBS.
{% content-ref url="../common-errors-and-known-issues/cursor-shows-when-screen-sharing.md" %} cursor-shows-when-screen-sharing.md {% endcontent-ref %}
{% content-ref url="../source-settings/cursor.md" %} cursor.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&private
&privacy
Forcing relay mode is provided for testing and emergency purposes. It will typically increase latency; sometimes by a lot.
Alternatives to relay mode include:
- Using wired Ethernet instead of Wi-Fi will also reduce packet loss.
- A VPN service, like Speedify, will likely be better than using a TURN server.
Uses of relay mode include:
- Can potentially reduce packet loss with some guests on bad connections.
- Some peer to peer connections over residential networks struggle, and introducing a relay server can help avoid those issues.
- Has the advantage of hiding your IP address from peers.
You can deploy your own TURN server if intending to use this feature a lot or needing more bandwidth.
Please feel free to donate to VDO.Ninja to help support the provided TURN servers.
Currently TURN servers are deployed numerous countries around the world.
Ports that a TURN server may use include 443, 3478, and potentially others.
{% hint style="info" %} More information on what TURN is here {% endhint %}
If using &privacy
on the URL (using TURN server), with the intent being to hide your IP address, a page will prompt you if an IFrame tries to load, asking if you wish to continue.
Using &relay
will not do this behavior, despite using the turn server none-the-less; so &privacy
is evolving to be a bit more strict than &relay
alone.
It will even show if loaded into OBS, as privacy trumps there. (IFrames can steal IP address, etc.).
You can also just use &nowebsite
, to disable IFrames from loading at all (always existed as an option).
Certain known sites are excepted; YouTube, Twitch, Vimeo, etc. will not ask for confirmation.
{% content-ref url="turn.md" %} turn.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
Adding &stats
to a URL shows the connection/media stats window.
On desktop, you can hold CTRL
(or CMD
) and Left-Click
a video to get its stats.
On Version 22 you can Right-Click
-> Stats on a video feed to get its stats.
On mobile, you can just rapidly touch the display to trigger the stats window instead.
The &stats
URL parameter is for those like vMix users who might not be able to interact with the browser source.
General Option! (&push
, &room
, &view
, &scene
)
Forces TCP mode if connected to a TURN server.
Versus the default, which may be UDP or TCP.
{% content-ref url="turn.md" %} turn.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&osc
Example: &api=SomeAPIKey
Value | Description |
---|---|
(key) | API KEY to control VDO.Ninja remotely |
You can use this parameter to enable the HTTP/WSS remote control API for VDO.Ninja. You pass a API KEY value to the parameter, and if it matches the remote control's API KEY, then the remote control interface will be able to send commands to your VDO.Ninja session.
You can control guests in the director's room, or you can control your local microphone and camera, as examples.
Please see https://github.com/steveseguin/Companion-Ninja for documentation and details of this command. There is a module for Bitfocus's Companion available, along with HTTP and WSS API endpoints.
Please see https://companion.vdo.ninja for a sample interface to test this command out with. The Companion module is available here: https://github.com/bitfocus/companion-module-vdo-ninja
{% content-ref url="../guides/hotkey-support/" %} hotkey-support {% endcontent-ref %}
{% content-ref url="../guides/hotkey-support/how-to-control-vdo.ninja-with-touch-portal.md" %} how-to-control-vdo.ninja-with-touch-portal.md {% endcontent-ref %}
Sender-Side Option! (&push
)
&cb
&chat
Example: &chatbutton=0
Value | Description |
---|---|
0 |
hides the chat button |
1 |
shows the chat button |
Adding &chatbutton=0
or 1
hides or shows the chat button on the control bar.
{% content-ref url="../viewers-settings/nomicbutton.md" %} nomicbutton.md {% endcontent-ref %}
{% content-ref url="../viewers-settings/and-novideobutton.md" %} and-novideobutton.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&deaf
Audio playback is muted in VDO.Ninja. If you just want to mute the speaker button temporarily use &mutespeaker
.
{% content-ref url="../source-settings/and-mutespeaker.md" %} and-mutespeaker.md {% endcontent-ref %}
{% content-ref url="../advanced-settings/view-parameters/noaudio.md" %} noaudio.md {% endcontent-ref %}
{% content-ref url="../advanced-settings/video-parameters/and-blind.md" %} and-blind.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&l
Example: &label=Steve
Value | Description |
---|---|
(no value given) | It will prompt the user for a Display Name on load |
(string) | Sets the label for the guest/browser tab |
TITLEn\SUBTITLE |
Multiple lines |
&label
sets a display name label to the stream ID.
- Uses the label in OBS Studio if dragging the link into OBS Studio.
- Will change the name of the Browser tab to the Label specified.
- Shows up in the connection debug Stats window.
- If left blank, it will prompt the user for a Display Name on load.
- You can use
&showlabels
to show the labels in the video sources.
Until I figure out a better way of doing this, I've enabled a way to have a display name be on multiple-lines in VDO.Ninja.
&label=DisplayNameHere\nSubtitleHere
Note the use of as a line break ie:
https://vdo.ninja/?label=Steve_Seguin\n(he/him)\nhttps://twitch.tv/vdoninja&push=JaAiVEH
https://vdo.ninja/?view=JaAiVEH&showlabels
So it's not super obvious how to do this currently, so I think the next goal will be to add the option to let a guest enter their own sub-title, etc, when joining, using dedicated input fields. But until then, I hope this still helps. You can stylize the sub-label within OBS's CSS section, targeting the following CSS, but please note I'll probably be tweaking the CSS/HTML as well in the future:
.video-label>span:nth-child(2) {
font-size: 50%;
display: block;
text-align: center;
}
{% content-ref url="../advanced-settings/design-parameters/showlabels.md" %} showlabels.md {% endcontent-ref %}
{% content-ref url="../newly-added-parameters/and-screensharelabel.md" %} and-screensharelabel.md {% endcontent-ref %}
{% content-ref url="../advanced-settings/setup-parameters/and-labelsuggestion.md" %} and-labelsuggestion.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&noap
&noaudioprocessing
disables the web-audio audio processing pipelines of both inbound and outbound audio. This is not the same as disabling echo-cancellation, denoise, or auto-gain; those are not web-audio-based.
Disabling the web-audio processing pipeline can help reduce audio distortion, clicking, and some echo-cancellation issues, especially if your CPU is overloaded.
The web-audio pipeline is like a chain of audio-plugins, loaded into Javascript, which does custom audio processing. This includes the low-cut filters, limiting, compression, audio-visualizers, active-speaker, director-side gain and mute control, and more.
This audio pipeline can start to have problems though if the CPU is overloaded. This can result in odd issues, including clicking. This pipeline is disabled by default in scenes, but it's usually enabled by default for most guest types.
{% hint style="warning" %} Disabling audio processing will disable many features, such as audio-visualizers, gain control, and loudness-monitoring API functions.
The ability to remotely mute a guest as a director (along with &audiogain=0
) will not work if audio processing is disabled.
{% endhint %}
General Option! (&push
, &room
, &view
, &scene
)
Example: &pie=YourPiesocketAPIKey
Value | Description |
---|---|
(API_KEY) | the only parameter is your own piesocket.com API key |
Third-party handshake-server service option. If using piesocket, you can just do &pie=APKKEY
to use that service, without deploying any code or servers yourself.
{% hint style="warning" %} At the time of originally adding this feature, PieSocket was a free service. That has since changed (Dec 2021). VDO.Ninja is not affiliated with PieSocket and never has been. We have no recommendation on whether you should use them or not.
For a free handshake-server though, please instead consider hosting your own on Google Cloud or Amazon AWS with a free micro-server instance. The following server code is compatible with VDO.Ninja: https://github.com/steveseguin/websocket_server {% endhint %}
Director and/or Sender Option! (&director
, &push
, &room
)
&queue
lets the room's director review guests who join a room.
The option can be used in one of two ways; either as a powerful screening room or as a simple approval system, depending on if the &queue
option is also used on the director's URL.
{% embed url="https://www.youtube.com/embed/DDJrhhdNX_c" %}
{% hint style="info" %}
&queue
was changed in v24 to not allow the guest to see the director's video, until the director activates the guest with their pink activate-guest button. Otherwise, it's the same as before. Use &screen
for the old version.
{% endhint %}
If used on the director's URL, as well as the guest's URL, guests are added to a queue as they join, and the director can connect to those guests with a button in their lower control bar. This feature prevents the director's computer from being overwhelmed with connections.
The guests will not be able to see anyone, until they are transferred or approved. Once approved, the director will be able to see them, and they will be able to see the director.
Guests can be disconnected and they can then rejoin the queue, but when they do they will be at the end of the queue again.
This system can support hundreds of guests in queue, but it is not advisable to use this system if you expect thousands of guests to join.
{% hint style="info" %} Looking for feedback! {% endhint %}
The &queue
option can be added to both the director URL and the guest URL, or just the guest's URL.
Example director link:
https://vdo.ninja?director=roomname&queue
Corresponding room link:
https://vdo.ninja/?room=roomname&queue
When &queue
is added both the guests' links and director's link, there will be a new 'wait list' button added to the director's view, which when pressed, will load the next guest in queue in the director's room. The guest will be able to see the director and only the director then.
The director can add more guests this way, kicking out those they don't want, and continue to cycle thru the queue of guests as they join the room. This setup is designed as a screening room, where the director is expected to transfer the guests to the main production room when appropriate.
When transferred, the guest will no longer be considered in 'a queue' and will be able to see everyone in the new room they were transferred to, and vice versa. The guest will not know which room they were transferred to, and will be unable to rejoin without joining the queue again. You can use the "change URL" button in the director's room if you wish to permanent-transfer a guest to a new link.
This setup is ideal for when dozens or hundreds of guests may try joining a room. The director can load a few guests at a time, preventing their system from being overloaded. Relying on a transfer room prevents the main room from being attacked as well.
When &queue
is added to just the invite link for a guest, and not added to the director's link also, the guest will auto-load for the director, and only for the director. There is no wait-list.
The director will have a button for each joined guest titled "Activate Guest", which will pressed, will accept the guest into the current room as if a normal guest. They will see other activated guests in the room, without needing to be transferred to another room.
This approach to just adding &queue
to the guest invite links, and not putting the room itself into a screening room, is well suited when you are only expecting just a few guests to join, and not dozens or hundreds, since the director will auto-load the video of each guest who joins.
Since it's possible for a user to just remove &queue
from their URL when joining, bypassing the need for activation, this method is considered less secure versus the use of the screening room where users are transferred to the main room instead.
As a director, you can use &view
in the URL to specify stream IDs that you wish to connect normally, bypassing the queue.
For example:
https://vdo.ninja/?director=MyRoom123&codirector&queue&push=mainDirector123&view=coDirectorStreamID123
https://vdo.ninja/?director=MyRoom123&codirector&queue&push=coDirectorID123&view=mainDirector123
The above links allows a co-director join the room, despite the main director and co-director being in queuing-mode. By specifying each other's stream ID as a listed view value, they can both bypass each other's queue together.
&view
can accept a list of stream IDs. When in &queue
mode, &view
allows connections to join that are not listed, but only if they are brought in via the queue. This makes it a bit of a special case for &view
, where it otherwise is pretty strict about who connects or not.
The "queue" mode, when applied only to the guest-link, has been extended with new options. These modes do not apply when you have &queue
also on the director's link, however, rather just when added to the guest-invite link only.
These options might be appealing for screening guests when either you don't want to use a transfer room or don't expect too many guests to be in queue.
{% content-ref url="../advanced-settings/guest-queuing-parameters/and-screen-alpha.md" %} and-screen-alpha.md {% endcontent-ref %}
{% content-ref url="../advanced-settings/guest-queuing-parameters/and-hold-alpha.md" %} and-hold-alpha.md {% endcontent-ref %}
{% content-ref url="../advanced-settings/guest-queuing-parameters/and-holdwithvideo-alpha.md" %} and-holdwithvideo-alpha.md {% endcontent-ref %}
{% content-ref url="../advanced-settings/settings-parameters/and-queuetransfer.md" %} and-queuetransfer.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
&rem
Example: &remote=somepasscode
Value | Description |
---|---|
(some passcode value) | this string will have to match on both sides of the connection |
{% hint style="info" %} Android devices only! {% endhint %}
Must be enabled by both the sender and viewer with identical passcodes in order to work. This is a security precaution. If you pass no value to &remote
, it will still work, so long as both sides leave it blank.
In some ways, the &remote
function gives permissions to a viewer that would otherwise be restricted to a director or the sender themselves.
A director of a room can remotely change focus/zoom of a participant without needing the &remote
command. This applies to both the main director and any co-director, and that's accessible via their per-guest video settings options.
There is a toggle in the director's room which adds &remote
to the guest's invite link.
Use the mouse wheel over the video you wish to zoom in or out of as a viewer. The sender needs to support zoom, which often is limited to some webcams and Android devices.
Remote focus may also work as well by holding CTRL
(or Command) while using the mouse wheel. The sender needs to support focus for this to work, which often is limited to some webcams and Android devices. It's sometime listed as "focus distance" in the senders video settings menu.
To check if a device supports zoom or focus, go to https://vdo.ninja/supports. It will show whether your browser and the selected camera supports focus/zoom.
If you are the one publishing with an Android device, you can hold the screen down and move your finger up or down to zoom in and out as well; you don't need a remote user or the settings menu to do this.
A bit less accessible, but using &remote
also gives the viewer permission to request statistic information. The monitoring tool, also used by the VDO.Ninja speed-test, makes use of the &remote
flag to remote access stats.
Example usage:
Monitoring Link: https://vdo.ninja/monitor?sid=BaGpHmu,stevetest123
It will pull statistics data from the sender of a video stream and visualize it, allowing for remote monitoring of stream quality. For this command to work though, the publisher needs to add &remote
to their URL to allow for remote access.
This reason for needing &remote
is privacy related, as the statistical information being shared with the monitor page could include information like browser or system data of remote viewers unconnected to the monitoring user. While likely unneeded, adding &remote=somePassword
to both the monitoring and push links will further increase security with a password check.
The VDO.Ninja speed test (https://vdo.ninja/speedtest) has a link at the bottom of the page, which is all already configured to provide remote monitoring of speed test results without needing to play with any parameters or settings.
In regards to &sid
, you can pass multiple stream IDs, and so long as each remote sender of that stream ID has &remote
added to their URL, the monitoring page will be able to monitor all those outbound streams.
Nacks per second is similar to packet loss, and so a high nack loss rate implies a restriction on network quality. "quality limitation reason" may also be stated, which can imply whether the CPU or Network is the bottleneck in achieving maximum quality.
If viewers of a stream ID being monitor have a label assigned (&label
), then that will appear as a label on the monitor page besides the graph, identifying it.
When using the &remote
control option, the viewer can now remotely hang-up the sender via the right-click menu. The sender needs to remote control enabled for this to work of course.
&remote
, if used on a push link without a password added, it will now allow the remote viewer limited control (hangup, focus, zoom, detailed stats), even if they don't have &remote
added to their URL also. When using &remote
, the option to "reload" the remote browser is now available, so you can potentially reload a remote unattended session that contains&autostart&webcam
.
General Option! (&push
, &scene
, &solo
)
&roomid
&r
Example: &room=RoomID
Value | Description |
---|---|
(string) | 1 to 49-characters long: aLphaNumEric-characters; case sensitive. |
Rooms broadcast to all participants who have joined.
Rooms are complemented by the &director=roomname
function. Directors can have oversight of a room.
Rooms limit the viewing bitrate that guests of a room can request. OBS does not have these viewing limits though.
Rooms have no forced limit on the number of guests allowed, but practically 10 is about the limit I'd recommend.
Adding &showonly=xxx
and &roombitrate=0
to the guest's URL can be used to help increase the capacity of rooms to 30 or more.
An alternative to a &room
is a faux-room, which can be done with:
https://vdo.ninja/?push=aaa&view=bbb,ccc,ddd
There's a documentation page dedicated to rooms here.
There's also a video below looking at what sort of performance and system load there is when using an unoptimized group room.
{% embed url="https://www.youtube.com/watch?v=VYYG4rZffcM" %}
You can reduce CPU load using the &broadcast
flag, if hosting a larger room.
You can also transfer guests between group rooms, using the transfer function that the director has.
{% content-ref url="../getting-started/rooms/" %} rooms {% endcontent-ref %}
{% content-ref url="../getting-started/rooms/transfer-rooms.md" %} transfer-rooms.md {% endcontent-ref %}
{% content-ref url="../viewers-settings/director.md" %} director.md {% endcontent-ref %}
description: >- Sets the audio mode to stereo and changes default audio settings to improve audio quality
General Option! (&push
, &room
, &view
, &scene
)
&s
&proaudio
Example: &stereo=1
Value | Description |
---|---|
(no value given) | It behaves like 3 or 1, depending on if you are a guest or not |
0 | will try to down-mix your mic to mono. Does not enable any pro-audio settings |
1 | enables it for both push and view (if used on both links) |
2 | enables it just for viewing requests and not publishing requests |
3 | enables it for just publishing requests and not viewing requests |
4 | enables 5.1-multichannel audio support (Experimental and may require a Chrome flag to be set) |
5 | This is the default if nothing is set. It behaves like 3 or 1, depending on if you are a guest or not |
6 | solely just enables stereo for both in/out |
8 | 7.1 surround sound audio #and-stereo-8 |
Adding &stereo
to the URL will apply audio-specific setting presets. For inbound audio streams, it can be used to increase the audio bitrate from 32-kbps to 256-kbps. For outbound streams, it will disable echo-cancellation and noise-reduction. When applied to both the outbound and inbound sides of an audio stream, it will also enable stereo audio if available.
There are a variety of different modes that apply different combination of presets. You can also override any preset with other URL parameters, such as &audiobitrate
, &outboundaudiobitrate
, and &aec=1
.
If using a microphone, wearing headphones is strongly recommended if using this parameter, along with knowledge of correctly setting your microphone gain settings. Echo and feedback issues can occur if this option is used incorrectly.
When using this option in a group room, you can't simply just apply this URL option to the director and have it apply to all guests. You will need to add the flag to each guest and to each scene-link to enable the pro-audio stereo mode. Depending on the value you pass to the URL parameter, you will get slightly different outcomes.
&stereo
and &proaudio
currently do the same thing, so they are just aliases of each other. When used, they can be used to setup the audio transfer pipeline to allow for unprocessed, high-bitrate, stereo audio.
Use of this option is generally for advanced users who understand the consequences of enabling this. High-quality audio can cause audio clicking, reduced video quality, feedback issues, low volume levels, and higher background noise levels.
For stereo-channel support to work, you will want both the viewer AND the publisher of the stream to have the respective &stereo
flag add to their URL.
You can customize things further using &aec
, &ag
, &dn
, &ab
and &mono
. These flags will override the presets applied by the &stereo
flag. Please note, depending on your browser, enabling &aec
, &ag
, or &dn
can force disable stereo audio.
The most powerful mode is stereo=1
, which if enabled:
- Turns off audio normalization or auto-gain when publishing (
&push
) - Turns off noise-cancellation when publishing
- Turns off echo-cancellation when publishing
- Enables higher audio bitrate playback, up to 256-kbps, when listening (
&view
)
If the parameter is used, but left without a value, it is treated as a special case (either 1 or 3). Please see follow link for more info:
Option | alias | aec | autogain | denoise | stereo playback | stereo output | default ab in | max ab out | limited ab in | cbr |
---|---|---|---|---|---|---|---|---|---|---|
&stereo=0 |
off | on | on | on | off | no | 32 | 510 | 510 | no |
&stereo=1 |
both | off | off | off | on | yes | 256 | 510 | 510 | yes |
&stereo=2 |
in | on | on | on | on | no | 256 | 510 | 510 | yes |
&stereo=3 |
out | off | off | off | off | yes | 32 | 510 | 510 | no |
&stereo=4 |
multi | off | off | off | on (5.1) | yes | 256 | 510 | 510 | yes |
The default mode when &stereo
is used alone is &stereo=5
, which acts like either &stereo=3
or &stereo=1
, depending on whether the link its applied to is a room guest or not. This option will make the most sense for most users.
Option | Context | alias | aec | autogain | denoise | stereo playback | stereo output | default ab in | max ab out | limited ab in | cbr |
---|---|---|---|---|---|---|---|---|---|---|---|
&stereo=5 |
Regular/OBS | 5 | off | off | off | on | yes | 256 | 510 | 510 | yes |
&stereo=5 |
Director | 5 | off | off | off | on | yes | 32 | 510 | 510 | no |
&stereo=5 |
Room Guest | 5 | off | off | off | off | yes | 32 | 510 | 510 | no |
Option | alias | aec | autogain | denoise | stereo playback | stereo output | default ab in | max ab out | limited ab in | cbr |
---|---|---|---|---|---|---|---|---|---|---|
iOS devices | on | on | on | off | off | 32 | 32 | 32 | no |
Just for reference, the audio codec used by VDO.Ninja is OPUS (48khz), which can provide high-fidelity music transfer when the audio bitrate is set to 80-kbps per channel or higher. The default audio bitrate used is 32-kbps VBR, which is sufficient for most voice applications. Increasing the audio bitrate to a near-lossless 500-kbps or something may end up causing more problems than anything, but that is supported if needed.
&stereo
now works with the WHIP output, so if enabled, you'll publish stereo 2.0 with a default audio bitrate of around 80 to 100-kbps; otherwise the default is mono at around 60kbps. These defaults bitrates might be changed own the road.
7.1 surround sound audio is being supported now, in a technical sense, although really only if the source is a server stream. To use, add &stereo=8
on the viewer end. (5.1 multi channel was around supported with &stereo=4
I think)
{% content-ref url="../advanced-settings/view-parameters/audiobitrate.md" %} audiobitrate.md {% endcontent-ref %}
{% content-ref url="../source-settings/and-outboundaudiobitrate.md" %} and-outboundaudiobitrate.md {% endcontent-ref %}
{% content-ref url="../newly-added-parameters/and-screensharestereo.md" %} and-screensharestereo.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
Allows a user to save and then later restore their streaming session settings via the use of local storage.
Clearing the browser's cache will clear the settings.
This will not work if the site is wrapped as an IFRAME.
The user will be prompted with a pop-up when they return to the site, after using &sticky
, to see if they wish to recover their previous settings. These settings are those stored in the URL only, so it essentially loads the previously used URL.
There is a toggle in the director's room which adds &sticky
to the guest's invite link.
New in v23
Added a little "pin" icon to the end of the copy/view link when sharing your camera. Pressing it is the same as using &sticky
on your URL, as next time you visit VDO.Ninja it will ask you if you wish to reload your &push
link.
&sticky
and the "save room" button won't work for links loaded in OBS Studio anymore - there isn't a usecase for this really, and using &sticky
there just complicates things for some users.
{% content-ref url="../advanced-settings/settings-parameters/and-clearstorage.md" %} and-clearstorage.md {% endcontent-ref %}
General Option! (&push
, &room
, &view
, &scene
)
This parameter lets you specify a STUN server for webRTC negotiation. The default STUN servers use those provided by Google (and recently also Cloudflare), at stun:stun.l.google.com:19302
, but with this command you can set your own.
&stun
will overwrite the existing STUN values provided by VDO.Ninja. If you wish to keep the existing STUN server options, adding additional options, or if you wish to add multiple custom STUN servers, you can use the related &addstun
parameter. This is the same idea, but when used it won't overwrite the existing STUN options.
Using &stun
and &addstun
together will let you specify two custom STUN servers.
Setting &stun
to false will clear the default STUN servers.
If your STUN server requires a password, you can pass the STUN server address with semi-comma separated values in the form &stun=USERNAME;PASSWORD;ADDRESS
Basic sample usage of &stun
:
https://vdo.ninja/?push&stun=stun:stun4.l.google.com:19302
A STUN (Session Traversal Utilities for NAT) server is used to discover a device's public IP address and port, especially when it is behind a Network Address Translator (NAT), facilitating peer-to-peer communication in technologies like WebRTC.
If your browser has disabled WebRTC IP leaking, then the STUN servers may be pretty useless, as the only IP your browser will share with other peers is any obtained from the relay server.
Without a STUN server though, you will still share your local IP, the HOST candidate type, as well as any RELAY candidates obtained from available turn servers.
The magic with VDO.Ninja and peer-to-peer webRTC is largely made possible by STUN servers.
When dealing with ICE (Interactive Connectivity Establishment) candidates, you may encounter terms like "srflx" and "prflx," which refer to different types of ICE candidates. ICE is a protocol used for establishing peer-to-peer communication sessions, often for real-time audio and video communication.
- srflx (Server Reflexive):
- Server reflexive candidates are created when a device behind a Network Address Translator (NAT) sends a request to a STUN (Session Traversal Utilities for NAT) server. The STUN server then sends a response back, and this response contains a reflexive candidate. This reflexive candidate represents the public IP and port of the NAT device.
- Srflx candidates are used to traverse NATs and allow the devices on both sides to find a route to communicate through the NAT.
- Srflx is the most common candidate type seen when making a connection with another remote peer on the Internet, via VDO.Ninja.
- prflx (Peer Reflexive):
- Peer reflexive candidates are also a result of communication with a STUN server, but unlike server reflexive candidates, they represent the reflexive address of the remote peer, not the local device. In other words, they are the public IP and port of the other side, as observed by the STUN server.
- Prflx candidates can be helpful in situations where a WebRTC peer wants to communicate with another peer, and it needs to discover the public address of that peer to establish direct communication.
- Prflx are not common among VDO.Ninja connections, but may be seen when tethering, using a symmetrical firewall, or other non-common networking setups.
In summary, srflx and prflx candidates both involve the use of STUN servers to discover reflexive addresses, but srflx represents the public address of the local device (behind NAT), while prflx represents the public address of the remote peer. These types of candidates are crucial for WebRTC communication because they help establish peer-to-peer connections across NAT devices and firewalls.
{% content-ref url="../newly-added-parameters/and-addstun.md" %} and-addstun.md {% endcontent-ref %}
{% content-ref url="turn.md" %} turn.md {% endcontent-ref %}
Sender-Side Option! (&push
)
Shows a help-screen on the guest joining.
General Option! (&push
, &room
, &view
, &scene
, &director
)
Example: &turn=steve;setupYourOwnPlease;turn:turn.vdo.ninja:443
Value | Description |
---|---|
(user;pwd;turnserveraddress) | Set this TURN server to turnserveraddress with username user and password pwd |
false | off | Disable the use of the TURN servers |
Several TURN servers are provided by Steve for free, for now, and these are automatically selected based on your geographic location. You may wish to use your own privately hosted TURN server instead though, and the &turn
is one flexible way to select it.
- Canada
- Germany
- USA
- France/UK
https://vdo.ninja/?turn=steve;setupYourOwnPlease;turn:turn.vdo.ninja:443&relay
Note the use of turn:
, and in the case of TLS/SSL, turns:
TURN Servers are designed to help certain users connect when they are behind a firewall or other network restriction. About 1 in 10 users need a TURN server to use VDO.Ninja; if you are having problems, check to see if they are using the TURN server.
Sometimes, rarely, using your own TURN server can improve video quality for some users, if the public network routing is very bad and the TURN server is hosted on a high-quality private network, like Google Cloud. Details are provided in the code repo no how to deploy your own (turnserver.md).
TURN servers are NOT something you can use to share one video stream with multiple viewers. (That is an SFU server, which is out of scope of this article.) A TURN server acts like a middle-man, routing the encrypted data between two peers, mainly when those two peers are unable to speak directly themselves.
Using a TURN server can also hide your IP address from other peers. You will need to use &relay
to FORCE the TURN server to be enabled, as otherwise the system will still try to use a direct p2p connection, instead of the TURN server. You may want to add turn and relay flags to both the viewer and the sender side, to ensure things are correctly set.
https://vdo.ninja/speedtest performs a connection test using the TURN server. It will select the closest public TURN server to you. At peak hours, these TURN servers might have lower performance compared to at off-peak hours, so consider hosting your own TURN server if absolute maximum performance is needed.
You can check to see if you are using the TURN server by checking the connection stats window (Left-Click
+ CTRL
while viewing a video. In this stats display, "Relay" implies connected to a TURN server. HOST implies connected via a LAN. SRFLX/PRFLX implies connected directly via STUN.
Details on how to setup and deploy your own TURN server is here, although there are also plenty of guides online for this, too:
https://github.com/steveseguin/vdo.ninja/blob/develop/turnserver.md
It is possible to store credentials for your TURN server on a server, pulling them as needed via an API, such as from Twilio's API. It is also possible to hard-code the credentials into the app itself. Both these options require self-deploying the website code however.
{% content-ref url="and-tcp.md" %} and-tcp.md {% endcontent-ref %}
{% content-ref url="../common-errors-and-known-issues/hosted-your-own-turn-server.md" %} hosted-your-own-turn-server.md {% endcontent-ref %}
{% content-ref url="and-relay.md" %} and-relay.md {% endcontent-ref %}
{% content-ref url="../newly-added-parameters/and-tz.md" %} and-tz.md {% endcontent-ref %}
{% hint style="warning" %} Sending a 4K video feed with VDO.Ninja is very CPU intensive. Be prepared to use all of 8 real cpu cores (not threads). {% endhint %}
VDO.Ninja has 3 predefined &quality
levels:
&quality=0
tries to do 1080p (1920x1080 @ 60fps)&quality=1
is the default. It tries to select 720p (1280x720 @ 30fps ) for both screen capture and webcam.&quality=2
tries to do 360p (640x360 @ 30 fps).
By “trying”, I mean that if the resolution is not available, VDO.Ninja defaults to another resolution that the camera supports instead. This way, no errors are thrown and a compatible stream is sent, even if it’s not exactly what you might have desired.
VDO.Ninja is however capable of doing higher resolutions and custom resolutions however; you just need to manually specify the resolution you want. When you manually specify a resolution, if it doesn’t work, an error is thrown.
While I could make a selectable option for 4K in the user interface, another problem with 4K is that it requires a LOT of CPU power to encode. Most users will always select the highest resolution allowed, not understanding that it might actually be a bad idea. Maxing out your CPU can actually result in worse quality with lower frame rates than selecting a lower, safer, resolution.
That all said, you can give “4K” a go by adding &width=3840&height=2160
to the invite link.
For example then, https://vdo.ninja/?push=inviteGuest123&width=3840&height=2160
If the guest does not support 4K, this will give an error to the guest, stating that the video device is over-constrained.
The default frame rate is 60-fps, although if their device does not support that, it will use a lower support frame rate. If you manually specify a frame rate, and the camera or display does not support it, it will also give an error.
Next, while you might have selected 4K, with the exception of static video screen shares, you cannot transfer 4K video with the default video bitrates set. For action, you will need closer to 40-mbps video bitrates set on the viewer’s end. For talking head videos, you will want over 10-mbps and possibly even more. Without a high enough bitrate set, the video will not stream at 4K and more than likely not maintain 60-fps.
To set a target bitrate add &videobitrate=20000
for 20-mbps for example. This goes on the viewer link.
As a result, to successfully stream 4K video, you generally need a computer system with 8 real CPU cores or more, running at 3.6ghz or higher. A modern AMD 3900X-series CPU or Intel 9900K CPU are ideal for this task, but a quad-core laptop will not be. You might be able to get away with lesser bitrates and lesser CPU requirements if just screen-sharing text, but it still is not for the faint of heart.
Lastly, macOS users may find that 4K is simply not possible or very difficult. If you do manage to get it working, it might only operate at 5-fps or so. I don’t quite know why this is, but if you intend on sharing 4K video, you might be better off using a Windows PC. It seems to perform better.
You can customize the playback of videos by added parameters to the VDO.Ninja URL links, along with many other aspects. The default video bitrate of most modern browsers is around 2500-kbps, which is okay, but we can achieve higher video quality if we manually set this to something even higher.
https://vdo.ninja/?view=streamid&videobitrate=6000
You’ll notice that we added &videobitrate=6000
to the viewer’s side and not the publishing side. The viewer gets to control the bitrate; every viewer can set their own custom video bitrate in fact.
On the publishing side, the default target resolution is already a high 1280x720 @ 60-fps, but we can set this higher by adding &quality=0
to the push link. This will have the publisher’s side try to make available a 1920x1080 video stream, if their camera or video device supports it. If not, it will fall back to 720p. https://vdo.ninja/?push=streamid&quality=0
For 1080p60 gaming, you’ll want to set the video bitrate to 12000-kbps or higher, as lower bitrates might cause the frame rate to be quite low otherwise. Otherwise, for talking head-type videos, the default video bitrate is often going to be adequate.
Higher resolution streams, especially 1080p60, requires a LOT of CPU power. Having 4-CPU cores is generally recommend for 1080p60 video streams, and 6 to 8 cores are recommended if you are intending ti game at the same time.
Using Ethernet instead of Wi-Fi will also help to ensure the frame loss at these higher resolutions is managable. At higher resolutions, frame rates are more likely to be unstable.
4K30 video is achievable with VDO.Ninja, with a fast enough computer and with very high video bitrates; often in the realm of 30 to 40-mbps.
As VDO.Ninja dynamically adjusts video resolution and bitrate to match the available Internet connection bandwidth availability, sometimes 1280x720 video resolutions won’t be maintainable. You can run the https://vdo.ninja/speedtest to see if you are able to hit at least 2000-kbps, which is about what is needed for smooth 720p video.
You can customize the capture resolution and playback quality of videos by adding parameters to the VDO.Ninja URL.
The default video bitrate of most modern browsers is around 2500-kbps, which is okay, but we can achieve higher video quality if we manually set this to something even higher.
https://vdo.ninja/?view=streamid&videobitrate=6000
You’ll notice that we added &videobitrate=6000
to the viewer’s side and not the publishing side. The viewer gets to control the bitrate; every viewer can set their own custom video bitrate in fact. (For some games, a bitrate of 20000-kbps may be needed, but normally that's overkill though, and can actually increase frame loss if it is higher than your connection can handle.)
You can also play with different video codecs; &codec=av1
is a viewer side option and tends to offer better colors and quality than the default vp8 or h264 codecs, but av1 will use a up a lot more CPU.
Another viewer side option is &scale=100
, which will disable dynamic fit-to-window scaling optimizations. This is especially valuable if wanting to downlscale 4K to 1080p video, as otherwise VDO.Ninja would limit the resolution to the size of the OBS Browser source window. It can also help when there is more than one video on screen, but do note that disabling the auto-scale optimizations to achieve better quality will increase the CPU and network load for all parties.
Sometimes adding some sharpness to the video as a digital video effect in OBS can help improve video quality, especially for video containing fine-text, like a screen share or video overlay. By default text might look a bit soft with VDO.Ninja, and sharpening can resolve it.
On the publishing side, the default target resolution is already 1280x720 @ 60-fps, but we can set this higher by adding &quality=0
to the push link. This will have the publisher’s side try to make available a 1920x1080 video stream, if their camera or video device supports it. If not, it will fall back to 1280x720p. https://vdo.ninja/?push=streamid&quality=0
For 1080p60 gaming, you’ll want to set the video bitrate to 12000-kbps or higher, as lower bitrates might cause the frame rate to be quite low otherwise. Otherwise, for talking head-type videos, the default video bitrate is often going to be adequate.
Higher resolution streams, especially 1080p60, requires a LOT of CPU power. Having 4-CPU cores is generally recommend for 1080p60 video streams, and 6 to 8 cores are recommended if you are intending to game at the same time.
Up to 4K or beyond is possible as well, but you'll need to manually specify the capture resolution with &width
and &height
instead, and it will require significantly more CPU and network bandwidth than even 1080p. You can also gently ask for a specific frame rate with &maxframerate=60
, which is sometimes needed with certain iPhones to force 60-fps at 1080p.
As VDO.Ninja dynamically also adjusts video resolution and bitrate to match the available Internet connection bandwidth availability, sometimes 1280x720 video resolutions won’t be maintainable. You can run the https://vdo.ninja/speedtest to see if you are able to hit at least 2000-kbps, which is about what is needed for smooth 720p video.
Using Ethernet instead of Wi-Fi will also help to ensure the quality and frame loss at these higher resolutions is obtainable. At higher resolutions, frame rates are more likely to be unstable and the resolution might be throttled to something lower. Packet loss will impact the quality of a video stream quite a bit, and in rare cases, you may need to use &relay
or &meshcast
mode to assist in overcoming network throttling or routing issues.
When in a group room, specifically as a guest or director sharing video with another guest, the video will be limited to 500-kbps by default.
The director can increase the total room bitrate using a slider under the room settings menu; the button for is found in the director's lower menu bar.
You can also use &totalroombitrate=4000
to set a higher room bitrate via the URL, as well as experiment with other bitrate options or trying out &meshcast
. Setting the room bitrate too high though can cause everyone in the room to have problems, specifically with overloaded CPUs or network bandwidth saturation. 500-kbps is the default for a reason.
{% hint style="info" %} This set of instructions will work for Windows, Mac1 and Linux2. {% endhint %}
- Go to https://vdo.ninja/?push with your mobile phone and start sharing your camera.
- Add your VDO.Ninja ‘view’ link as a Browser Source in OBS in a Scene.
- Select the "Control audio via OBS" option to bring audio in.
- Resize the source as you see fit.
- Configure OBS' Virtual Camera to use the Scene or Source as the Output Selection
- Select “Start Virtual Camera” in OBS.
- Open your 3rd party program and choose “OBS Virtual Camera” as the Video input.
Detailed steps of how to perform this setup and include audio from the device are explained here.
OBS VirtualCam is fully compatible with VDO.Ninja and is useful for connecting MULTIPLE different OBS mixers together remotely, so you can take turn producing a show. You can also use it to turn your smartphone into a webcam. You can also share your “live show” with a small group of friends, perhaps those who are also in the show with you, so everyone has a real-time view of the show that is going on.
Sometimes you may need to stop/restart the OBS VirtualCam if it starts crashing your computer. If you see nothing but “GREY”, then you need to start it before using it. See “How to use”. If you see just black, its probably because you haven’t put anything into OBS yet.
While you can achieve a multi-person chat with a group room, you can also do it without it.
For example, https://vdo.ninja/?view=id2&push=id1
You’ll notice that here we have the link both a PUSH and VIEW parameter. This allows us to view a remote video and publish our own video to others within a single browser tab. This has the advantage over using two browser tabs as echo-cancellation will work with this approach. It is also compatible with mobile devices where two browser tabs isn’t likely feasible.
The downside of this approach is that you’ll need to create a custom link for every person. In this case,
https://vdo.ninja/?view=id2&push=id1
and https://vdo.ninja/?view=id1&push=id2
If you go with a simple group room instead, you won’t need to personalize links in this way, but rather just have a single link for multiple guests.
For example, https://vdo.ninja/?room=yourroomname
or for something even cleaner, https://vdo.ninja/yourroomname
To create a 3-person setup, you can list multiple streams IDs as VIEW values alongside the PUSH value into three different personalized links.
https://vdo.ninja/?view=id1,id2&push=id3
https://vdo.ninja/?view=id1,id3&push=id2
https://vdo.ninja/?view=id2,id3&push=id1
Bring remote video and audio streams into your video production software for free. Low-latency and high-quality, VDO.Ninja is flexible tool ideal for the COVID era of remote participation. As a beginner to VDO.Ninja you should take a look at these pages:
- vdo.ninja-basics.md
- stream-ids.md
- the-power-of-the-url-parameter.md
- multi-person-chat.md
- rooms
- high-quality-camera.md
- mobile-phone-camera-into-webcam.md
- cheat-sheet-of-basic-parameters
VDO.Ninja is a passion project and is free to use.
If you'd like to donate as a way of saying thank you, please visit Steve Seguin's GitHub Sponsors page. Donations are appreciated.
While GitHub Sponsors is the main way to donate, there is also PayPal and buymeacoffee. Some crypto options are also listed on the GitHub Sponsors page, including Bitcoin and Ethereum. If you wish to contribute financially in other ways, please contact Steve directly: [email protected]
If you do make a gift, be sure to let @steve know on Discord so he can thank you personally.
User feedback, bug reports, and suggestions are great ways to contribute to the project; they are highly-valued. Spreading the word of VDO.Ninja to those who may find it useful is also greatly appreciated. Community involvement, such as helping to support other users, writing user-guides, and even showcasing what you've made with VDO.Ninja is also appreciated.
If you'd like to grab a VDO.Ninja branded sticker or mug, there is a merch store with a 0% commission fee set. It won't financially support the project, but it's always motivating to see them randomly in a stream. https://zero.vdo.ninja.
Stream IDs are not magical in any way and can be manually or automatically created and reused.
Use https://vdo.ninja/?push=STREAMID
to publish a video and https://vdo.ninja/?view=STREAMID
to remotely view it. If you don't manually specify a stream ID, VDO.Ninja will sometimes generate one for you. You can reuse the generated stream ID if you wish.
Stream IDs only exist when they are actively used; once you stop using a stream ID, it no longer exists until it is used again.
- When in a group room, a stream ID can only be accessed from within that same room, unless transferred to a new room by the room's director.
- To make up a valid stream ID of your own, choose something with less than 51-characters of length and ensure it's AlpHaNuMerIc-only.
- A stream ID must not already be in active use, else you will be provided with an error stating this. This isn't the case when using a password however, as the password AND the stream ID must be the same in this case for the stream ID to be considered already in use. So, you technically can reuse the same stream IDs, changing only the password, if security is a concern. Even still, you should try to keep stream ID's confidential and change them when appropriate.
- You can use the
&label
property to give a name to a stream, rather than using a stream ID to do the same. Using this strategy of using securely-named stream IDs, while using labels to assign a name to a stream, will improve security and unlock new options, like lower-third display name overlays. - A director does have a stream ID, and they can be manually assigned to a director in the same way they are assigned to any publisher.
- When a guest shares their screen, while also sharing their webcam, the screen share stream will get its own stream ID. Adding
&ssid
to the guest link can have the stream ID for that screen share be predictable, appending_ss
as a value. Otherwise, the screen share stream may have a random stream ID.
You can customize the playback of videos by adding query string parameters to the VDO.Ninja URL links, along with many other aspects. VDO.Ninja is highly flexible in this regard, letting you achieve your desired outcome without needing to code and without additional software.
For example, a simple viewer URL link such as
https://vdo.ninja/?view=streamid
could be amended to
https://vdo.ninja/?view=streamid&videobitrate=500
which will cause the viewer to receive the publisher's video stream at a video bitrate of 500-kbps.
{% hint style="info" %}
Multiple parameters can be appended together by using the ampersand (&
) as a separating character.
{% endhint %}
For example, to view the video stream published at stream ID streamid
at a video bitrate of 500-kbps and set the &proaudio
parameter to 1
:
http://vdo.ninja/?view=streamid&videobitrate=500&proaudio=1
Some parameters, like &view
will accept a comma-separated list of valid values, so you can do some rather powerful combos, such as publishing your own video (using &push
) while also viewing multiple others videos. VDO.Ninja will auto-mix the videos together into a single layout for you:
http://vdo.ninja/?push=aaa&view=bbb,ccc,ddd
{% content-ref url="../advanced-settings.md" %} advanced-settings.md {% endcontent-ref %}
{% content-ref url="../advanced-settings/cheat-sheet-of-basic-parameters/" %} cheat-sheet-of-basic-parameters {% endcontent-ref %}
VDO.Ninja needs two things to work:
- Someone pushing a video feed out from their device
- Someone viewing that video feed
- Visit https://vdo.ninja/ with your web browser (Chrome, Edge, Safari).
- Select
Add your camera to OBS
. - Select your camera and audio device from the list of devices.
You will see the video feed of the device on screen. - Select
Start
and at the top of the screen a ‘view’ link will appear. - Copy this view link and send it to someone you want to have access to this feed, or place it inside an OBS browser source.
WebRTC is the magic behind VDO.Ninja. While the magic sauce is so much more than that, WebRTC powers the engine. This way VDO.Ninja works everywhere there is a modern browser. MS Edge, Google Chrome, Mozilla Firefox, Safari, Opera, Vivaldi, Brave. You name it.
VDO.Ninja is a peer-to-peer system. This means for each new person viewing your feed, a new encode is processed. It also is CPU bound since encoding usually takes place on the CPU. Take care not to overload your system. Keep an eye on your CPU usage.
description: >- A room allows for group chat and enables a director to control the room and access to each stream
The rooms feature creates a virtual room where multiple devices can connect to share audio and video. It offers echo-cancellation and text-chat support as well. A room's ‘director’ can manage the guests from the control room, easily accessing individual sources for integration into OBS.
♻️ If a room isn't already in use, you can use and reuse it forever.
🔑 Adding a password will allow you to use your room, even if the same room name is already in use.
🏷️ You can change the room name anytime; just modify the URL.
- There is Chrome-imposed limit of about 128 peers while using video and chat connections.
- You will probably bump into video decoding limits before reaching a 128 peers limit, due to limits on the host's processor power and to a lesser degree their bandwidth.
If you want a room that can handle 30 people, it can be done. However, everyone in the group needs good internet, a fast computer, or the room needs video previews disabled for guests. The &broadcast
feature can help accomplish this, for example.
For very large groups (i.e. larger than 40), it's generally advised that you use regular server-based chatting service, like Google Meets, and send a VDO.Ninja invite link to each person individually. This way, you can record the individual streams of those in the Google Meet at a high resolution but still have all the guests see and hear each other.
If you use OBS VirtualCam, now included with OBS v26, you can broadcast from OBS directly into the Google Hangouts or other conferencing software. To avoid audio feedback/echo issues, having the guests wear headphones is suggested.
- Passwords are available to keep rooms secure, but are optional.
- A room name + password combination makes the room unique. IE: a
?room=roomname&password=GeNeRaTedPaSsWoRd
and a?room=roomname&password=ThisIsAnotherPassword
are different rooms.
Guests have their own link to join a room. They will be able to see all of the other guests in the room, including themselves. Settings to restrict what sources each group member can see or hear are also available.
Guest devices present in the Room will see and hear all other present device video/audio streams.
Text-chat is available to those in the room
The video quality of those in a group room will appear low to guests, but this is to ensure more bandwidth and CPU resources are made available for the OBS's access to the stream. This can be changed with parameters such as &totalroombitrate
which lets you increase the bitrate of a room.
The director will be able to view the room, without joining it themselves, and they will have controls provided that will let them modify aspects of how the room shows up in their OBS. For example, they will be able to mute certain people so they can't be heard or seen in OBS.
The director can also join the room if needed. Toggle the 'Director will also be a performer' option when creating a room. This can also be done by appending &showdirector
to the director page URL.
The director will be provided isolated direct links to each of those video streams in the group room, allowing for fine-grain mixing control in OBS.
Using OBS Virtualcam (or the Mac equivalent), you can even let your guests view the OBS live stream with sub-100ms of latency. In this case, each guest only needs to view one video stream, the main mixed OBS stream, freeing up group resources to allow for even larger group rooms.
A director can also address a specific guest via full screen text messages, or via dedicated talkback audio.
Text Messages can be broadcast to the room from the director.
When you create a room, the guest's feeds will show up in the director’s room. While multiple people can join the director’s room, only the first director to join has the ability to issue commands. Any one in the director room can access the isolated solo streams for each guest though.
Appended to the bottom of the video control box for each guest video is a SOLO LINK button and a link. You can copy the link with either the button or the link, or you can just drag the link (on Windows) into OBS. This gives you an independent window of that guest’s stream, at high quality.
The controls in the VDO.Ninja’s director room only will let you adjust the volume (and mute) that solo video. The ‘add to scene’ links do not apply to solo-links.
You can create a solo link by hand by doing https://vdo.ninja/?room=RID&view=SID&solo
&solo
is left blank, while the &view
value is specified.
Every time you view a link, in OBS or elsewhere, you increase the load on the remote guests’s computer. Pulling more than one HD feed from a remote guest is not advisable, unless they have a capable computer and good internet connection. As a director, you can disable the preview video in the control box, freeing up a small bit more bandwidth for those connected on very weak connections. (three buttons; video off / video on / binoculars for a HD preview).
--- description: A powerful tool that allows a director to move guests to a different room ---Sometimes you will want to move a user from one room to another. This is often the case if wanting to pre-screen users, or if you want to create break-out rooms. It also is a way to ensure when you kick a user out of a room, they cannot be allowed back in without express permission.
When a user is transferred to another room, they no longer are the owner of that guest. The director of the room you transferred that guest to becomes the owner.
Only the main director can transfer users; anyone can be the director of a room -- it's first come first serve, so be sure to leave the director-window open if you wish to remain the director of a room
When a guest is transferred to a new room, they do not know which room they are transferred to. This allows for privacy and secrecy, allowing for the main landing room to act like a screening room.
The &queue
command can be used in conjunction with rooms and transfer rooms. When you transfer a user from a queue, they will no longer be in any queue once transferred. When in queue, the guest will not be able to see anyone, but the director will be able to see them. When transferred out of the queue, they will be able to see everyone in the room.
If you transfer someone to a room, the passwords for both rooms need to match. This may change in the future.
If someone in a transfer room disconnects or refresh, they will end up back in the original landing room. This is for privacy and security reasons, as once a user is kicked out or disconnected, the expectation is they cannot enter the room again unless explicitly allowed. Be sure that any guest who is transferred has a stable connection; unstable mobile connections or connections using VPN services may get booted out every now and then.
If you'd like to transfer a user to a new room, along with a new password or setting, you can use the Change URL option instead; as seen in the image above. The guest transferred in this fashion WILL be able to see the room they were transferred to, along with any new password. If they get disconnected or if they refresh, they will stay in the new room. This is quite useful if privacy and security are not urgently needed, as it allows for more robust options.
There's an option called &rooms
, which allows the director to list multiple room names via the URL. These rooms become buttons that the director can press to pre-arm the transfer button with.
There are several Audio Filters in VDO.Ninja. Some of them are turned on by default, some are not. To activate these Audio Filters you have to add them to the source side.
So for example:
https://vdo.ninja/?push (for a basic push link)
https://vdo.ninja/?room=SOMEROOMNAME (for a guest in a room)
Name | Parameter | By default | Change the default setting |
---|---|---|---|
Outbound Audio Bitrate | &oab | 32-kbps | &oab=XX (0-510 kbps) |
Pro Audio | &proaudio | off | &proaudio |
Master Gain | &audiogain | 100% | &audiogain=XX (0-200 %) |
Auto Gain Control | &autogain | on | &autogain=0 |
Echo Cancellation | &echocancellation | on | &echocancellation=0 |
Noise Suppression | &denoise | on | &denoise=0 |
Noise Gating | &noisegate | off | &noisegate |
Compressor | &compressor | off | &compressor |
Limiter | &limiter | off | &limiter |
Equalizer | &equalizer | off | &equalizer |
Lowcut | &lowcut | off | &lowcut=XX (in hz) |
Microphone Delay | &micdelay | 0-ms | &micdelay=XX (in ms) |
{% hint style="info" %}
- Adding
&proaudio
to a source link disables Auto Gain, Echo Cancellation and Noise Suppression, sets the audio to stereo and the possible outbound audio bitrate to 256-kbps - the
&proaudio
parameter is the same as the&stereo
parameter {% endhint %}
Default settings of VDO.Ninja:
There is a very useful google sheet with a matrix for the &proaudio
(&stereo
) parameter:
{% embed url="https://docs.google.com/spreadsheets/d/1onfIh1hNR1Gh_mthkhmezzWNUMYKMGKPrwx7T428_hc/edit#gid=0" %} https://docs.google.com/spreadsheets/d/1onfIh1hNR1Gh_mthkhmezzWNUMYKMGKPrwx7T428_hc/edit#gid=0 {% endembed %}
Options to control the audio bitrate:
- Add
&proaudio
to the source AND view link to get 256-kbps (echo cancellation, noise suppression and auto gain are then DISABLED) - Add
&proaudio
to the view link to get 256-kbps (echo cancellation, noise suppression and auto gain are still ENABLED) - Add
&oab=100
to the source link to get 100-kbps - Add
&audiobitrate=200
to the view link to get 200-kbps
{% hint style="info" %}
&proaudio
overrides the bitrate of&oab
if set on the source AND view link or only on the view link -> you get 256-kbps.&audiobitrate
overrides&proaudio
and&oab
{% endhint %}
This also works for &room
on the source side and &scene
on the view side if you are in a room.
Some examples:
1)
https://vdo.ninja/?push=SOMESTREAMID
https://vdo.ninja/?view=SOMESTREAMID&proaudio
-> 256-kbps
2)
https://vdo.ninja/?push=SOMESTREAMID&oab=100
https://vdo.ninja/?view=SOMESTREAMID&audiobitrate=200
-> 200-kbps
3)
https://vdo.ninja/?push=SOMESTREAMID&proaudio
https://vdo.ninja/?view=SOMESTREAMID
-> 32-kbps
4)
https://vdo.ninja/?push=SOMESTREAMID&proaudio
https://vdo.ninja/?view=SOMESTREAMID&audiobitrate=96
-> 96-kbps
{% hint style="info" %}
To see the audio bitrate
Right-Click -> Show Stats
or
Control (Command) + Left-Click
on a video source
{% endhint %}
description: >- Screen sharing in browsers only allows for tab-audio or desktop-audio capture; not window.
This page contains the standard guide for capturing application-specific audio in Windows. Less complex methods are being developed, with some current alternative options listed here.
Guide: Routing Windows application’s audio to VDO.Ninja
(For MacOS users, you can use Loopback by Roguemedia instead, or check out this list of free options: https://docs.vdo.ninja/platform-specific-issues/macos#capturing-audio)
- 1) Install the VB-Cable Virtual Audio device. (Voicemeeter can be used instead)
https://www.vb-audio.com/Cable/
Tip: If you want to configure the VB Audio driver with custom settings, the recommended sample rate is 48000-hz, as that is the sample used by VDO.Ninja.
- 2) Load up Window Mixer by typing in Mixer to the windows search bar:
- 3) For the application you want, select the Output dropdown and select CABLE Input.
-
4) We can now head over to https://vdo.ninja, but we will want to add the advanced URL parameter
&proaudio
to the web URL, which disables echo cancellation and other digital effects. It will make the audio sound better and echo cancellation is likely not needed if capturing from a Game or Application window.
For example,https://vdo.ninja/?push=myStreamID&proaudio
You can also add this to the view link, which increases the audio quality even more. For example,https://vdo.ninja/?view=myStreamID&proaudio
\ -
5) In VDO.Ninja, select the Cable Output device.
Tip: If you hold downCTRL
(Command
) while selecting inputs, you can select more than one at a time.
\ -
6) A simple way to hear the audio as an output is to just unmute the video. Right-click and show the controls, if not visible, then unmute.
-
7) Alternatively, you can also use the Sound properties for the VB cable to “listen to this device” in Windows, so you can hear the audio even if not in VDO.Ninja. This method might have lower latency than the method in step 6.
While this option still requires a virtual audio cable, as seen above, you can use OBS to capture the application's audio and output the audio from OBS to the virtual cable via the Monitor output in OBS.
Another way of selecting application audio for the Virtual Audio Cable
An alternative to using a virtual audio cable is to use OBS to capture the audio, and then publish the audio to VDO.Ninja directly using the WHIP-publishing mode.
WHIP is an experimental feature currently in OBS and may require a special version of OBS at the moment to access, but it might be included in OBS by default with the release of OBS v30 or v31.
Check out a demo YouTube video of how to accomplish this:
Publishing from OBS directly to VDO.Ninja
More details will be provided as the feature develops.
{% embed url="https://www.youtube.com/watch?v=ynSOE2d4Z9Y" %} Using WHIP to publish to VDO.Ninja directly from OBS {% endembed %}
Vingester.app can let you do VDO.Ninja to NDI. It uses a browser window and can be used to export a copy of the window to FFmpeg, NDI, or make the source available for window-capture. It is a bit heavy on CPU usage, but on a dedicated computer, it works quite well for hosting a few NDI streams.
https://github.com/steveseguin/vingester
Electron Capture is the officially supported tool for doing window capture of VDO.Ninja. It's very light weight and has quite a few command line options to batch start several windows at a time, along with support for hotkeys and other nifty VDO.Ninja specific tasks.
https://github.com/steveseguin/electroncapture
If using Electron Capture on Windows, you can currently do Win+Tab
to switch between virtual desktops --- and sometimes this lets you can put all the VDO.Ninja windows in one desktop, and have a second desktop for vMix etc. It works with some windows setups, and in others, might just show black videos when trying to capture.
While this approach will still use a browser source, you can ingest VDO.Ninja into a browser source for an app like OBS Studio, or even something paid like ManyCam, and then export the captured video stream via their Virtual Camera features into another app that supports webcam / video input devices.
Audio can be exported directly via VDO.Ninja into a virtual audio device, either their the &audiooutput
feature, or from even the right-click context menu, where you can specify which audio output device an audio stream should be played into it. If a virtual audio cable is selected as the output destination, you can then bring that virtual audio cable into any audio application as a raw audio stream, as if it was a microphone or line-in source.
There's also WHEP/WHIP output from VDO.Ninja, which is relatively a new technology/feature, and so not quite a replacement for browser sources. That said, OBS Studio is starting to support this ingestion approach, along with GStreamer, many WebRTC CDN servers and services, and perhaps over the coming years something like vMix will adopt this new technology as well. Please provide feedback and requests if using WHIP/WHEP, so i can continue to improve it.
There's also Raspberry.Ninja (https://github.com/steveseguin/raspberry_ninja), which supports saving raw VDO.Ninja media streams to disk. While there is a bug that's blocking things from working soothingly, can technically use it to pull raw video sources from VDO.Ninja and push to not just disk, but even NDI, system sockets/pipes, RTSP servers, and much more.
While Raspberry.Ninja need more time to cook when it comes to video ingestion, it is more capable than using WHEP/WHIP alone, and supports the data-channel transport protocol, allow for dynamic settings to be applied and meta information to be transmitted, such as tally-light indicators.
There are some third parties that have integrated with VDO.Ninja already, which are able to pull from VDO.Ninja and make the streams available as RTSP sources or such, but I do not have access to their code sources and so cannot promote their paid services here, but you can perhaps search around to find them online.
Learn the basic concepts of VDO.Ninja: Rooms, Control Center and Scenes
Learn how to use parameters to customize VDO.Ninja's behavior\
Learn how to automate starting up VDO.Ninja, automatically join rooms and scenes with camera and audio devices already selected\
Learn how to route guest and application audio on the Mac using Loopback
\
Author:
Chris Marquardt
A GoPro itself doesn't support streaming directly to VDO.Ninja on its own, but there are some indirect ways to do it currently.
While this approach requires a computer, you can connect a GoPro to VDO.Ninja via USB and a computer. The GoPro will appear in your browser and VDO.Ninja for live streaming anywhere.
https://gopro.com/en/ca/news/how-to-use-gopro-for-webcam
You can still connect older GoPros to VDO.Ninja on a computer with an HDMI to USB adapter. While it doesn't stream wirelessly to the computer itself, that host computer can then stream the GoPro video stream to any computer in the world wirelessly and with low latency using VDO.Ninja.
https://gopro.com/en/ca/news/how-to-use-gopro-for-webcam
There's also the option of putting something like a Chromebook or MacBook M1 into a backpack, and doing much the same thing -- connect the GoPro to the Chromebook with a long HDMI cable. An HDMI to USB adapter can be used to connect the HDMI to the ultralight laptop, and you can use just the normal VDO.Ninja browser to stream the HDMI video.
As mentioned previously, newer GoPros (such as a Hero 8 Black or newer), can use USB-C instead of HDMI.
If using a service such as Speedify.com on your laptop, you can bond WiFi and Cellular signals together, allowing you to save bandwidth and be truly mobile, while not dropping the video connection. Hardware cellular bonding solutions are available for professionals needing even more connection reliability.
Another option, one that I haven't tested yet myself personally, is to use an Android tablet device that supports HDMI input.
One such option is this YoloBox production, which I think you can install Chrome onto?. While I haven't tried it, if you can select the HDMI input within Chrome on that device, you might be able to stream to VDO.Ninja with an HDMI device in this way.
https://www.amazon.ca/YoloBox-Band-Facebook-YouTube-Encoder/dp/B07PP6KHHV
Some iPads seem to support USB camera support, so using an HDMI to USB adapter with an iPad may allow for connecting a GoPro to VDO.Ninja on the iPad.
Next year, I'll have some mobile apps out that support HDMI input into a mobile phone, with VDO.Ninja as an output, but at present I haven't had the time to do that.
I do however have an app that lets you screen share the output of an Android device to VDO.Ninja. Using it, you can use an android phone to "preview" the GoPro output in full-screen mode, and then with the VDO.Ninja app stream that full-screen GoPro output to VDO.Ninja. This approach would not require HDMI cables.
One option is to use a Raspberry Pi, which can ingest the HDMI video of the GoPro and stream it to VDO.Ninja over WiFi.
The code for this project is here: https://github.com/steveseguin/raspberry_ninja
It's still a young project, and while things are functional, it's still mainly for those who are interested in tinkering.
If building your own, you might find that it can be built so small that you might be able to use it on its own as a wireless camera, and not need a GoPro at all.
Open-source projects that can be self hosted can convert RTMP into WHEP, which is compatible with VDO.Ninja. https://vdo.ninja/whep contains a WHEP player, and more and more companies are beginning to offer WHEP natively.
In the future, GoPro may support WHIP output, which would be an alternative to RTMP, and would be compatible with VDO.Ninja directly.
Companies like StageTen.tv offer RTMP and WHIP ingest, and while it's not obvious, they can offer a clean output per guest feed for use in VDO.Ninja or OBS Studio.
Restream.io and many open-source projects offer RTMP ingestion, with a way to pull RTMP into OBS Studio, and while there would be a delay, it is an option. Some users will even publish to Twitch, and pull the Twitch stream into OBS Studio, removing ads and overlays using Twitch Turbo and CSS.
In the future, VDO.Ninja may support RTMP to VDO.Ninja directly, via its free Meshcast.io service, however this is still in the works and not official.
description: >- If Wi-Fi isn't holding up for you, you can try connecting over USB or other adapter-type instead.
{% embed url="https://www.youtube.com/watch?v=abCuANblE5w" %} Demoing an Ethernet adapter for an iPhone and VDO.Ninja {% endembed %}
Connecting your smartphone to your laptop via USB seems quite appealing, but it's not always the easiest option. Below I provided three options for tethering your phone to better Internet, with the recommended option first.
One easy option is to buy a smartphone to Ethernet adapter; this can be either USB-C, micro-USB, or Lightning port-based smartphones. These then can connect directly to your router via an Ethernet cable.
You can find details on how to buy and connect such an adapter here: https://www.pcmag.com/how-to/connect-phone-tablet-to-internet-ethernet-cable
If you'd need to be able to charge while connected, there are adapters that offer charging and Ethernet at the same time. I would recommend buying a 100-mbps adapter over a gigabit adapter, as compatibility will probably be better with the 100-mbps adapter and it is still more than sufficient. There's plenty of options on Amazon for under $20.
If you're trying to get away on a budget or don't have access to Ethernet at all, another option is do a reverse-tether to your computer. You can use your smartphone's USB cable for this, but this method is a bit challenging to setup and not all devices will probably be compatible with it.
There are many approaches to setting this up, such as this one: https://liliputing.com/2020/03/gnirehtet-reverse-tethering-app-lets-your-android-phone-use-your-pcs-internet-connection.html
Many of these approaches require root-access to your Android / iPhone device and need a lot of low-level networking setup. As a result, unless your phone already has the feature supported in its settings somewhere, it may be too tricky for most users to setup. A functional paid-option may exist for this, though I'm not sure what it is.
If you're still okay with using Wi-Fi, but just need to connect to the computer directly, you can use Windows 10 mobile hotspot option. This is pretty easy to setup, assuming you can find the correct settings on your computer for it and if you have an available Wi-Fi adapter to use as the tether. The option may not appear if you only have one network adapter. Details linked below:
{% embed url="https://support.microsoft.com/en-us/windows/use-your-pc-as-a-mobile-hotspot-c89b0fad-72d5-41e8-f7ea-406ad9036b85" %}
description: >- There are numerous free URL management tools to make using VDO.Ninja even more flexible
You can use services like https://short.io to create aliases of your invite links, leveraging those service platforms to also keep track of invites you have sent out, how many times they have been opened, and also change the VDO.Ninja settings contained in the invite after sending it.
VDO.Ninja lets you move guests between room and change the URL of a guest after they have connected, but it doesn't offer services itself that let you change the URL before the user has connected.
{% hint style="info" %} I have no relation to Short.io; it's just what service I happen to use. There are plenty of other options out there. {% endhint %}
- D&D / TTRPG session for recording or streaming - by CharisSophia
- OBS and VDO.Ninja DJ Setup Guide - Community Written Guide
- How to add custom backgrounds and live video effects
- How to improve your video quality with some better lighting tricks
- How to see your camera's max resolution limit, and if it supports manual focus/zoom
- How to send output of your webcam only and not the entire output from OBS into VDO.Ninja
- How to apply a green screen to VDO.Ninja streams
- Info on using "chrome.exe --autoplay-policy=no-user-gesture-required" to force Auto-play in Chrome
- How to deploy your own TURN (relay) server
- Alternative domain names and other connection methods
- Consider the IFRAME API as an alternative to self-hosting VDO.Ninja
- How to test your Internet connection quality with a video-echo test
- How to host your own RTSP server for VDO.Ninja by using OBS with the OBS-RTSP-Server plugin
- How to improve streaming performance and reliability with a Speedify
- LAN vs WAN - VDO.Ninja traffic diagram - by saimiri 31
- Jon Myer VDO.Ninja Playlist
- Nilson1489 (German Tutorial) Basics
- Nilson1489 (German Tutorial) Rooms
- Record multiple sources in OBS Studio
- Control OBS using SocialStream using Touch Portal
- Control VDO.Ninja with Bitfocus Companion
- Control VDO.Ninja via Touch Portal
- How to stream to a Raspberry Pi and use as a remote monitor
- How to obfuscate (hide) the URL parameters for guest links
- How to do VDO.Ninja to NDI output
- How to view Twitch chat while using VDO.Ninja on mobile devices
- 3rd-party written How-To Guide for VDO.Ninja
- A tool to create editable URL invite links
Hardware-accelerated video encoding is a tricky topic; it can sometimes work, but when it does, it doesn't always work as hoped.
It generally only works with H264 video, but it may work with other codecs in rare cases.
On a Windows PC, a Chromium-based browser offers your best chance of it working. Every month it seems the support for hardware encoding improves, which is great. The viewer just needs to request H264 video from your computer for it to have a chance of working. &codec=h264
If it works, in the video stats window (CTRL + Click
), you'll see the video codec type to be listed as External Encoder, if the hardware acceleration is working. CPU load may not decrease always, and there isn't an easy way to tell which encoder is being used, but if it says the codec is h264
, then it's likely still using just software.\
Despite software using a lot of CPU, it offers better compatibility, fewer glitches, and technically can still handle dozens of video streams at a time if your CPU is fast enough. Hardware however can be finicky, where glitching is common and a hardware encoder typically can only support three video encoding sessions at a time.
What's really strange about hardware encoding on a PC is that it may actually use MORE CPU than the software-based openH264 alternative. If your goal is to save CPU power, a hardware encoder may just introduce more problems and offer no benefit at all; at least if encoding with a PC.
You can specify whether to use software or hardware H264 by changing the H264 profile ID; this can be specified, for example, using &h264profile=42e01f
. 42e01f
should trigger the OpenH264 software encoder, if available.
AMD systems, and some Intel systems, the default H264 hardware encoder will limit bitrates. Using VP8 or a software-based H264 encoder could allow for higher bitrates. The software VP8 encoder does seem to use more CPU than the H264 encoders, but it often is more stable, especially for screen shares.
On a MacOS system, Chrome may drop frame rates suddenly when using the H264 encoder.
On older versions of iOS, the H264 encoders can sometimes only support 720p30, while the VP8 software encoder on iOS can support 1080p. This recently changed with the iOS ~15, so newer iPhones can now support 1080p30 with H264. Your iPhone may still get very hot, so I am unsure if its actually hardware-accelerated; newer iPhones will do better than older.
In the past, iOS devices were limited by how many videos could be encoded using H264, often just three total, so keep that in mind. This might have changed with newer iPhones however; untested.
Many Android phones may not support H264 encoding in Chrome; this seems to vary based on the browser version, device chipset, and other factors. Trying to force H264 with such incompatible devices might result in no video, as the browser isn't always smart enough to know it isn't working. Chrome on Android doesn't seem to have a software-based H264 encoder.
One user has reported that while using Chrome, Brave, and Firefox with their Samsung S23+ has poor performance with video encoding, likely due to using software encoding, Microsoft's Edge browser on Android did make use of the hardware encoding. Performance in this case was near comparable to an iPhone 14 Pro's encoding performance. Users with other devices that also use a Snapdragon GPU may wish to try MS Edge if having lackluster video encoding performance.
With non-Snapdragon GPUs, such as found in entry-level and some mid-range smartphones, the hardware H264 encoder may not be available regardless of browser used. Using software-based encoders may trigger overheating or CPU throttling, especially at higher resolutions, so if you are unable to trigger hardware-encoding on a slower Android device, you may need to be content with lower resolutions and bitrates.
On the Google Pixel the H264/VP8 encoder will glitch like crazy when used in Portrait mode, however it's glitch free when using the VP9 codec via software encoding.
If a director, choosing to publish video to your group with H264 might reduce some CPU load, but if using an Nvidia graphics card, you may end up forfeiting your ability to use NVenc encoding for RTMP or MKV file recording, since Nvidia only offers typically three encoders. You can unlock this limit, but the benefits of using NVenc with VDO.Ninja often provides no benefits it seems over a software H264 option.
If using a CDN-service like meshcast.io, where a server redistributes the video to a large audience, H264 is highly compatible with most viewers, but this is only true for the OpenH264 profile ID 42e01f
of H264. Hardware-encoded version of H264 may not be compatible with all browsers, such as with Safari viewers, so its not advised.
OperaGX tends to have issues with H264 encoding.
On the bright side, H264 is supported well on macOS, and it seems to use less CPU to decode than VP8. H264 on OBS 27.1 and older (for PC) offers lower packet-loss-induced "rainbow puke" than the VP8 codec, but this isn't a factor anymore with OBS 27.2 and newer. On PC, VP8 and H264 seem to use about the same CPU to decode in OBS. I'd advise you to do your own testing though.
For many devices that are offering hardware accelerated encoding, a minimum or specific resolution is needed, else the device may switch back to software based encoding.
Sometimes this minimum resolution is 640x360, but other times it might be 1920x1080.
If you're comfortable with Linux, basic publishing into VDO.Ninja is available using GStreamer and Python. The project is located here: https://github.com/steveseguin/raspberry_ninja/
Hardware encoding with multiple viewer per encoded stream is supported with this option, although features are limited. It is not for the faint of heart; generally this approach is still reserved for hobbyists, enthusiasts, and developers. A Raspberry Pi can publish 1080p30 to VDO.Ninja, and supports HDMI connected cameras; at least when using this project's code.
Code and quick start deployment images are available for the Raspberry Pi and Nvidia Jetson embedded development boards, along with hardware-encoding support for those platforms.
Other Linux systems are support with the provided code, but it is up to you to ensure the hardware driver and configuration is setup correctly in those cases.
The project will hopefully keep expanding, to include more devices and operating systems.
While AV1 hardware encoders are not common at the moment, they should be supported as they are adopted by browsers and hardware manufactures. &codec=av1
H265/HEVC however isn't commonly supported by browsers, although Thorium / Safari browsers may support it, it's not an officially supported option. You can give it a try however by using &codec=h265
.
With OBS v30 supporting WHIP output, it's now possible to stream video directly from OBS to VDO.Ninja via WebRTC with hardware accelerated encoding.
There are limitations with OBS's WHIP implementation in version 30 however, which may get addressed in the future, but without a server supporting OBS's WHIP output currently, this option is primarily limited for single point to point video distribution on controlled networks.
You can however use OBS's WHIP output with an SFU server however, such as Cloudflare's WHIP/WHEP server, and VDO.Ninja can ingest the WHEP output from that. This setup would work a bit like how Meshcast works with VDO.Ninja currently, except with the source being specified as WHEP-based, rather than from Meshcast.
description: >- A common question on how to achieve the highest quality capture into OBS for a remote interview.
The highest quality possible is a bit tricky, as that will depend on certain factors that may be hard to determine without testing and tweaking in advanced.
Depending on what you're trying to do exactly, how many people are being interviewed, and your technical level of savviness, different options may appeal to you.
The VDO.Ninja group room has a director role, with everyone else being a guest.
The director can record locally in browser, to their own disk, or they can record remotely, to the guest's computer. The highest quality recording possible will be to record to the guest's own computer directly, bypassing the Internet. This however currently requires the guest send the recording to you afterwards, which introduces a risk of failure, nor is it always feasible.
While recording the stream as the director themselves is an option, via VDO.Ninja's director control center, better performance and more reliable results can be obtained by using OBS Studio to record the stream.
When using OBS to record, you may wish to use the provided solo-links for each guest, putting each into its own OBS Studio instance, and recording each guest independently. OBS Studio can be opened multiple times, and hardware accelerated encoding is often available up to 3 streams or more. You can also consider checking out https://obsproject.com/forum/resources/source-record.1285, which is a plugin for OBS that lets you record multiple sources at a time with one OBS instance.
If using OBS to record, configure OBS to record at a high bitrate, let's say 20,000-kbps, at perhaps 1920x1080 resolution. For each OBS browser source, which contains the solo-links, will we ensure they are 1920x1080 resolution also, and we will append &videobitrate=12000
&audiobitrate=160
to each view link.
You can speak to the guest via the director's control center, which will provide echo cancellation for the director's mic, and this provides the easiest setup and operation. If you want even more control over settings and optimizations though, but don't want a director role, you may way to try the next method.
In this mode, there is no group room, and all guest stream IDs need to be manually specified. You can typically get excellent 1080p recording quality though with the following parameters:
Guest link: https://vdo.ninja/?push=GUEST_ID&quality=0&proaudio&view=HOST_ID&vb=200&ab=16
Host link: https://vdo.ninja/?push=HOST_ID&view=GUEST_ID&vb=50&ab=16
OBS link*: https://vdo.ninja/?view=GUEST_ID&vb=12000&ab=128&scale=100
* Note the OBS Browser source should be set to a width of 1920 and a height of 1080.
The idea here is both you and the guest can talk to each other in the browser, at relatively very low quality, while in OBS you are capturing a very high quality version of just the guest. I'd imagine you can record the host locally in OBS, without needing VDO.Ninja in most cases.
I am also assuming the guest is wearing headphones; if not, you may need to remove &proaudio
from their invite link. Removing it will lower the audio quality, but with it added you will not have echo cancellation enabled.
You can improve the quality a small bit further with some added complexity, by having the host use OBS as the video/audio monitor when speaking to the guest, rather than pulling any audio/video in via a browser window. You can also consider using the Electron Capture app, instead of an OBS browser source, which will let you share one guest video stream with several apps via window-capture.
For the highest quality, you'll want to record the guest at their native resolution, so if each guest is 1080p resolution, you can capture 4 guests in OBS if OBS is recording at 4K resolution, or you can record each guest as their own independent video. Common options here could be to have multiple OBS instances being open, or by using the source-record plugin for OBS: https://obsproject.com/forum/resources/source-record.1285.
If doing screen shares, or overlays, adding a bit of sharpening as an OBS video effects filter can also help the recording look better. Sharpening will make lines and fine details, like hair, pop out a bit more. This is especially helpful for text, which is usually a bit soft in video otherwise.
The relatively new AV1 video codec offers better colors, better compression, and often better frame rates than other codecs. If your guest supports it, with a computer that won't overheat because of it, it might be worth trying.
Add &codec=av1
to the solo- or view-link of the guest you are recording, to get the system to prefer using it instead.
The biggest impact and limitation is normally the connection itself; please sure that both sides have excellent high-quality connections. Bad connections will ruin a stream.
Sometimes using &relay
or &meshcast
can help with certain bad connections, in rare cases at least. Meshcast can be used on the sender's side, while &relay
can be used on either/both side. Normally just avoiding WiFi can resolve many such packet loss issues though.
If the guest is on a mobile device, consider using a USB (lightning) to Ethernet adapter for that phone, to connect it to the Internet router directly, rather than using WiFi. If that isn't an option, bonded cellular connections may be an option for some users as well.
{% embed url="https://www.youtube.com/watch?v=je2ljlvLzlY" %}
If packet loss is a still serious issue, then there is a feature in VDO.Ninja to let you record the video directly on the guest's computer, remotely, bypassing the Internet during the recording itself. It's experimental though, so it might only be useful as a backup, but when it works, it's fantastic! The &record
option, added to the guest's link, will let them control the recording, if there is no director present to start/stop the recording.
If your phone is getting warm, putting a metal heatsink on the backside of the phone directly can help keep it from thermal throttling. You can also try changing codecs, to see if perhaps there is a better option.
As for laptops, ensure they are plugged in and are not overheating.
Some smartphones will have limited functionality if using an older version of the operating system. This is especially true of iOS devices, where iOS 16 has several core improvements over iOS 16, for example.
Certain browsers, such as Firefox, should also be avoided in most cases. Chromium-based browsers will offer better control over video bitrates, with more options and features to use.
Avoid Bluetooth or mobile devices for audio sources.
Also refer to &audiobitrate
or &proaudio
for options to improve audio bitrate.
The bitrate controls are accessible via a URL parameter that can be added to the VIEW link.
Something like https://vdo.ninja/?view=yyyyy&bitrate=10000 will let the viewer request set a 10-mbps bitrate; up to around 20000-kbps is reasonable, but higher is possible in situations. The value is in kilobits per second and the default bitrate is 2500-kbps.
The viewer sets the bitrate generally, although you can set maximum allowed bitrates as the publisher of a stream. See the advanced settings in the wiki for more help here; there are many options available.
When in a group room, the guests will generally get a very low-quality preview of the stream. This can be changed with the &totalroombitrate
parameter or via the room's director settings menu. The higher the room bitrate however, the more CPU and Network load will be placed on those in the room.
When dealing with a group scene link, you can use &bitrate
as normal, or &totalbitrate
. There are many other ways to control bitrates, in both rooms and push links, with these being the standard options.
Camera resolution by default is captured at 1280x720. You can increase this by changing the quality setting when selecting your camera, or by adding &quality=0
to the URL. The &quality
parameter acts as a preset, where &quality=0 is preset for 1920x1080 @ 60-fps, &quality=1
is 720p60, and &quality=2
is a gentle 360p30.
You can manually set the video resolution via the URL, using &width=1920&height=1080
, and this might be helpful when dealing with non-standard aspect-ratios.
{% hint style="info" %} If using the OBS Virtual Camera as a source, be sure to activate it in OBS before trying to access it with VDO.Ninja with non-standard resolutions set. {% endhint %}
The resolution can also be set on the viewer-side via the &scale=100
parameter. This scales down the resolution, as a percentage, based on the original camera capture resolution.
By default, VDO.Ninja will try to optimize and scale down the incoming resolution to fit the viewer's window size, but sometimes you might want to disable this. Adding &scale=100
to the view link can achieve that, as it forces 100% scale, or no scaling in other words.
VDO.Ninja may still scale the video down however, although only if the connection between the two peers is having network issues, if the sender's encoder is having issues, or if the set bitrate is too low to sustain the higher resolution.
You can improve audio quality in the same way, by increasing the &audiobitrate
, but you can get better results by just disabling noise and echo cancellation instead.
&proaudio
is flag that presets many audio options, which can be added to both the sender's and viewser's link to enable stereo audio with no audio processing and a very high audio bitrate set. You may need to be using headphones, especially if in a group room, if using &proaudio
or if disabling the echo cancellation features.
{% content-ref url="video-bitrate-for-push-view-links.md" %} video-bitrate-for-push-view-links.md {% endcontent-ref %}
{% content-ref url="video-bitrate-in-rooms.md" %} video-bitrate-in-rooms.md {% endcontent-ref %}
{% content-ref url="audio-filters.md" %} audio-filters.md {% endcontent-ref %}
The browser doesn't allow much control over the resolution, which is unfortunate. The published resolution will often change based on network conditions or CPU performance, but also if the bitrate for a video stream is too low.
There are still some options though:
- Ensure you and your viewers have rock solid Internet. Packet loss can cause the resolution to drop, so make sure to avoid packet loss.
- Increase the target bitrate by using
&videobitrate=20000
on the viewer side. If in a group room, consider using&meshcast
or increasing the total room bitrate. This is particularly true at higher resolutions with lots of motion. - Add
&scale=100
to the view links. This will disable any optimization VDO.Ninja applies to limit resolution based on window playback size. You can also try&scale=50
to lower the resolution, helping to keep the resolution stable at a lower resolution. - Adding
&contenthint=detail
to the guest's link is me telling the browser to "lock the resolution to something high", but it may still ignore it. This will tell the browser to lower frame rates instead of resolution, but in some cases the resolution may still drop. - Using
&chunked
on the guest invite links sends video over the data-channels instead, which is something that allows VDO.Ninja to lock the resolution / frame rate with, but this can be very troublesome to use and may increase latency a lot.
This is also experimental and can be buggy, so please report bugs and issues and over time it may be something I can more often recommend. - In some cases, you can have guests publish video via OBS's WHIP output into VDO.Ninja. This lacks a lot of functionality and remote control, but it should lock the resolution and frame rate. Missed frames and latency may be issues though.
- You can also publish video via Raspberry.Ninja, where I can control resolution also. Just like with OBS's WHIP output, frame loss may be an issue.
- You can record solo links in OBS Studio or with Vingester.app, which will record the inbound videos at a fixed resolution, despite the source having varying frame rates and resolutions. If recording at a high bitrate and with a touch of sharpness added, you can achieve great results.
Support for remote PowerPoint slide control. (previous/next slide):
- Documented things quite a bit here: https://github.com/steveseguin/powerpoint_remote
- I've only tested with Windows + PowerPoint so far, but it can be tweaked to work with more than PPT without much trouble
- Uses AutoHotKey + VDO.Ninja + MIDI to achieve the result; quite a few different ways implement it, with samples provided
- Built-in basic controller added, via
&powerpoint
(aliases:&slides
,&ppt
,&pptcontrols
) - IFrame sample app provided with larger buttons and sample code to add more custom buttons/actions if needed. (start/stop/etc): https://vdo.ninja/examples/powerpoint
- HTTP / WSS remote control also added;
https://api.vdo.ninja/YOURAPIKEY/nextSlide
andprevSlide
- Local Streamdeck support also working, via MIDI
{% embed url="https://youtu.be/ORH8betTt8Y" %} Remote control PowerPoint with VDO.Ninja {% endembed %}
&powerpoint
as a URL parameter
iPhones 12 and newer, running higher than iOS 16.0, and with the rear camera selected, can access 1080p60 video output in VDO.Ninja. This was tested last with Safari on an iPhone 12 Pro, running iOS 16.2 on VDO.Ninja v23. (May 5th 2023)
The actual frame rate of the video that the viewer receives may be lower than the 60 or 30-fps capture rate. It may end up ranging from 20-fps to 45-fps. As a result, limiting the capture frame rate of the device to 30-fps, such as with &maxframerate=30
, may help offer more stable frame rates, even if limited to 30-fps. So, 1080p30 may be preferable to 1080p60 in some cases.
Keep in mind, high motion and highly detailed scenes may also require higher bitrates; the default VDO.Ninja encoding bitrate is just barely suitable for stationary talking heads at 1080p60, but increasing the video bitrate to 4000-kbps, up to as high as 20000-kbps, may help.
1080p60 seems to work with H264 video encoding (default) and even VP9 video encoding, if enabled. On a side note, H265 (HEVC) may work Safari to Safari, but it is untested at present and may only work in highly controlled situations. The state of AV1 support though is quickly changing, and may be supported by iPhones in the near future. Both these newer codec options may be quite useful for when 4K streaming becomes more common.
As for older devices, iPhone 11 and older, they may only be able to achieve 1080p30 or 720p60 capture, assuming they are running iOS 16 and up. The front and rear cameras may achieve different frame rates or resolutions, depending on the device. You may need to experiment to find what works best for you specific iOS device, though such as if using an iPhone SE or iPad.
If selecting 1080p60, but getting 720p60, that may be the result of the device defaulting to 720p60 rather than 1080p30. Using &maxframerate=30&quality=0
, you might be able to to achieve 1080p30 instead.
For example, front facing cameras on an iPhone 6S might be able to achieve 720p60, but the rear camera may achieve 1080p30 max. Trying to force 1080p60 on the iPhone 6S may result in a lower resolution being actually selected, or an error message may appear.
Older versions of VDO.Ninja (v22 and older), and some specific iOS device models, may need some custom URL tweaking to get the maximum available resolution / frame rate.
You can force 1080p on many iPhones, but you then need to use &codec=vp8
also then on older iOS versions.
for example:
https://vdo.ninja/?push=streamid&width=1920&height=1080
and:
https://vdo.ninja/?view=streamid&codec=vp8&videobitrate=6000
Older iOS versions do not support h264 at resolutions higher than 720p30.
If you use VP8 though, you will be using the software-based encoder, which will make the iPhone pretty warm/hot. It also only works only on newer iOS versions (iOS 14, for example).
In newer versions of iOS , it's possible to do 1080p60 with H264 encoding, but only under specific circumstances.
description: >- Guest invites can be configured to ensure guests join with the same stream ID every time they join, allowing for reusable view- and solo-links.
If you connect with the &push=xxxx
URL parameter set, you essentially are telling the system what you want the 'view=' ID to be. In this case, it would be xxxx
. This value is referred to as the "stream ID".
As long as the stream ID is not already in use, you can use it to identify the stream you or a guest is publishing with. In so doing, you can ensure you always connect with the same stream ID, making subsequent view- and solo- links reusable.
If a guest joins a room without the &push
value set in advanced, their URL will update to include a randomly generated &push
value once they start streaming. So, if a guest refreshes their page once they start streaming, they will rejoin with the same stream ID, as the stream ID will be embedded in the URL at that point.
However, if a guest re-joins the room using the original invite link, which didn't have a &push
value included in it, they will be assigned a new &push
value once they rejoin.
It's important to note as well that you should not copy and share your VDO.Ninja URL after you've already started streaming, as your URL will contain your unique stream ID at that point. Share the original invite link instead, or modify the URL so it includes a different and unique stream ID to avoid conflicts.
A &push
ID can be up to around 40-characters in length, using alphanumeric characters, and it can be pretty much anything you want to make up. You don't need to register anything; it just needs to be unique, and preferably, random enough so that it is secure from others also picking the same value.
While you can use a name as a stream ID, it's not very secure to do so. Instead, you can label your streams with &label
to make it easier to identify. &showlabels
will then show those labels via a video overlay if you want as well.
You can also use &permaid
on a guest invite link, which will save the randomly generated stream ID to the guest's local browser storage. Every time they rejoin, their stream ID kept in local storage will be reused. With this approach, you do not need to set a stream ID ahead of time, and as long as the guest doesn't clear their cache, change computers, or use a different browser, the stream ID won't change.
Another option is to not use stream IDs at all to specify a video to load into OBS, etc. Instead, you can use custom scenes. Scene 1, S2, S3, etc. When a guest joins a room, you can simply assign the guest to a specific scene, and that scene link in OBS would be unchanging. Guests would not automatically be assigned to a scene, so you'd need to manually do that, but you don't need to update any URL in OBS with this approach.
Like the above, you can also use the VDO.Ninja Mixer App (https://vdo.ninja/mixer) to have custom layouts, with "slots", and you can assign guests as they join to certain slots. You can have the system auto-assign guests to the first available slot also, or manually do so.
There are perhaps other ways of doing this as all as well, but for most users, specifying a custom stream ID for each guest is recommended. The use of a spreadsheet to keep track of invites for guests is a great way to manage this, and with the use of URL forwarding services, like short.io, you can also change a guest's VDO.Ninja invite link retroactively, via the shortening service.
To get a video to mirror while full-screened, you have a few options.
One is to just full screen the browser itself; F11 on most desktops. The video itself may not be fullscreen, but the browser will be and should be pretty close to perfect. Adding &hideheader
can hide any menu bars, if there are any.
Another option that is undergoing experimental testing as of Sept 23rd 2020 is to use the &effects
option, with &effects=2
applying a mirrored effect to the video before publishing the video.
Push Link
https://vdo.ninja/?push=SOMESTREAMID&effects=2
View Link
https://vdo.ninja/?view=SOMESTREAMID
So by adding &effects=2
, the video will be mirrored in a way that can be full screened. There are some limitations with this approach still, but I'm curious to get your feedback.
description: >- Maintaining a smooth 1080p60 can be tricky, but there are variety of options to achieve the desired results
To maintain a high quality 1080p60 stream, especially if screen sharing game content, you'll want at least 12-mbps to 20-mbps of upload bandwidth.
You'll also need a pristine Internet connection to maintain a low-latency and smooth result; you can test your connect at https://vdo.ninja/speedtest. High packet loss will limit the possibility of maintaining both low-latency and high quality video; in such a case, you'll need to prioritize one over the other.
https://vdo.ninja/?push=SOMESTREAMID&screenshare&quality=0
Alias: https://vdo.ninja/?push=SOMESTREAMID&ss&q=0
Copy one of the two links above and change SOMESTREAMID into a different name. The name picked just needs to be a unique alphanumeric value is not already in active use.
You can also add &fps=60
to the link, to attempt to force 60-fps, but the default with &quality=0
is already 60-fps.
https://vdo.ninja/?view=SOMESTREAMID&videobitrate=10000&scale=100
Alias: https://vdo.ninja/?v=SOMESTREAMID&vb=10000&scale=100
Copy one of the two links above and change SOMESTREAMID in the same name as you did for the Push Link. You can change &videobitrate=10000
to another value if you want to change the bitrate.
Parameter | Explanation |
---|---|
Push Link | |
&push=SOMESTREAMID |
sets a unique stream ID |
&screenshare |
selects screen sharing instead of webcam |
&quality=0 |
sets the resolution to 1920x1080p |
View Link | |
&view=SOMESTREAMID |
selects the stream ID |
&videobitrate=10000 |
sets the video bitrate to 10,000-kbps, you can change the value if you want |
&scale=100 |
tells the system to not scale down the screen share |
{% hint style="info" %}
If you have problems maintaining good video quality, you can add &codec=av1
to the viewer's side to see if it makes the screen share any better. AV1 is a newer codec with better compression efficiency. H264, VP8, and VP9 are other options to try.
{% endhint %}
Screen sharing at 60-fps is the default, but sometimes this does not always work.
You can try forcing 60-fps by adding &fps=60
to the source (sender-side link). If you get an error, you can try using &maxframerate=60
instead.
Try disabling variable refresh rates, such as those offered by Freesync or G-Sync.
{% hint style="warning" %}
You may not achieve 60 FPS depending on your hardware, the browser or the type of screen share you use or the viewer uses.
Sharing a chrome window or tab is the best way to get 60 FPS consistently. If you share your screen or any other window you might only get 30 FPS.
Screen sharing a "Window" with Chrome (chromium) tends max out at ~42 FPS, while screen sharing via "Entire Screen" tends to make out close to 59 FPS.
{% endhint %}
You can use the &contenthint
parameter in some browsers to suggestion whether to prioritize frame rate or resolution. Sometimes getting both high isn't possible.
and-contenthint.md
and-screensharecontenthint.md
These parameters take detail or motion as a value, based on whether you value resolution or frame rate.
For an e-sports optimized version of VDO.Ninja, with many of the settings pre-confi