use chrono::{DateTime, Utc}; use diesel::prelude::*; use serde::{Deserialize, Serialize}; use std::collections::HashMap; use uuid::Uuid; use super::schema::*; #[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable, Insertable)] #[diesel(table_name = video_projects)] pub struct VideoProject { pub id: Uuid, pub organization_id: Option, pub created_by: Option, pub name: String, pub description: Option, pub resolution_width: i32, pub resolution_height: i32, pub fps: i32, pub total_duration_ms: i64, pub timeline_json: serde_json::Value, pub layers_json: serde_json::Value, pub audio_tracks_json: serde_json::Value, pub playhead_ms: i64, pub selection_json: serde_json::Value, pub zoom_level: f32, pub thumbnail_url: Option, pub status: String, pub created_at: DateTime, pub updated_at: DateTime, } #[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable, Insertable)] #[diesel(table_name = video_clips)] pub struct VideoClip { pub id: Uuid, pub project_id: Uuid, pub name: String, pub source_url: String, pub start_ms: i64, pub duration_ms: i64, pub trim_in_ms: i64, pub trim_out_ms: i64, pub volume: f32, pub clip_order: i32, pub transition_in: Option, pub transition_out: Option, pub created_at: DateTime, } #[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable, Insertable)] #[diesel(table_name = video_layers)] pub struct VideoLayer { pub id: Uuid, pub project_id: Uuid, pub name: String, pub layer_type: String, pub track_index: i32, pub start_ms: i64, pub end_ms: i64, pub x: f32, pub y: f32, pub width: f32, pub height: f32, pub rotation: f32, pub opacity: f32, pub properties_json: serde_json::Value, pub animation_in: Option, pub animation_out: Option, pub locked: bool, pub keyframes_json: Option, pub created_at: DateTime, } #[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable, Insertable)] #[diesel(table_name = video_audio_tracks)] pub struct VideoAudioTrack { pub id: Uuid, pub project_id: Uuid, pub name: String, pub source_url: String, pub track_type: String, pub start_ms: i64, pub duration_ms: i64, pub volume: f32, pub fade_in_ms: i64, pub fade_out_ms: i64, pub waveform_json: Option, pub beat_markers_json: Option, pub created_at: DateTime, } #[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable, Insertable)] #[diesel(table_name = video_exports)] pub struct VideoExport { pub id: Uuid, pub project_id: Uuid, pub format: String, pub quality: String, pub status: String, pub progress: i32, pub output_url: Option, pub gbdrive_path: Option, pub error_message: Option, pub created_at: DateTime, pub completed_at: Option>, } #[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable, Insertable)] #[diesel(table_name = video_command_history)] pub struct VideoCommandHistory { pub id: Uuid, pub project_id: Uuid, pub user_id: Option, pub command_type: String, pub command_json: serde_json::Value, pub executed_at: DateTime, } #[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable, Insertable)] #[diesel(table_name = video_analytics)] pub struct VideoAnalytics { pub id: Uuid, pub project_id: Uuid, pub export_id: Option, pub views: i64, pub unique_viewers: i64, pub total_watch_time_ms: i64, pub avg_watch_percent: f32, pub completions: i64, pub shares: i64, pub likes: i64, pub engagement_score: f32, pub viewer_retention_json: Option, pub geography_json: Option, pub device_json: Option, pub created_at: DateTime, pub updated_at: DateTime, } #[derive(Debug, Clone, Serialize, Deserialize, Queryable, Identifiable, Insertable)] #[diesel(table_name = video_keyframes)] pub struct VideoKeyframe { pub id: Uuid, pub layer_id: Uuid, pub property_name: String, pub time_ms: i64, pub value_json: serde_json::Value, pub easing: String, pub created_at: DateTime, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct CreateProjectRequest { pub name: String, pub description: Option, pub resolution_width: Option, pub resolution_height: Option, pub fps: Option, } #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct UpdateProjectRequest { pub name: Option, pub description: Option, pub playhead_ms: Option, pub selection_json: Option, pub zoom_level: Option, pub status: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AddClipRequest { pub name: Option, pub source_url: String, pub at_ms: Option, pub duration_ms: Option, } #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct UpdateClipRequest { pub name: Option, pub start_ms: Option, pub duration_ms: Option, pub trim_in_ms: Option, pub trim_out_ms: Option, pub volume: Option, pub transition_in: Option, pub transition_out: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AddLayerRequest { pub name: Option, pub layer_type: String, pub start_ms: Option, pub end_ms: Option, pub x: Option, pub y: Option, pub width: Option, pub height: Option, pub properties: Option, } #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct UpdateLayerRequest { pub name: Option, pub start_ms: Option, pub end_ms: Option, pub x: Option, pub y: Option, pub width: Option, pub height: Option, pub rotation: Option, pub opacity: Option, pub properties: Option, pub animation_in: Option, pub animation_out: Option, pub locked: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AddAudioRequest { pub name: Option, pub source_url: String, pub track_type: Option, pub start_ms: Option, pub duration_ms: Option, pub volume: Option, } #[derive(Debug, Clone, Serialize, Deserialize, Default)] pub struct UpdateAudioRequest { pub name: Option, pub start_ms: Option, pub duration_ms: Option, pub volume: Option, pub fade_in_ms: Option, pub fade_out_ms: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SplitClipRequest { pub at_ms: i64, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ChatEditRequest { pub message: String, pub playhead_ms: Option, pub selection: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct PreviewFrameRequest { pub at_ms: Option, pub width: Option, pub height: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TranscribeRequest { pub clip_id: Option, pub language: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct GenerateCaptionsRequest { pub style: Option, pub max_chars_per_line: Option, pub font_size: Option, pub color: Option, pub background: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TTSRequest { pub text: String, pub voice: Option, pub speed: Option, pub language: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AutoReframeRequest { pub target_width: i32, pub target_height: i32, pub focus_mode: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ApplyTemplateRequest { pub template_id: String, pub customizations: Option>, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TransitionRequest { pub transition_type: String, pub duration_ms: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ExportRequest { pub format: Option, pub quality: Option, pub save_to_library: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct BackgroundRemovalRequest { pub clip_id: Uuid, pub replacement: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct VideoEnhanceRequest { pub clip_id: Uuid, pub upscale_factor: Option, pub denoise: Option, pub stabilize: Option, pub color_correct: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct BeatSyncRequest { pub audio_track_id: Uuid, pub sensitivity: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AddKeyframeRequest { pub property_name: String, pub time_ms: i64, pub value: serde_json::Value, pub easing: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct WaveformRequest { pub audio_track_id: Uuid, pub samples_per_second: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RecordViewRequest { pub export_id: Uuid, pub watch_time_ms: i64, pub completed: bool, pub country: Option, pub device: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ProjectFilters { pub status: Option, pub search: Option, pub limit: Option, pub offset: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ProjectResponse { pub id: Uuid, pub name: String, pub description: Option, pub resolution_width: i32, pub resolution_height: i32, pub fps: i32, pub total_duration_ms: i64, pub playhead_ms: i64, pub zoom_level: f32, pub thumbnail_url: Option, pub status: String, pub clips_count: usize, pub layers_count: usize, pub created_at: DateTime, pub updated_at: DateTime, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ProjectDetailResponse { pub project: ProjectResponse, pub clips: Vec, pub layers: Vec, pub audio_tracks: Vec, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ChatEditResponse { pub success: bool, pub message: String, pub commands_executed: Vec, pub project: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct UploadResponse { pub file_url: String, pub file_name: String, pub file_size: u64, pub mime_type: String, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TranscriptionSegment { pub start_ms: i64, pub end_ms: i64, pub text: String, pub confidence: f32, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TranscriptionResponse { pub segments: Vec, pub full_text: String, pub language: String, pub duration_ms: i64, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TTSResponse { pub audio_url: String, pub duration_ms: i64, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SceneInfo { pub start_ms: i64, pub end_ms: i64, pub thumbnail_url: Option, pub description: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct SceneDetectionResponse { pub scenes: Vec, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct TemplateInfo { pub id: String, pub name: String, pub description: String, pub thumbnail_url: String, pub duration_ms: i64, pub category: String, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ExportStatusResponse { pub id: Uuid, pub status: String, pub progress: i32, pub output_url: Option, pub gbdrive_path: Option, pub error_message: Option, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct BackgroundRemovalResponse { pub processed_url: String, pub duration_ms: i64, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct VideoEnhanceResponse { pub enhanced_url: String, pub enhancements_applied: Vec, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct BeatMarker { pub time_ms: i64, pub strength: f32, pub beat_type: String, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct BeatSyncResponse { pub beats: Vec, pub tempo_bpm: f32, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct WaveformResponse { pub samples: Vec, pub duration_ms: i64, pub sample_rate: i32, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct RetentionPoint { pub percent: f32, pub viewers: i64, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct GeoData { pub country: String, pub views: i64, pub percent: f32, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct DeviceBreakdown { pub desktop: f32, pub mobile: f32, pub tablet: f32, pub tv: f32, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AnalyticsResponse { pub views: i64, pub unique_viewers: i64, pub total_watch_time_ms: i64, pub avg_watch_percent: f32, pub completions: i64, pub shares: i64, pub likes: i64, pub engagement_score: f32, pub viewer_retention: Vec, pub top_countries: Vec, pub devices: DeviceBreakdown, } #[derive(Debug, Clone, Serialize, Deserialize)] pub struct ExportProgressEvent { pub export_id: Uuid, pub project_id: Uuid, pub status: String, pub progress: i32, pub message: Option, pub output_url: Option, pub gbdrive_path: Option, } pub enum ProjectStatus { Draft, Editing, Exporting, Published, Archived, } impl std::fmt::Display for ProjectStatus { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Draft => write!(f, "draft"), Self::Editing => write!(f, "editing"), Self::Exporting => write!(f, "exporting"), Self::Published => write!(f, "published"), Self::Archived => write!(f, "archived"), } } } impl From<&str> for ProjectStatus { fn from(s: &str) -> Self { match s.to_lowercase().as_str() { "editing" => Self::Editing, "exporting" => Self::Exporting, "published" => Self::Published, "archived" => Self::Archived, _ => Self::Draft, } } } pub enum ExportStatus { Pending, Processing, Completed, Failed, } impl std::fmt::Display for ExportStatus { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { Self::Pending => write!(f, "pending"), Self::Processing => write!(f, "processing"), Self::Completed => write!(f, "completed"), Self::Failed => write!(f, "failed"), } } }