Discord auto-publisher
capturevideo.js is a Chrome extension content script. It finds the <video> elements on a page such as Discord, captures each one, and publishes them all into one VDO.Ninja room with the SDK, so you can pull every participant into OBS or a VDO.Ninja scene.
This page documents the script; it does not run it. The script only works inside a Chrome extension: it reads its on/off setting from chrome.storage and talks to the extension's background script, and it patches RTCPeerConnection on the page it is injected into.
Install
- Copy the files
vdoninja-sdk.jsanddemos/capturevideo.jsinto your extension folder. - Register both as content scripts in
manifest.json, SDK first (see below). - Turn it on. The script stays idle until
vdoninjadiscordistrueinchrome.storage.local, or your background script answers itsgetSettingsmessage with that setting. - Join a Discord video call. Each video gets a small overlay with View and Copy links, and a banner shows the link for the whole room.
Manifest
Load the SDK before the script; capturevideo.js exits early if VDONinjaSDK is not defined. The storage permission is needed for chrome.storage.
{
"permissions": ["storage"],
"content_scripts": [{
"matches": ["https://discord.com/*"],
"js": [
"vdoninja-sdk.js",
"capturevideo.js"
],
"run_at": "document_start"
}]
}
How it uses the SDK
For every video it finds, the script creates its own SDK instance in one shared, randomly named room, then connects, joins the room, and publishes the captured stream. This is the configuration in capturevideo.js:
const ROOM_ID = 'autopublish_' + Math.random().toString(36).substring(7);
const vdo = new VDONinjaSDK({
room: ROOM_ID,
salt: "vdo.ninja", // Ensure compatibility with VDO.Ninja
// password not specified - will use default password
debug: true
});
// stream = videoElement.captureStream(30), plus any audio it can find
await vdo.connect();
await vdo.joinRoom({ room: ROOM_ID });
await vdo.publish(stream, {
streamID: streamId,
label: label || ''
});
Because no password is passed, the SDK uses its shared default password (someEncryptionKey123). With the vdo.ninja salt, that matches VDO.Ninja's own defaults, so ordinary vdo.ninja links can view the streams. Signaling is not private: anyone who learns the room name can watch.
- The stream label comes from the page when it can find one (a Discord username, a Teams tile name, a video title). The overlay shows it as plain text.
- When a video is removed from the page, the script disconnects that video's SDK instance.
Watching the streams
The room name is random each time the page loads. The script logs it to the browser console (Room ID: and View URL:), and the on-page overlays link to it.
| What | Link |
|---|---|
| Every video in one scene | https://vdo.ninja/?room=autopublish_XXXXX&scene |
| One video | https://vdo.ninja/?room=autopublish_XXXXX&view=STREAM_ID&solo |
To test: load the unpacked extension, enable the setting, open a Discord channel with video, then open the console and follow the View URL it prints.