update pi video publisher

This commit is contained in:
legop3
2025-11-15 15:04:46 -05:00
parent 6d4aacb903
commit 2e1186a482
5 changed files with 49 additions and 16 deletions
+2 -2
View File
@@ -13,8 +13,8 @@ source "$ENV_FILE"
: "${PUBLISH_URL:?PUBLISH_URL not set in ${ENV_FILE}}" : "${PUBLISH_URL:?PUBLISH_URL not set in ${ENV_FILE}}"
VIDEO_WIDTH="${VIDEO_WIDTH:-1280}" VIDEO_WIDTH="${VIDEO_WIDTH:-640}"
VIDEO_HEIGHT="${VIDEO_HEIGHT:-720}" VIDEO_HEIGHT="${VIDEO_HEIGHT:-480}"
VIDEO_FPS="${VIDEO_FPS:-30}" VIDEO_FPS="${VIDEO_FPS:-30}"
VIDEO_BITRATE="${VIDEO_BITRATE:-3000000}" VIDEO_BITRATE="${VIDEO_BITRATE:-3000000}"
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -5,7 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" /> <link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>webui</title> <title>webui</title>
<script type="module" crossorigin src="/assets/index-_yFT6hTb.js"></script> <script type="module" crossorigin src="/assets/index-CVsa8jPZ.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-CIpY4YLn.css"> <link rel="stylesheet" crossorigin href="/assets/index-CIpY4YLn.css">
</head> </head>
<body> <body>
+35 -2
View File
@@ -1,3 +1,13 @@
const RTC_CONFIG = {
iceServers: [
{ urls: 'stun:stun.l.google.com:19302' },
{ urls: 'turn:your.turn.server:3478', username: 'user', credential: 'pass' },
],
bundlePolicy: 'max-bundle',
rtcpMuxPolicy: 'require',
};
function buildAuthHeader(token) { function buildAuthHeader(token) {
if (!token) return {}; if (!token) return {};
const credential = `${token}:${token}`; const credential = `${token}:${token}`;
@@ -22,19 +32,33 @@ export class WhepPlayer {
} }
} }
configureVideoElement() {
if (!this.video) return;
this.video.playsInline = true;
this.video.autoplay = true;
this.video.disableRemotePlayback = true;
if ('latencyHint' in HTMLMediaElement.prototype) {
this.video.latencyHint = 'interactive';
}
}
async start() { async start() {
if (!this.url || !this.video) { if (!this.url || !this.video) {
throw new Error('Video target missing'); throw new Error('Video target missing');
} }
this.stop(); this.stop();
this.notify('connecting'); this.notify('connecting');
this.configureVideoElement();
this.abortController = new AbortController(); this.abortController = new AbortController();
const pc = new RTCPeerConnection(); const pc = new RTCPeerConnection(RTC_CONFIG);
this.pc = pc; this.pc = pc;
const stream = new MediaStream(); const stream = new MediaStream();
pc.ontrack = (event) => { pc.ontrack = (event) => {
event.streams[0]?.getTracks().forEach((track) => stream.addTrack(track)); event.streams[0]?.getTracks().forEach((track) => stream.addTrack(track));
this.video.srcObject = stream; this.video.srcObject = stream;
if (track.kind === 'video' && 'playoutDelayHint' in event.receiver) {
event.receiver.playoutDelayHint = 0;
}
}; };
pc.addTransceiver('video', { direction: 'recvonly' }); pc.addTransceiver('video', { direction: 'recvonly' });
pc.addTransceiver('audio', { direction: 'recvonly' }); pc.addTransceiver('audio', { direction: 'recvonly' });
@@ -51,7 +75,10 @@ export class WhepPlayer {
}; };
try { try {
const offer = await pc.createOffer(); const offer = await pc.createOffer({
offerToReceiveAudio: true,
offerToReceiveVideo: true,
});
await pc.setLocalDescription(offer); await pc.setLocalDescription(offer);
const response = await fetch(this.url, { const response = await fetch(this.url, {
@@ -68,6 +95,12 @@ export class WhepPlayer {
} }
const answerSdp = await response.text(); const answerSdp = await response.text();
await pc.setRemoteDescription({ type: 'answer', sdp: answerSdp }); await pc.setRemoteDescription({ type: 'answer', sdp: answerSdp });
pc.getReceivers().forEach((receiver) => {
if ('playoutDelayHint' in receiver) {
receiver.playoutDelayHint = 0;
}
});
await this.video.play().catch(() => {});
this.notify('playing'); this.notify('playing');
} catch (err) { } catch (err) {
this.notify('error', err.message); this.notify('error', err.message);