Skip to content

Commit 620aa65

Browse files
authored
Merge branch 'steveseguin:develop' into develop
2 parents 76fd4e3 + e93c2eb commit 620aa65

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+71186
-30189
lines changed

.github/workflows/static.yml

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# Simple workflow for deploying static content to GitHub Pages
2+
name: Deploy static content to Pages
3+
4+
on:
5+
# Runs on pushes targeting the default branch
6+
push:
7+
branches: ["develop"]
8+
9+
# Allows you to run this workflow manually from the Actions tab
10+
workflow_dispatch:
11+
12+
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
13+
permissions:
14+
contents: read
15+
pages: write
16+
id-token: write
17+
18+
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
19+
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
20+
concurrency:
21+
group: "pages"
22+
cancel-in-progress: false
23+
24+
jobs:
25+
# Single deploy job since we're just deploying
26+
deploy:
27+
environment:
28+
name: github-pages
29+
url: ${{ steps.deployment.outputs.page_url }}
30+
runs-on: ubuntu-latest
31+
steps:
32+
- name: Checkout
33+
uses: actions/checkout@v4
34+
- name: Setup Pages
35+
uses: actions/configure-pages@v5
36+
- name: Upload artifact
37+
uses: actions/upload-pages-artifact@v3
38+
with:
39+
# Upload entire repository
40+
path: '.'
41+
- name: Deploy to GitHub Pages
42+
id: deployment
43+
uses: actions/deploy-pages@v4

