chunker ui redo

This commit is contained in:
2026-03-15 16:03:53 -03:00
parent d5a3372d6b
commit b40bd68411
62 changed files with 5460 additions and 1493 deletions

View File

@@ -1,15 +1,4 @@
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family:
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: #1a1a1a;
color: #e0e0e0;
}
@import "../../common/styles/theme.css";
.app {
display: flex;

View File

@@ -115,7 +115,6 @@ function App() {
setJobs(data);
};
const assetJobs = jobs.filter((j) => j.source_asset_id === selectedAsset?.id);
const completedJobs = jobs.filter((j) => j.status === "completed");
if (loading) return <div className="loading">Loading...</div>;

View File

@@ -42,6 +42,8 @@ export default function JobPanel({
preset_id: selectedPresetId || null,
trim_start: hasTrim ? trimStart : null,
trim_end: hasTrim ? trimEnd : null,
output_filename: null,
priority: 0,
});
onJobCreated();
} catch (e) {

View File

@@ -2,45 +2,17 @@
* GraphQL API client
*/
import { gql } from "../../common/api/graphql";
import { getAssets, scanMediaFolder } from "../../common/api/media";
import type {
MediaAsset,
TranscodePreset,
TranscodeJob,
CreateJobRequest,
SystemStatus,
MediaAsset,
} from "./types";
const GRAPHQL_URL = "/api/graphql";
async function gql<T>(query: string, variables?: Record<string, unknown>): Promise<T> {
const response = await fetch(GRAPHQL_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ query, variables }),
});
const json = await response.json();
if (json.errors?.length) {
throw new Error(json.errors[0].message);
}
return json.data as T;
}
// Assets
export async function getAssets(): Promise<MediaAsset[]> {
const data = await gql<{ assets: MediaAsset[] }>(`
query {
assets {
id filename file_path status error_message file_size duration
video_codec audio_codec width height framerate bitrate
properties comments tags created_at updated_at
}
}
`);
return data.assets;
}
export { getAssets, scanMediaFolder };
export async function getAsset(id: string): Promise<MediaAsset> {
const data = await gql<{ asset: MediaAsset }>(`
@@ -55,20 +27,6 @@ export async function getAsset(id: string): Promise<MediaAsset> {
return data.asset;
}
export async function scanMediaFolder(): Promise<{
found: number;
registered: number;
skipped: number;
files: string[];
}> {
const data = await gql<{ scan_media_folder: { found: number; registered: number; skipped: number; files: string[] } }>(`
mutation {
scan_media_folder { found registered skipped files }
}
`);
return data.scan_media_folder;
}
// Presets
export async function getPresets(): Promise<TranscodePreset[]> {
const data = await gql<{ presets: TranscodePreset[] }>(`

View File

@@ -1,135 +1,21 @@
/**
* TypeScript Types - GENERATED FILE
* TypeScript Types — re-exported from common generated types.
*
* Do not edit directly. Regenerate using modelgen.
*/
export type AssetStatus = "pending" | "ready" | "error";
export type JobStatus = "pending" | "processing" | "completed" | "failed" | "cancelled";
export type ChunkJobStatus = "pending" | "chunking" | "processing" | "collecting" | "completed" | "failed" | "cancelled";
export interface MediaAsset {
id: string;
filename: string;
file_path: string;
status: AssetStatus;
error_message: string | null;
file_size: number | null;
duration: number | null;
video_codec: string | null;
audio_codec: string | null;
width: number | null;
height: number | null;
framerate: number | null;
bitrate: number | null;
properties: Record<string, unknown>;
comments: string;
tags: string[];
created_at: string | null;
updated_at: string | null;
}
export interface TranscodePreset {
id: string;
name: string;
description: string;
is_builtin: boolean;
container: string;
video_codec: string;
video_bitrate: string | null;
video_crf: number | null;
video_preset: string | null;
resolution: string | null;
framerate: number | null;
audio_codec: string;
audio_bitrate: string | null;
audio_channels: number | null;
audio_samplerate: number | null;
extra_args: string[];
created_at: string | null;
updated_at: string | null;
}
export interface TranscodeJob {
id: string;
source_asset_id: string;
preset_id: string | null;
preset_snapshot: Record<string, unknown>;
trim_start: number | null;
trim_end: number | null;
output_filename: string;
output_path: string | null;
output_asset_id: string | null;
status: JobStatus;
progress: number;
current_frame: number | null;
current_time: number | null;
speed: string | null;
error_message: string | null;
celery_task_id: string | null;
execution_arn: string | null;
priority: number;
created_at: string | null;
started_at: string | null;
completed_at: string | null;
}
export interface ChunkJob {
id: string;
source_asset_id: string;
chunk_duration: number;
num_workers: number;
max_retries: number;
processor_type: string;
status: ChunkJobStatus;
progress: number;
total_chunks: number;
processed_chunks: number;
failed_chunks: number;
retry_count: number;
error_message: string | null;
throughput_mbps: number | null;
elapsed_seconds: number | null;
celery_task_id: string | null;
priority: number;
created_at: string | null;
started_at: string | null;
completed_at: string | null;
}
export interface CreateJobRequest {
source_asset_id: string;
preset_id: string | null;
trim_start: number | null;
trim_end: number | null;
output_filename: string | null;
priority: number;
}
export interface UpdateAssetRequest {
comments: string | null;
tags: string[] | null;
}
export interface SystemStatus {
status: string;
version: string;
}
export interface ScanResult {
found: number;
registered: number;
skipped: number;
files: string[];
}
export interface DeleteResult {
ok: boolean;
}
export interface WorkerStatus {
available: boolean;
active_jobs: number;
supported_codecs: string[];
gpu_available: boolean;
}
export type {
AssetStatus,
JobStatus,
ChunkJobStatus,
MediaAsset,
TranscodePreset,
TranscodeJob,
ChunkJob,
CreateJobRequest,
UpdateAssetRequest,
SystemStatus,
ScanResult,
DeleteResult,
WorkerStatus,
} from "../../common/types/generated";