This commit is contained in:
legop3
2026-01-17 20:28:16 -05:00
parent 7041a3c6df
commit 66b8c839b7
7 changed files with 32 additions and 10 deletions
+1
View File
@@ -16,6 +16,7 @@ media:
preview: preview:
enabled: false enabled: false
codec: "av1" codec: "av1"
transport: "rtsp"
fps: 10 fps: 10
width: 640 width: 640
roomBitrateKbps: 200 roomBitrateKbps: 200
+1 -1
View File
@@ -8,7 +8,7 @@ metricsAddress: 0.0.0.0:9998
pprof: no pprof: no
pprofAddress: 127.0.0.1:9999 pprofAddress: 127.0.0.1:9999
rtsp: no rtsp: yes
rtmp: no rtmp: no
hls: no hls: no
@@ -12,6 +12,7 @@ const previewConfig = mediaConfig.preview || {};
const ENABLED = Boolean(previewConfig.enabled); const ENABLED = Boolean(previewConfig.enabled);
const PREVIEW_CODEC = String(previewConfig.codec || 'av1').toLowerCase(); const PREVIEW_CODEC = String(previewConfig.codec || 'av1').toLowerCase();
const PREVIEW_TRANSPORT = String(previewConfig.transport || 'rtsp').toLowerCase();
const PREVIEW_FPS = Number(previewConfig.fps || 10); const PREVIEW_FPS = Number(previewConfig.fps || 10);
const PREVIEW_WIDTH = Number(previewConfig.width || 640); const PREVIEW_WIDTH = Number(previewConfig.width || 640);
const ROOM_BITRATE_KBPS = Number(previewConfig.roomBitrateKbps || 200); const ROOM_BITRATE_KBPS = Number(previewConfig.roomBitrateKbps || 200);
@@ -36,6 +37,10 @@ function buildSrtPublishUrl(streamId) {
return `srt://127.0.0.1:9000?streamid=#!::r=${encoded},m=publish&latency=10&mode=caller&transtype=live&pkt_size=1316`; return `srt://127.0.0.1:9000?streamid=#!::r=${encoded},m=publish&latency=10&mode=caller&transtype=live&pkt_size=1316`;
} }
function buildRtspPublishUrl(streamId) {
return `rtsp://127.0.0.1:8554/${streamId}`;
}
function sanitizeCodec(codec) { function sanitizeCodec(codec) {
return String(codec || '').toLowerCase().replace(/[^a-z0-9]/g, '') || 'av1'; return String(codec || '').toLowerCase().replace(/[^a-z0-9]/g, '') || 'av1';
} }
@@ -91,6 +96,17 @@ function buildArgs(source) {
const gop = Math.max(1, Math.round(GOP_SECONDS * PREVIEW_FPS)); const gop = Math.max(1, Math.round(GOP_SECONDS * PREVIEW_FPS));
const maxrate = Math.floor(source.bitrateKbps * 1.1); const maxrate = Math.floor(source.bitrateKbps * 1.1);
const bufsize = Math.max(1, source.bitrateKbps * 2); const bufsize = Math.max(1, source.bitrateKbps * 2);
const codec = PREVIEW_CODEC === 'av1' ? 'libsvtav1' : 'libx264';
const extraCodecArgs =
codec === 'libx264'
? ['-tune', 'zerolatency', '-profile:v', 'baseline', '-sc_threshold', '0']
: [];
const outputUrl =
PREVIEW_TRANSPORT === 'rtsp' ? buildRtspPublishUrl(source.outputId) : buildSrtPublishUrl(source.outputId);
const outputArgs =
PREVIEW_TRANSPORT === 'rtsp'
? ['-f', 'rtsp', '-rtsp_transport', 'tcp']
: ['-f', 'mpegts'];
return [ return [
'-hide_banner', '-hide_banner',
'-loglevel', '-loglevel',
@@ -105,9 +121,10 @@ function buildArgs(source) {
'-vf', '-vf',
`fps=${PREVIEW_FPS},scale=${PREVIEW_WIDTH}:-1`, `fps=${PREVIEW_FPS},scale=${PREVIEW_WIDTH}:-1`,
'-c:v', '-c:v',
PREVIEW_CODEC === 'av1' ? 'libsvtav1' : 'libx264', codec,
'-preset', '-preset',
PRESET, PRESET,
...extraCodecArgs,
'-g', '-g',
String(gop), String(gop),
'-keyint_min', '-keyint_min',
@@ -120,9 +137,8 @@ function buildArgs(source) {
`${bufsize}k`, `${bufsize}k`,
'-pix_fmt', '-pix_fmt',
'yuv420p', 'yuv420p',
'-f', ...outputArgs,
'mpegts', outputUrl,
buildSrtPublishUrl(source.outputId),
]; ];
} }
+1 -1
View File
@@ -24,7 +24,6 @@ export default function DriverVideoPanel({layoutFormat = 'desktop'}) {
return () => clearInterval(timer); return () => clearInterval(timer);
}, [session?.mode]); }, [session?.mode]);
const roverId = session?.assignment?.roverId; const roverId = session?.assignment?.roverId;
const av1Supported = supportsAv1WebRtc();
const rosterEntry = const rosterEntry =
roverId && session?.roster ? session.roster.find((item) => String(item.id) === String(roverId)) : null; roverId && session?.roster ? session.roster.find((item) => String(item.id) === String(roverId)) : null;
const hasAudio = Boolean(rosterEntry?.media?.audioPublishUrl); const hasAudio = Boolean(rosterEntry?.media?.audioPublishUrl);
@@ -71,6 +70,7 @@ export default function DriverVideoPanel({layoutFormat = 'desktop'}) {
const sources = useVideoRequests(entries); const sources = useVideoRequests(entries);
const info = roverId && shouldShowVideo ? sources[roverId] : null; const info = roverId && shouldShowVideo ? sources[roverId] : null;
const audioInfo = roverId && hasAudio ? sources[`${roverId}-audio`] : null; const audioInfo = roverId && hasAudio ? sources[`${roverId}-audio`] : null;
const av1Supported = supportsAv1WebRtc();
const previewEntries = roverId const previewEntries = roverId
? [ ? [
{ {
+1 -1
View File
@@ -118,7 +118,7 @@ export default function RoomCameraPanel({
feed={feed} feed={feed}
label={camera.name || camera.id} label={camera.name || camera.id}
videoSession={previewSession} videoSession={previewSession}
preferVideo={av1Supported} preferVideo={Boolean(previewSession?.url)}
/> />
</article> </article>
); );
+7 -2
View File
@@ -36,13 +36,13 @@ function MiniSummaryContent() {
enabled: !inLockdown, enabled: !inLockdown,
version: session?.mode, version: session?.mode,
}); });
const av1Supported = supportsAv1WebRtc();
const [index, setIndex] = useState(0); const [index, setIndex] = useState(0);
const snapshotFeeds = useRoverSnapshots( const snapshotFeeds = useRoverSnapshots(
roster.map((rover) => rover.id), roster.map((rover) => rover.id),
{ enabled: !inLockdown, version: session?.mode }, { enabled: !inLockdown, version: session?.mode },
); );
const av1Supported = supportsAv1WebRtc();
const previewEntries = roster.map((rover) => ({ const previewEntries = roster.map((rover) => ({
type: 'rover', type: 'rover',
id: rover.id, id: rover.id,
@@ -162,7 +162,12 @@ function MiniSummaryContent() {
</FitViewportFrame> </FitViewportFrame>
) : activeCamera ? ( ) : activeCamera ? (
<FitViewportFrame> <FitViewportFrame>
<RoomCameraFrame camera={activeCamera} feed={activeFeed} videoSession={activeRoomPreview} preferVideo={av1Supported} /> <RoomCameraFrame
camera={activeCamera}
feed={activeFeed}
videoSession={activeRoomPreview}
preferVideo={Boolean(activeRoomPreview?.url)}
/>
</FitViewportFrame> </FitViewportFrame>
) : ( ) : (
<div className="flex h-full w-full items-center justify-center text-sm text-slate-500"> <div className="flex h-full w-full items-center justify-center text-sm text-slate-500">
+1 -1
View File
@@ -103,11 +103,11 @@ function SpectatorContent() {
useSpectatorMode(); useSpectatorMode();
const frames = useTelemetryFrames(); const frames = useTelemetryFrames();
const roster = session?.roster ?? []; const roster = session?.roster ?? [];
const av1Supported = supportsAv1WebRtc();
const snapshotFeeds = useRoverSnapshots( const snapshotFeeds = useRoverSnapshots(
roster.map((rover) => rover.id), roster.map((rover) => rover.id),
{ enabled: !inLockdown, version: session?.mode }, { enabled: !inLockdown, version: session?.mode },
); );
const av1Supported = supportsAv1WebRtc();
const previewEntries = roster.map((rover) => ({ const previewEntries = roster.map((rover) => ({
type: 'rover', type: 'rover',
id: rover.id, id: rover.id,