fix(lab): seal RAV004 spatial replay transport

This commit is contained in:
DCCONSTRUCTIONS
2026-08-30 10:42:41 +03:00
parent f1cbe0061a
commit 757d368c86
11 changed files with 492 additions and 91 deletions
@@ -180,6 +180,7 @@ export function M4ReplayThreatVisual({
showReferenceMediaLayers = true,
showSpatialOverlaySummary = true,
playbackTransport = "epoch-stream",
spatialPlaybackTransport = "auto",
recoverTimestampStalls = false,
onActiveSequenceChange,
}: {
@@ -198,6 +199,7 @@ export function M4ReplayThreatVisual({
showReferenceMediaLayers?: boolean;
showSpatialOverlaySummary?: boolean;
playbackTransport?: "segmented" | "epoch-stream";
spatialPlaybackTransport?: "auto" | "sealed-binary" | "json";
recoverTimestampStalls?: boolean;
onActiveSequenceChange?: (sequence: number | null) => void;
}) {
@@ -293,6 +295,7 @@ export function M4ReplayThreatVisual({
currentSeconds: playbackController.playback.currentSeconds,
includeSpatialPoints: evidenceDemand.sourceSpatialPoints,
endpointRoot: timelineEndpointRoot,
spatialPlaybackTransport,
});
const [videoSource, setVideoSource] = useState<ObservationSourceDescriptor | null>(null);
const [videoLoading, setVideoLoading] = useState(false);
@@ -1143,6 +1146,7 @@ export function M4ReplayThreatVisual({
imageWidth={timeline.imageWidth}
imageHeight={timeline.imageHeight}
boxes={activeBoxes}
overlaySeconds={frame?.sessionSeconds}
semanticOverlay={mediaMode === "video" ? semanticOverlay : undefined}
pointCloudOverlay={mediaMode === "video" ? pointCloudOverlay : undefined}
ariaLabel={`${evidenceLabel} recorded-realtime frame ${frame?.sequence ?? 0}: ${activeBoxes.length} proposals`}
@@ -80,6 +80,7 @@ function FullRouteReviewEvidence({
classifiedSpatialLayer={sealedSpatialGap}
evidenceLabel="RAVNOVES004TREE"
playbackTransport="segmented"
spatialPlaybackTransport="sealed-binary"
recoverTimestampStalls
showReferenceMediaLayers
showSpatialOverlaySummary
@@ -34,14 +34,14 @@ export function m4ThreatChunkWindowStarts(
if (chunkSize < 1 || frameCount < 1) return [];
return [
activeChunkStart,
...Array.from(
{ length: RETAINED_CHUNKS_BEHIND },
(_, index) => activeChunkStart - (index + 1) * chunkSize,
),
...Array.from(
{ length: PREFETCH_CHUNKS_AHEAD },
(_, index) => activeChunkStart + (index + 1) * chunkSize,
),
...Array.from(
{ length: RETAINED_CHUNKS_BEHIND },
(_, index) => activeChunkStart - (index + 1) * chunkSize,
),
].filter((start) => start >= 0 && start < frameCount);
}
@@ -86,12 +86,14 @@ export function useM4ThreatTimelineFrame({
currentSeconds,
includeSpatialPoints = true,
endpointRoot,
spatialPlaybackTransport = "auto",
}: {
resultId: string;
timeline: M4ThreatTimeline | null;
currentSeconds: number;
includeSpatialPoints?: boolean;
endpointRoot?: string;
spatialPlaybackTransport?: "auto" | "sealed-binary" | "json";
}) {
const [chunks, setChunks] = useState<ReadonlyMap<number, M4ThreatTimelineChunk>>(
() => new Map(),
@@ -104,8 +106,10 @@ export function useM4ThreatTimelineFrame({
totalBytes: 0,
});
const [playbackError, setPlaybackError] = useState<string | null>(null);
const binaryPlayback = endpointRoot === undefined
|| endpointRoot === M4_THREAT_TIMELINE_ENDPOINT_ROOT;
const binaryPlayback = spatialPlaybackTransport === "sealed-binary"
|| (spatialPlaybackTransport === "auto" && (
endpointRoot === undefined || endpointRoot === M4_THREAT_TIMELINE_ENDPOINT_ROOT
));
const inFlight = useRef(new Map<number, AbortController>());
const chunksRef = useRef(chunks);
const activeChunkStartRef = useRef<number | null>(null);