diff --git a/src-tauri/src/models.rs b/src-tauri/src/models.rs index 6d05b4f..28661a4 100644 --- a/src-tauri/src/models.rs +++ b/src-tauri/src/models.rs @@ -9,6 +9,10 @@ pub struct VideoMetadata { pub fps: f64, pub thumbnail_url: Option, pub stream_url: String, + /// Whether English captions are available (manual or auto-generated) + pub has_captions: bool, + /// True if the available captions are auto-generated (lower quality) + pub captions_are_auto: bool, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -84,6 +88,28 @@ pub enum ExportScope { Merged, } +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct CaptionStyle { + pub font_family: String, + pub font_size: u32, + pub text_color: String, + pub bold: bool, + pub outline_color: String, + pub background_enabled: bool, + pub background_opacity: f64, + pub background_color: String, + pub text_outline: bool, + pub shadow_enabled: bool, + pub shadow_depth: u32, + pub shadow_color: String, + pub dimmed_color_mode: String, + pub dimmed_opacity: f64, + pub dimmed_color: String, + pub position: String, + pub word_highlight: bool, +} + #[derive(Debug, Clone, Serialize, Deserialize)] #[serde(rename_all = "camelCase")] pub struct ExportConfig { @@ -93,6 +119,25 @@ pub struct ExportConfig { pub output_directory: String, pub video_title: String, pub source_file_path: String, + /// Whether to include captions in the export + pub include_captions: bool, + /// Whether to burn subtitles into the video (requires re-encoding) + pub burn_in_captions: bool, + /// Path to the VTT caption file (if available) + pub caption_file_path: Option, + /// Style settings for burned-in captions + pub caption_style: Option, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(rename_all = "camelCase")] +pub struct WaveformTiers { + /// ~2,000 peaks — overview for full-duration view + pub tier0: Vec, + /// ~10,000 peaks — moderate zoom + pub tier1: Vec, + /// All extracted peaks — deep zoom + pub tier2: Vec, } #[derive(Debug, Clone, Serialize, Deserialize)] diff --git a/src/lib/bindings/export.ts b/src/lib/bindings/export.ts index 89cdfd7..3c65eb6 100644 --- a/src/lib/bindings/export.ts +++ b/src/lib/bindings/export.ts @@ -1,5 +1,25 @@ import { invoke, Channel } from '@tauri-apps/api/core'; +export interface CaptionStyle { + fontFamily: string; + fontSize: number; + textColor: string; + bold: boolean; + outlineColor: string; + backgroundEnabled: boolean; + backgroundOpacity: number; + backgroundColor: string; + textOutline: boolean; + shadowEnabled: boolean; + shadowDepth: number; + shadowColor: string; + dimmedColorMode: string; + dimmedOpacity: number; + dimmedColor: string; + position: string; + wordHighlight: boolean; +} + export interface ExportConfig { clips: Array<{ id: string; @@ -13,10 +33,15 @@ export interface ExportConfig { outputDirectory: string; videoTitle: string; sourceFilePath: string; + includeCaptions: boolean; + burnInCaptions: boolean; + captionFilePath: string | null; + captionStyle: CaptionStyle | null; } type ExportEvent = | { event: 'progress'; data: { current: number; total: number; label: string } } + | { event: 'clipProgress'; data: { current: number; total: number; label: string; percent: number } } | { event: 'finished'; data: { paths: string[] } } | { event: 'error'; data: { message: string } }; @@ -24,7 +49,8 @@ export async function exportClips( config: ExportConfig, onProgress: (current: number, total: number, label: string) => void, onFinished: (paths: string[]) => void, - onError: (message: string) => void + onError: (message: string) => void, + onClipProgress?: (current: number, total: number, label: string, percent: number) => void ): Promise { const onEvent = new Channel(); onEvent.onmessage = (message) => { @@ -32,6 +58,9 @@ export async function exportClips( case 'progress': onProgress(message.data.current, message.data.total, message.data.label); break; + case 'clipProgress': + onClipProgress?.(message.data.current, message.data.total, message.data.label, message.data.percent); + break; case 'finished': onFinished(message.data.paths); break; diff --git a/src/lib/components/ExportDialog.svelte b/src/lib/components/ExportDialog.svelte index 99744cf..5166551 100644 --- a/src/lib/components/ExportDialog.svelte +++ b/src/lib/components/ExportDialog.svelte @@ -1,6 +1,7 @@