This commit is contained in:
legop3
2025-11-14 02:29:11 -05:00
parent 588c7aa571
commit 440325296c
10 changed files with 56 additions and 19 deletions
+2 -1
View File
@@ -4,7 +4,8 @@
"private": true,
"scripts": {
"start": "node index.js",
"dev": "nodemon index.js"
"dev": "nodemon index.js",
"check:media": "node scripts/checkMedia.js"
},
"dependencies": {
"bcrypt": "^6.0.0",
+1
View File
@@ -82,6 +82,7 @@ registerModule('spectator/main', (require, exports) => {
videoPlayer
.startStream(playerId, {
url: resp.url,
token: resp.token,
mount: wrap,
onStatus: (state, detail) => {
if (state === 'playing') {
+2 -1
View File
@@ -152,10 +152,11 @@ registerModule('services/roverUI', (require, exports) => {
videoPlayer.stopStream('driver');
return;
}
const { url } = resp;
const { url, token } = resp;
videoPlayer
.startStream('driver', {
url,
token,
mount: videoContainer,
videoEl: driverVideo,
onStatus: (state, detail) => {
+2 -12
View File
@@ -70,8 +70,7 @@ registerModule('services/videoPlayer', (require, exports) => {
};
this.attachAutoPlayLoop();
const credential = token || extractSessionToken(url);
if (!credential) {
if (!token) {
throw new Error('Missing video session token');
}
const offer = await this.pc.createOffer();
@@ -80,7 +79,7 @@ registerModule('services/videoPlayer', (require, exports) => {
method: 'POST',
headers: {
'Content-Type': 'application/sdp',
Authorization: `Basic ${btoa(`${credential}:${credential}`)}`,
Authorization: `Basic ${btoa(`${token}:${token}`)}`,
},
body: offer.sdp,
});
@@ -120,15 +119,6 @@ registerModule('services/videoPlayer', (require, exports) => {
}
}
function extractSessionToken(url) {
try {
const parsed = new URL(url, window.location.origin);
return parsed.searchParams.get('session');
} catch (err) {
return null;
}
}
async function startStream(id, { url, token, mount, videoEl, onStatus } = {}) {
stopStream(id);
const player = new Player(id, { mount, videoEl, onStatus });
+40
View File
@@ -0,0 +1,40 @@
#!/usr/bin/env node
const http = require('http');
const api = process.env.MEDIAMTX_API || 'http://127.0.0.1:9997';
function fetchJSON(path) {
return new Promise((resolve, reject) => {
const req = http.request(api + path, (res) => {
let data = '';
res.on('data', (chunk) => (data += chunk));
res.on('end', () => {
try {
resolve(JSON.parse(data));
} catch (err) {
reject(err);
}
});
});
req.on('error', reject);
req.end();
});
}
async function main() {
const list = await fetchJSON('/v3/paths/list');
if (!list.items || !list.items.length) {
console.log('No active paths');
return;
}
list.items.forEach((item) => {
console.log(
`${item.name.padEnd(12)} ready=${item.ready} tracks=${item.tracks.join(',') || 'none'} bytes=${item.bytesReceived}`
);
});
}
main().catch((err) => {
console.error('check-media failed:', err.message);
process.exit(1);
});
+1 -2
View File
@@ -23,8 +23,7 @@ function canView(socket) {
app.post('/mediamtx/auth', (req, res) => {
const body = req.body || {};
const path = (body.path || '').replace(/^\//, '');
const params = new URLSearchParams(body.query || '');
const sessionId = params.get('session');
const sessionId = body.user;
const roverId = path;
if (!sessionId || !roverId) {
+2 -2
View File
@@ -37,8 +37,8 @@ io.on('connection', (socket) => {
throw new Error('Not authorized for video');
}
const sessionId = videoSessions.createSession(socket, roverId);
const url = `${mediaConfig.whepBaseUrl.replace(/\/$/, '')}/${roverId}?session=${sessionId}`;
cb({ url });
const url = `${mediaConfig.whepBaseUrl.replace(/\/$/, '')}/${roverId}`;
cb({ url, token: sessionId });
} catch (err) {
logger.warn('video request failed: %s', err.message);
cb({ error: err.message });