.prettierrc

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"semi": true,
3+
"singleQuote": false,
4+
"tabWidth": 4,
5+
"useTabs": true,
6+
"bracketSpacing": true,
7+
"jsxBracketSameLine": false,
8+
"arrowParens": "avoid",
9+
"trailingComma": "none",
10+
"printWidth": 10000
11+
}

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ For more advanced users, you can see the [install.md](https://github.com/stevese
3939

4040
If self-hosting, you might also wish to host your own video relay TURN server. Directions on how to deploy a TURN server are listed in the turnserver.md file. Only about ~ 5% of remote guests usually will need a TURN server, often those connected via 4G LTE or those behind a strict firewall, but most other users don't need one. While VDO.Ninja does host some pubiic TURN servers, they are quite expensive to operate, so please try to avoid abusing if possible. If you are deploying your own version of VDO.Ninja, I'd ask you to use your own TURN servers if you are capable of doing so; it's understandable if you aren't able to though.
4141

42-
For users wishing to host VDO.Ninja offline (where no Internet is available), there's a respository with everything needed to deploy locally and offline here: https://github.com/steveseguin/offline_deployment. The offline version includes a Docker option, and there are some community-created Dockers available for online hosting. I may eventually offer an official Docker option designed for online users with heavier requirements, but I lack time and support to maintain such a project currently.
42+
For users wishing to host VDO.Ninja offline (where no Internet is available), there's a repository with everything needed to deploy locally and offline here: https://github.com/steveseguin/offline_deployment. The offline version includes a Docker option, and there are some community-created Dockers available for online hosting. I may eventually offer an official Docker option designed for online users with heavier requirements, but I lack time and support to maintain such a project currently.
4343

4444
### Develop vs Release versions
4545

@@ -64,7 +64,7 @@ Join me and the community on Discord for support and more: https://discord.vdo.n
6464

6565
The sub-Reddit is available at, https://reddit.com/r/vdoninja. I will often offer a single-message response to support questions posted there, but for deeper discussion, join the Discord.
6666

67-
Also check out the FAQ for common answers: https://docs.vdo.ninja or view recent product updates at https://updates.vdo.ninja
67+
Also check out the FAQ for common answers: https://docs.vdo.ninja or view recent product updates at: https://updates.vdo.ninja
6868

6969
I maintain a Youtube playlist with VDO.Ninja related content I create at https://www.youtube.com/watch?v=vLpRzMjUDaE&list=PLWodc2tCfAH1WHjl4WAOOoRSscJ8CHACe, however Youtube is full of community-created guides that are worth checking out.
7070

base64.html

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>VDO.Ninja CSS to Base64 Converter</title>
7+
<style>
8+
body {
9+
font-family: Arial, sans-serif;
10+
background-color: #1E1E1E;
11+
color: #E0E0E0;
12+
max-width: 800px;
13+
margin: 0 auto;
14+
padding: 20px;
15+
}
16+
h1, h2 {
17+
color: #E0E0E0;
18+
}
19+
textarea {
20+
width: 100%;
21+
height: 200px;
22+
margin-bottom: 10px;
23+
background-color: #2D2D2D;
24+
color: #E0E0E0;
25+
border: 1px solid #3D3D3D;
26+
border-radius: 4px;
27+
padding: 10px;
28+
font-family: monospace;
29+
}
30+
#output {
31+
height: 100px;
32+
}
33+
button {
34+
padding: 10px 20px;
35+
background-color: #4ecca3;
36+
color: #1E1E1E;
37+
border: none;
38+
border-radius: 4px;
39+
cursor: pointer;
40+
font-weight: bold;
41+
transition: background-color 0.3s;
42+
}
43+
button:hover {
44+
background-color: #45b392;
45+
}
46+
.container {
47+
background-color: #2D2D2D;
48+
padding: 20px;
49+
border-radius: 8px;
50+
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
51+
}
52+
</style>
53+
</head>
54+
<body>
55+
<div class="container">
56+
<h1>VDO.Ninja CSS to Base64 Converter</h1>
57+
<textarea id="cssInput" placeholder="Enter your CSS here..."></textarea>
58+
<button onclick="convertToBase64()">Convert</button><br><br>
59+
<i>💡Tip: Adding <b>!important</b> after your CSS values can help override existing values.</i>
60+
61+
<h2>Output:</h2>
62+
<textarea id="output" readonly></textarea>
63+
<button onclick="copyToClipboard()">Copy to Clipboard</button>
64+
</div>
65+
<script>
66+
function convertToBase64() {
67+
const cssInput = document.getElementById('cssInput').value;
68+
// Remove tabs and extra spaces
69+
const sanitizedCSS = cssInput.replace(/\s+/g, ' ').trim();
70+
const base64CSS = btoa(encodeURIComponent(sanitizedCSS));
71+
document.getElementById('output').value = '&cssb64=' + base64CSS;
72+
}
73+
function copyToClipboard() {
74+
const output = document.getElementById('output');
75+
output.select();
76+
document.execCommand('copy');
77+
alert('Copied to clipboard!');
78+
}
79+
</script>
80+
</body>
81+
</html>

