mirror of
https://github.com/Sendouc/sendou.ink.git
synced 2026-09-28 22:31:22 -05:00
Dont save frames unless debugging
This commit is contained in:
@@ -48,9 +48,10 @@ opens it, for anyone, through the same handoff Inspect uses.
|
||||
so events from different page loads share one timeline; the ring buffer
|
||||
stamps footage the same way.
|
||||
- **Retention** (`store/events.ts`, on a throttled pass at every save):
|
||||
whole sessions older than 30 days or beyond the newest 20 go; full-res
|
||||
frames are kept for everyone — a misread is only reportable while the
|
||||
frame exists — bounded by 72 h and `MAX_FRAMES`, the event staying with
|
||||
whole sessions older than 30 days or beyond the newest 20 go. Full-res
|
||||
frames (and the thumbnails made from them) are only captured in debug
|
||||
mode — the worker skips the PNG encode otherwise (`attachFrames`) — and
|
||||
are bounded by 72 h and `MAX_FRAMES`, the event staying with
|
||||
`hasFrame: false`. Clips have their own cap and outlive session deletion.
|
||||
- **Upload** is on by default when logged in (settings toggle, persisted).
|
||||
Live: a scoreboard closes its match and sends it, a 15 s tick retries
|
||||
|
||||
@@ -28,6 +28,7 @@ import styles from "./LandingView.module.css";
|
||||
import { getLiveSession, startCapture, useLiveSession } from "./live-session";
|
||||
import { SettingsPopover } from "./SettingsPopover";
|
||||
import { SourceSelect } from "./SourceSelect";
|
||||
import { useDebug } from "./use-debug";
|
||||
import { startVodScan } from "./vod-scan";
|
||||
import { useVods } from "./vods-feed";
|
||||
|
||||
@@ -55,6 +56,7 @@ export function LandingView() {
|
||||
const vods = useVods();
|
||||
const clips = useClips();
|
||||
const [telemetry] = useSearchParam(scannerSearchParams, "telemetry");
|
||||
const debug = useDebug();
|
||||
const [, setParams] = useSearchParamsTyped(scannerSearchParams);
|
||||
const [over, setOver] = useState(false);
|
||||
const [playing, setPlaying] = useState<ScannerClip | null>(null);
|
||||
@@ -68,7 +70,7 @@ export function LandingView() {
|
||||
setParams({ view: "live" });
|
||||
return;
|
||||
}
|
||||
await startCapture();
|
||||
await startCapture({ saveFrames: debug });
|
||||
if (getLiveSession().status === "running") setParams({ view: "live" });
|
||||
};
|
||||
|
||||
@@ -77,7 +79,7 @@ export function LandingView() {
|
||||
void inspectScreenshot(file);
|
||||
return;
|
||||
}
|
||||
void startVodScan(file, { telemetry });
|
||||
void startVodScan(file, { telemetry, saveFrames: debug });
|
||||
setParams({ view: "vod", name: file.name });
|
||||
};
|
||||
|
||||
|
||||
@@ -89,7 +89,10 @@ function ScanVodView({ name }: { name: string }) {
|
||||
const file = e.target.files?.[0];
|
||||
e.target.value = "";
|
||||
if (file) {
|
||||
void startVodScan(file, { telemetry: telemetryOn });
|
||||
void startVodScan(file, {
|
||||
telemetry: telemetryOn,
|
||||
saveFrames: debug,
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
@@ -179,8 +179,16 @@ function set(patch: Partial<LiveSnapshot>): void {
|
||||
for (const listener of listeners) listener();
|
||||
}
|
||||
|
||||
/** Opens the source, brings the worker up, then starts sampling; a second call while running is ignored. */
|
||||
export async function startCapture(): Promise<void> {
|
||||
/**
|
||||
* Opens the source, brings the worker up, then starts sampling; a second call
|
||||
* while running is ignored. `saveFrames` (debug mode) keeps each event's
|
||||
* analyzed frame and thumbnail for the raw detections.
|
||||
*/
|
||||
export async function startCapture({
|
||||
saveFrames,
|
||||
}: {
|
||||
saveFrames: boolean;
|
||||
}): Promise<void> {
|
||||
if (snapshot.status === "starting" || snapshot.status === "running") return;
|
||||
releaseCaptureLock = await acquireCaptureLock();
|
||||
if (!releaseCaptureLock) {
|
||||
@@ -232,6 +240,7 @@ export async function startCapture(): Promise<void> {
|
||||
client = new AnalyzerClient(onResult, onWorkerError, undefined, {
|
||||
frameQueueLimit: FRAME_QUEUE_LIMIT,
|
||||
webgpu: settings.webgpu,
|
||||
attachFrames: saveFrames,
|
||||
});
|
||||
try {
|
||||
await client.whenReady();
|
||||
|
||||
@@ -207,10 +207,14 @@ export async function uploadVodScan(
|
||||
}
|
||||
}
|
||||
|
||||
/** Scans `file` as fast as decoding allows; a finished scan replaces any saved one of the same name. */
|
||||
/**
|
||||
* Scans `file` as fast as decoding allows; a finished scan replaces any saved
|
||||
* one of the same name. `saveFrames` (debug mode) keeps each event's analyzed
|
||||
* frame and thumbnail for the raw detections.
|
||||
*/
|
||||
export async function startVodScan(
|
||||
file: File,
|
||||
{ telemetry }: { telemetry: boolean },
|
||||
{ telemetry, saveFrames }: { telemetry: boolean; saveFrames: boolean },
|
||||
): Promise<void> {
|
||||
cancelVodScan();
|
||||
const abort = { aborted: false };
|
||||
@@ -296,7 +300,11 @@ export async function startVodScan(
|
||||
seek.frameDone?.();
|
||||
seek.frameDone = null;
|
||||
},
|
||||
{ collectTelemetry: telemetry, webgpu: readSettings().webgpu },
|
||||
{
|
||||
collectTelemetry: telemetry,
|
||||
webgpu: readSettings().webgpu,
|
||||
attachFrames: saveFrames,
|
||||
},
|
||||
),
|
||||
);
|
||||
await Promise.all(clients.map((c) => c.whenReady()));
|
||||
|
||||
@@ -21,8 +21,8 @@ import { EVENTS_STORE, FRAMES_STORE, readwrite, tx } from "./db";
|
||||
const MAX_EVENTS = 10_000;
|
||||
|
||||
/**
|
||||
* Full-res frame PNGs (~1-2MB each) are what makes a misread reportable, so
|
||||
* they are kept for everyone — bounded by age and count, whichever bites first.
|
||||
* Full-res frame PNGs (~1-2MB each) are what makes a misread reportable; only
|
||||
* debug-mode captures save them, bounded by age and count, whichever bites first.
|
||||
*/
|
||||
const MAX_FRAMES = 200;
|
||||
const FRAME_MAX_AGE_MS = 72 * 60 * 60 * 1000;
|
||||
|
||||
@@ -81,6 +81,7 @@ let scheduler: DetectorScheduler | null = null;
|
||||
/** null unless the init message asked for telemetry */
|
||||
let telemetry: ScanTelemetry | null = null;
|
||||
let collectTelemetry = false;
|
||||
let attachFrames = true;
|
||||
let chunkAborted = false;
|
||||
/** last per-frame t, to reset telemetry when a new session rewinds the clock */
|
||||
let lastFrameT = Number.NEGATIVE_INFINITY;
|
||||
@@ -110,6 +111,7 @@ async function init({
|
||||
suppressSteadyFrames = true,
|
||||
collectTelemetry: collect = false,
|
||||
webgpu = false,
|
||||
attachFrames: attach = true,
|
||||
}: InitRequest): Promise<void> {
|
||||
// VoD scans need the helper workers: start them booting alongside init
|
||||
if (typeof VideoDecoder !== "undefined") {
|
||||
@@ -138,6 +140,7 @@ async function init({
|
||||
matchClosingTypes: SCOREBOARD_EVENT_TYPES,
|
||||
});
|
||||
collectTelemetry = collect;
|
||||
attachFrames = attach;
|
||||
telemetry = freshTelemetry();
|
||||
post({ kind: "ready" });
|
||||
} catch (error) {
|
||||
@@ -216,7 +219,7 @@ async function analyzePrepared(
|
||||
if (action === "added" || action === "replaced") listed = true;
|
||||
}
|
||||
const blob =
|
||||
listed && detector.attachFrame !== false
|
||||
attachFrames && listed && detector.attachFrame !== false
|
||||
? await frameBlob()
|
||||
: undefined;
|
||||
post({
|
||||
|
||||
@@ -68,6 +68,8 @@ export class AnalyzerClient {
|
||||
frameQueueLimit?: number;
|
||||
/** match templates on WebGPU when the browser has an adapter (settings `webgpu`) */
|
||||
webgpu?: boolean;
|
||||
/** ship the analyzed frame's PNG on results (default true) */
|
||||
attachFrames?: boolean;
|
||||
} = {},
|
||||
) {
|
||||
this.#frameQueueLimit = options.frameQueueLimit ?? 0;
|
||||
@@ -123,6 +125,7 @@ export class AnalyzerClient {
|
||||
suppressSteadyFrames: options.suppressSteadyFrames ?? true,
|
||||
collectTelemetry: options.collectTelemetry ?? false,
|
||||
webgpu: options.webgpu ?? false,
|
||||
attachFrames: options.attachFrames ?? true,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ export interface InitRequest {
|
||||
collectTelemetry?: boolean;
|
||||
/** match templates (and upscale sub-1080p frames) on WebGPU when an adapter exists; default false */
|
||||
webgpu?: boolean;
|
||||
/** PNG-encode the analyzed frame onto results whose events fired; default true (live and VoD scans only want it in debug mode) */
|
||||
attachFrames?: boolean;
|
||||
}
|
||||
|
||||
export interface AnalyzeRequest {
|
||||
|
||||
Reference in New Issue
Block a user