Archilyzer · Source

archilyzer

Archilyzer
git clone https://archilyzer.pages.dev/source/archilyzer.git
Log | Files | Refs | README | LICENSE

commit fef20670ac330227ef29e6ec0599417bc6ab49bc
parent d32e6b2e726ab50d56b8c3b6620f16460fc9ea3d
Author: I Mean I'm Just Saying <imeanimjustsaying@kiwifarms.st>
Date:   Mon, 29 Jun 2026 01:47:52 -0400

Add transcript coverage to public stats + charts

Carry a per-video `coverage` fraction (last cue end ÷ duration) in the
VideoStat record and expose it as a selectable chart Y-axis metric
("Transcript coverage") — e.g. average coverage by channel surfaces
channels with truncated/partial transcripts. Computed for free in
buildStats from the cue list already in memory; null when there's no
transcript or no usable duration.

Bumps STATS_SCHEMA_VERSION 4 -> 5 (clears the statsByPath cache; requires a
one-time build:index && build:stats to back-fill existing videos).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Diffstat:
Mcommon/components/charts/ChartConfigEditor.tsx | 1+
Mcommon/components/charts/ChartShapeControls.tsx | 1+
Mcommon/controller/buildStats.ts | 0
Mcommon/lib/chartConfig.ts | 4+++-
Mcommon/lib/chartShare.ts | 2+-
Mcommon/lib/stats.ts | 6+++++-
Mcommon/lib/transcripts-server.ts | 3+++
Mexport/CHANGELOG.md | 3+++
8 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/common/components/charts/ChartConfigEditor.tsx b/common/components/charts/ChartConfigEditor.tsx @@ -36,6 +36,7 @@ const METRIC_FIELDS: { value: MetricField; label: string }[] = [ { value: "commentCount", label: "Comments" }, { value: "channelFollowerCount", label: "Followers" }, { value: "cueCount", label: "Cue count" }, + { value: "coverage", label: "Transcript coverage" }, ]; export function ChartConfigEditor({ diff --git a/common/components/charts/ChartShapeControls.tsx b/common/components/charts/ChartShapeControls.tsx @@ -26,6 +26,7 @@ const METRIC_FIELDS: { value: MetricField; label: string }[] = [ { value: "commentCount", label: "Comments" }, { value: "channelFollowerCount", label: "Followers" }, { value: "cueCount", label: "Cue count" }, + { value: "coverage", label: "Transcript coverage" }, ]; // Map a gallery template's ChartConfig onto the search-page chart shape. The diff --git a/common/controller/buildStats.ts b/common/controller/buildStats.ts Binary files differ. diff --git a/common/lib/chartConfig.ts b/common/lib/chartConfig.ts @@ -39,7 +39,8 @@ export type MetricField = | "likeCount" | "commentCount" | "channelFollowerCount" - | "cueCount"; + | "cueCount" + | "coverage"; export type YMetric = | { agg: "count" } @@ -169,6 +170,7 @@ const METRIC_FIELD_LABEL: Record<MetricField, string> = { commentCount: "comments", channelFollowerCount: "followers", cueCount: "cues", + coverage: "transcript coverage", }; const AGG_LABEL: Record<Exclude<MetricAgg, "count">, string> = { diff --git a/common/lib/chartShare.ts b/common/lib/chartShare.ts @@ -138,7 +138,7 @@ function decY(raw: unknown): YMetric { const agg = oneOf(r.a, ["sum", "avg", "median", "max", "min"], "sum"); const field = oneOf( r.f, - ["duration", "viewCount", "likeCount", "commentCount", "channelFollowerCount", "cueCount"], + ["duration", "viewCount", "likeCount", "commentCount", "channelFollowerCount", "cueCount", "coverage"], "viewCount", ); return { agg, field }; diff --git a/common/lib/stats.ts b/common/lib/stats.ts @@ -2,7 +2,7 @@ import type { Platform } from "./platform"; // Bumping this invalidates the LMDB `statsByPath` incremental cache and forces // a full re-extraction (e.g. when a new field is added below). -export const STATS_SCHEMA_VERSION = 4; +export const STATS_SCHEMA_VERSION = 5; export const STATS_MANIFEST_VERSION = 1; // Visibility of a video on its source platform, derived from the availability @@ -52,6 +52,10 @@ export type VideoStat = { status: VideoStatus; hasTranscript: boolean; cueCount: number | null; + // Fraction of the video's duration covered by the transcript (last cue end ÷ + // duration). null when there's no transcript or no usable duration. Values + // well below 1 flag a truncated download (see lib/transcriptCoverage). + coverage: number | null; }; export type StatsChannelEntry = { diff --git a/common/lib/transcripts-server.ts b/common/lib/transcripts-server.ts @@ -139,6 +139,8 @@ export function summarizeStats( // source is resolvable. downloadedDate: string | null; transcribedDate: string | null; + // Last-cue-end ÷ duration; null when not computable. See transcriptCoverage. + coverage: number | null; }, ): VideoStat { const base = summarize(channelSlug, videoDir, meta, configName); @@ -168,6 +170,7 @@ export function summarizeStats( status: transcript.status, hasTranscript: transcript.hasTranscript, cueCount: transcript.cueCount, + coverage: transcript.coverage, }; } diff --git a/export/CHANGELOG.md b/export/CHANGELOG.md @@ -1,5 +1,8 @@ # Changelog +## [Unreleased] +- **Transcript coverage is now a chart metric.** Each video's stats record carries a `coverage` fraction (transcript's last cue end ÷ video duration), selectable as a Y-axis metric ("Transcript coverage") in the chart options — e.g. average coverage by channel surfaces channels with truncated/partial transcripts. Coverage is `null` for videos with no transcript or no usable duration. (Requires the one-time `build:index` + `build:stats` rebuild on the bumped stats schema; the field is back-filled for every transcribed video from its `transcript.cues.json`.) + ## [0.4.1] - 2026-06-22 - **New "Content added" charts: track when videos joined the library, not just when they were uploaded.** The time axis of any chart can now bin on **when we downloaded** or **transcribed** a video, in addition to its upload date — pick the **Date field** in the chart options. The dashboard ships a cumulative **Library growth (added)** chart by default (grouped by channel), and the chart gallery gains a **Content added** group with cumulative download/transcription curves and a per-month stacked-by-channel breakdown. Like every chart, these filter by channel and export to CSV/PNG. (Populating acquisition dates for existing videos requires a one-time data rebuild — `build:index` + `build:stats` re-extract on the bumped stats schema; videos added before this release fall back to file timestamps.)