1#[cfg(feature = "serde")]
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, PartialEq, Eq)]
11#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
12pub enum AspectRatio {
13 Widescreen,
15 Vertical,
17 Square,
19 Custom(String),
21}
22
23#[derive(Debug, Clone, PartialEq, Eq)]
25#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
26pub struct VideoRequest {
27 pub prompt: String,
29 pub aspect_ratio: AspectRatio,
31 pub duration_seconds: u32,
33 pub negative_prompt: Option<String>,
35 pub model: Option<String>,
37}
38
39impl VideoRequest {
40 pub fn new(prompt: impl Into<String>) -> Self {
42 Self {
43 prompt: prompt.into(),
44 aspect_ratio: AspectRatio::Widescreen,
45 duration_seconds: 8,
46 negative_prompt: None,
47 model: None,
48 }
49 }
50
51 pub fn aspect_ratio(mut self, aspect_ratio: AspectRatio) -> Self {
53 self.aspect_ratio = aspect_ratio;
54 self
55 }
56
57 pub fn duration_seconds(mut self, seconds: u32) -> Self {
59 self.duration_seconds = seconds;
60 self
61 }
62
63 pub fn negative_prompt(mut self, prompt: impl Into<String>) -> Self {
65 self.negative_prompt = Some(prompt.into());
66 self
67 }
68
69 pub fn model(mut self, model: impl Into<String>) -> Self {
71 self.model = Some(model.into());
72 self
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn creates_default_video_request() {
82 let request = VideoRequest::new("A cinematic city scene");
83
84 assert_eq!(request.duration_seconds, 8);
85 assert_eq!(request.aspect_ratio, AspectRatio::Widescreen);
86 }
87
88 #[test]
89 fn updates_video_request_fields() {
90 let request = VideoRequest::new("A product video")
91 .aspect_ratio(AspectRatio::Vertical)
92 .duration_seconds(12)
93 .negative_prompt("blurry")
94 .model("gemini-omni");
95
96 assert_eq!(request.duration_seconds, 12);
97 assert_eq!(request.aspect_ratio, AspectRatio::Vertical);
98 assert_eq!(request.negative_prompt, Some("blurry".to_string()));
99 assert_eq!(request.model, Some("gemini-omni".to_string()));
100 }
101}