cloudflare.html

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -124,22 +124,19 @@ <h1>Generate Cloudflare Auth for VDO.Ninja</h1>
124124
<h2>
125125
What you can do with Cloudflare + VDO.Ninja?
126126
</h2>
127-
<h3>Restream VDO.Ninja as an RTMP Output</h3>
128-
<p>Live Video Inputs (Cloudflare feature) can be set up to forward any input to another input. This can be a RTMP(S) service such as YouTube, Twitch or Facebook Live.</p>
129-
<p>In theory you could publish from VDO.Ninja WHIP output to Cloudstream, and then to your RTMP destinations, like Youtube.</p>
130-
<p></p>
131127
<h3>Meshcast-alternative</h3>
132128
<p>Instead of using Meshcast to broadcast video from director to guest, or guest to scene, you can use Cloudflare instead.</p>
133129
<p>Meshcast, or any compatible WHIP/WHEP service, can help reduce CPU and network load of guests by offloading distribution to a server, compared to using the peer-to-peer default of VDO.Ninja
134-
<h3>Automatic isolated guest recording</h3>
135-
<p>Cloudflare will automatically record incoming videos, allowing you (in theory) to have a backup of each guest in a room.</p>
130+
<p>VDO.Ninja has built-in support for Cloudflare's WHIP/WHEP, so setup and use is relatively easy.</p>
131+
<h3>Isolated guest recording remotely via WHEP</h3>
132+
<p>You can record the streams of each guest via WHEP remotely, without transcoding and without additional load on the guests.</p>
136133
<p>This offers a redundant backup for your recordings, but also makes it easier to do higher quality VODs edits after the live ends.</p>
137-
<h3>SRT, HLS, DASH, MP4, WHIP/WHEP options</h3>
138-
<p>Lots input and output options, although if you're here, you're probably interested in the WHIP/WHEP mainly.</p>
139-
<p>VDO.Ninja is compatible with WHEP and WHIP!</p>
140-
<h3>Very competitive pricing</h3>
141-
<p>There's a $5 entry tier, which is more than enough for testing.</p>
142-
<p>Or pay $1 per 1000 minutes of streaming.</p>
134+
<p>Raspberry.Ninja offers WHEP recording, via GStreamer for example, but FFMpeg builds may also support direct WHEP recording</p>
135+
<h3>Pricing</h3>
136+
<p>Cloudflare has decent pricing, however it's a bit obsecure at times what the limits actually are.</p>
137+
<h3>MediaMTX</h3>
138+
<p>If you prefer rolling your own SFU service, VDO.Ninja supports MediaMTX. (open-source!)</p>
139+
<p>Just add <b>&mediamtx=yourdomain.com</b> to your VDO.Ninja publishing URLs to have it use your own MediaMTX server.
143140
</div>
144141
</div>
145142
<div class='secondary'>

comms.html

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1093,6 +1093,16 @@
10931093
mobile = true;
10941094
}
10951095

1096+
var videoMode = false;
1097+
if (urlParams.has('video')){
1098+
videoMode = true;
1099+
}
1100+
1101+
var chat = true;
1102+
if (urlParams.has('hidechat')){
1103+
chat = false;
1104+
}
1105+
10961106
if (screen.height && screen.width && (screen.height*screen.width<400000)){
10971107
mobile = true;
10981108
}
@@ -1805,10 +1815,15 @@
18051815
var chatmsg = "Welcome to the Comms app. Select a group to participate in.";
18061816
chatmsg = encodeURIComponent(chatmsg);
18071817

1818+
var vtype = "&vd=0";
1819+
if (videoMode){
1820+
vtype = "&ad=0";
1821+
}
1822+
18081823
if (window.location.hostname == "comms.cam"){
1809-
var iframesrc = "https://vdo.ninja/?"+urlEdited+"&controlbarspace&volumecontrol&sharperscreen&groupmode&novice&ltb=350&minipreview&transparent&hideheader&margin&rounded&hidetranslate&cleandirector&vd=0&webcam&nvb&sstype=3&ssb&showlabel=toprounded&labelsize=85&style=2&room="+roomname+additional+additional2+"&b64css="+injectCSS+streamID+label+"&chatmsg="+chatmsg;
1824+
var iframesrc = "https://vdo.ninja/?"+urlEdited+vtype+"&controlbarspace&volumecontrol&sharperscreen&groupmode&novice&ltb=350&minipreview&transparent&hideheader&margin&rounded&hidetranslate&cleandirector&webcam&nvb&sstype=3&ssb&showlabel=toprounded&labelsize=85&style=2&room="+roomname+additional+additional2+"&b64css="+injectCSS+streamID+label+"&chatmsg="+chatmsg;
18101825
} else {
1811-
var iframesrc = "./index.html?"+urlEdited+"&controlbarspace&volumecontrol&sharperscreen&groupmode&novice&ltb=350&minipreview&transparent&hideheader&margin&rounded&hidetranslate&cleandirector&vd=0&webcam&nvb&sstype=3&ssb&showlabel=toprounded&labelsize=85&style=2&room="+roomname+additional+additional2+"&b64css="+injectCSS+streamID+label+"&chatmsg="+chatmsg;
1826+
var iframesrc = "./index.html?"+urlEdited+vtype+"&controlbarspace&volumecontrol&sharperscreen&groupmode&novice&ltb=350&minipreview&transparent&hideheader&margin&rounded&hidetranslate&cleandirector&webcam&nvb&sstype=3&ssb&showlabel=toprounded&labelsize=85&style=2&room="+roomname+additional+additional2+"&b64css="+injectCSS+streamID+label+"&chatmsg="+chatmsg;
18121827
}
18131828

