mirror of
https://github.com/legop3/MultiRoombaRover.git
synced 2026-09-16 01:21:20 -04:00
update pi video publisher
This commit is contained in:
@@ -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
@@ -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>
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
Reference in New Issue
Block a user