export interface Subtitle { id: string; startTime: number; endTime: number; originalText: string; translatedText: string; ttsText?: string; ttsLanguage?: string; speaker: string; speakerId?: string; words?: WordTiming[]; confidence?: number; voiceId: string; audioUrl?: string; volume?: number; age?: string; voiceCharacteristics?: string; emotion?: string; textStyle?: TextStyles; } export type LlmProvider = 'doubao' | 'gemini'; export type PipelineQuality = 'full' | 'partial' | 'fallback'; export type SubtitleJobStatus = 'queued' | 'running' | 'succeeded' | 'failed'; export type SubtitleJobStage = | 'queued' | 'upload_received' | 'preparing' | 'calling_provider' | 'processing_result' | 'succeeded' | 'failed'; export interface WordTiming { text: string; startTime: number; endTime: number; speakerId: string; confidence: number; } export interface SpeakerTrack { speakerId: string; label: string; gender?: 'male' | 'female' | 'unknown'; } export interface SubtitlePipelineResult { subtitles: Subtitle[]; speakers: SpeakerTrack[]; quality: PipelineQuality; sourceLanguage?: string; targetLanguage?: string; ttsLanguage?: string; duration?: number; alignmentEngine?: string; } export interface SubtitleGenerationProgress { jobId: string; requestId: string; status: SubtitleJobStatus; stage: SubtitleJobStage; progress: number; message: string; pollTimeoutMs?: number; } export interface TextStyles { fontFamily: string; fontSize: number; color: string; backgroundColor: string; strokeColor: string; strokeWidth: number; alignment: 'left' | 'center' | 'right'; isBold: boolean; isItalic: boolean; isUnderline: boolean; } export interface SubtitleDefaults { fontSize: number; bottomOffsetPercent: number; } export const DEFAULT_SUBTITLE_DEFAULTS: SubtitleDefaults = { fontSize: 24, bottomOffsetPercent: 10, }; export interface Voice { id: string; name: string; tag: string; avatar: string; gender: 'male' | 'female' | 'neutral'; language: string; }