Files
netfelix-audio-fix/server/types.ts
T
felixfoertsch 50e1ea66f4
Build and Push Docker Image / build (push) Successful in 1m1s
show processing reasons as pills on pipeline cards
Analyzer now computes structured reason tags (Remove tracks, Reorder,
Extract subs, Transcode, Fix default, Fix language tag, Fix title) and
stores them as JSON in review_plans.reasons. Pipeline cards show these
as badges next to the copy/transcode pill so users know why a file
needs processing. Replaces the old transcode_reasons computed from
stream_decisions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-21 11:01:54 +02:00

133 lines
3.9 KiB
TypeScript

// ─── Database row types ───────────────────────────────────────────────────────
export interface MediaItem {
id: number;
file_path: string;
type: "Movie" | "Episode";
name: string;
series_name: string | null;
series_key: string | null;
season_number: number | null;
episode_number: number | null;
year: number | null;
file_size: number | null;
container: string | null;
duration_seconds: number | null;
original_language: string | null;
orig_lang_source: "probe" | "radarr" | "sonarr" | "manual" | null;
needs_review: number;
imdb_id: string | null;
tmdb_id: string | null;
tvdb_id: string | null;
scan_status: "pending" | "scanned" | "error";
scan_error: string | null;
last_scanned_at: string | null;
last_executed_at: string | null;
created_at: string;
}
export interface MediaStream {
id: number;
item_id: number;
stream_index: number;
type: "Video" | "Audio" | "Subtitle" | "Data" | "EmbeddedImage";
codec: string | null;
profile: string | null;
language: string | null;
title: string | null;
is_default: number;
is_forced: number;
is_hearing_impaired: number;
channels: number | null;
channel_layout: string | null;
bit_rate: number | null;
sample_rate: number | null;
bit_depth: number | null;
}
export interface ReviewPlan {
id: number;
item_id: number;
status: "pending" | "approved" | "skipped" | "done" | "error";
is_noop: number;
auto_class: "auto" | "auto_heuristic" | "manual" | null;
sorted: number;
apple_compat: "direct_play" | "remux" | "audio_transcode" | null;
job_type: "copy" | "transcode";
subs_extracted: number;
notes: string | null;
reviewed_at: string | null;
created_at: string;
}
export interface StreamDecision {
id: number;
plan_id: number;
stream_id: number;
action: "keep" | "remove";
target_index: number | null;
custom_title: string | null;
/** Per-stream language override. When set, the analyzer and ffmpeg
* command builder both read this in preference to the raw
* media_streams.language. Lets the user correct an "und" or
* mislabeled audio track without going through Jellyfin. */
custom_language: string | null;
transcode_codec: string | null;
}
export interface Job {
id: number;
item_id: number;
command: string;
job_type: "copy" | "transcode";
status: "pending" | "running" | "done" | "error";
output: string | null;
exit_code: number | null;
created_at: string;
started_at: string | null;
completed_at: string | null;
}
// ─── Analyzer types ───────────────────────────────────────────────────────────
export interface StreamWithDecision extends MediaStream {
action: "keep" | "remove";
target_index: number | null;
}
export interface PlanResult {
is_noop: boolean;
has_subs: boolean;
auto_class: "auto" | "auto_heuristic" | "manual";
apple_compat: "direct_play" | "remux" | "audio_transcode" | null;
job_type: "copy" | "transcode";
decisions: Array<{
stream_id: number;
action: "keep" | "remove";
target_index: number | null;
transcode_codec: string | null;
}>;
notes: string[];
/** Short reason tags explaining why the file needs processing. */
reasons: string[];
}
// ─── Scan state ───────────────────────────────────────────────────────────────
export interface ScanProgress {
total: number;
scanned: number;
current_item: string;
errors: number;
running: boolean;
}
// ─── SSE event helpers ────────────────────────────────────────────────────────
export type SseEventType = "progress" | "log" | "complete" | "error";
export interface SseEvent {
type: SseEventType;
data: unknown;
}