18141829

@@ -1824,7 +1839,12 @@
18241839

18251840
if (!mobile){
18261841
document.getElementById("chatModule").classList.remove("hidden");
1827-
}
1842+
if (!chat){
1843+
toggleChat();
1844+
}
1845+
}
1846+
1847+
18281848

18291849
iframe.onload = function(){
18301850
iframe.contentWindow.postMessage({ groups: savedSession.activeGroups , groupView: savedSession.activeViewGroups }, "*");

convert.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<head>
2-
<link rel="stylesheet" href="./main.css?ver=40" />
2+
<link rel="stylesheet" href="./main.css" />
33
<style>
44
.container {
55
max-width: min(80%,875px);

devices.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<html>
22
<head>
33
<link rel="stylesheet" href="./lineawesome/css/line-awesome.min.css" />
4-
<link rel="stylesheet" href="./main.css?ver=11" />
4+
<link rel="stylesheet" href="./main.css" />
55
<link rel="stylesheet" href="./devices.css?ver=2" />
66
<meta name="viewport" content="width=device-width, initial-scale=1" />
77
<meta charset="utf8" />

dock.html

Lines changed: 20 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -194,31 +194,27 @@
194194
}
195195

196196
document.addEventListener("dragstart", event => {
197-
var url = event.target.href || event.target.value;
198-
199-
if (!url || !url.startsWith('https://')) return;
200-
if (event.target.dataset.drag!="1"){
201-
return;
202-
}
203-
//event.target.ondragend = function(){event.target.blur();}
204-
205-
var streamId = url.split('view=');
206-
var label = url.split('label=');
207-
208-
url += '&layer-name=OBSN';
209-
if (streamId.length>1) url += ': ' + streamId[1].split('&')[0];
210-
if (label.length>1) url += ' - ' + decodeURI(label[1].split('&')[0]);
211-
197+
var url = event.target.href || event.target.value;
198+
199+
if (!url || !url.startsWith('https://')) return;
200+
if (event.target.dataset.drag !== "1") return;
201+
202+
var streamId = url.split('view=');
203+
var label = url.split('label=');
212204

213-
url += '&layer-width=1920'; // this isn't always 100% correct, as the resolution can fluxuate, but it is probably good enough
214-
url += '&layer-height=1080';
215-
216-
event.dataTransfer.setDragImage(document.querySelector('#dragImage'), 24, 24);
217-
event.dataTransfer.setData("text/uri-list", encodeURI(url));
218-
//event.dataTransfer.setData("url", encodeURI(url));
219-
220-
//warnlog(event);
221-
205+
url += '&layer-name=VDO.Ninja';
206+
if (streamId.length > 1) url += ': ' + streamId[1].split('&')[0];
207+
if (label.length > 1) url += ' - ' + decodeURI(label[1].split('&')[0]);
208+
209+
// Add layer dimensions
210+
url += '&layer-width=1920';
211+
url += '&layer-height=1080';
212+
213+
event.dataTransfer.setDragImage(document.querySelector('#dragImage'), 24, 24);
214+
event.dataTransfer.setData("text/uri-list", encodeURI(url));
215+
216+
// Add this line to set the URL as plain text as well
217+
event.dataTransfer.setData("text/plain", encodeURI(url));
222218
});
223219

224220
</script>
@@ -285,7 +281,6 @@ <h3>OBS Browser Source Link:</h3>
285281
<input id="obs-link" class="task red" data-drag="1" onmousedown="copyFunction(this)" onclick="copyFunction(this)" />
286282
<br />
287283
<br />
288-
<i>(links are draggable)</i>
289284
</div>
290285
</div>
291286
<div class="gone" >

0 commit comments

Comments
 (0)