1#[cfg(feature = "serde")]
8use serde::{Deserialize, Serialize};
9
10#[derive(Debug, Clone, PartialEq, Eq)]
12#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
13pub enum AspectRatio {
14 Widescreen,
16 Vertical,
18 Square,
20 Custom(String),
22}
23
24#[derive(Debug, Clone, PartialEq, Eq)]
26#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
27pub struct VideoRequest {
28 pub prompt: String,
30 pub aspect_ratio: AspectRatio,
32 pub duration_seconds: u32,
34 pub negative_prompt: Option<String>,
36 pub model: Option<String>,
38}
39
40impl VideoRequest {
41 pub fn new(prompt: impl Into<String>) -> Self {
43 Self {
44 prompt: prompt.into(),
45 aspect_ratio: AspectRatio::Widescreen,
46 duration_seconds: 8,
47 negative_prompt: None,
48 model: None,
49 }
50 }
51
52 pub fn aspect_ratio(mut self, aspect_ratio: AspectRatio) -> Self {
54 self.aspect_ratio = aspect_ratio;
55 self
56 }
57
58 pub fn duration_seconds(mut self, seconds: u32) -> Self {
60 self.duration_seconds = seconds;
61 self
62 }
63
64 pub fn negative_prompt(mut self, prompt: impl Into<String>) -> Self {
66 self.negative_prompt = Some(prompt.into());
67 self
68 }
69
70 pub fn model(mut self, model: impl Into<String>) -> Self {
72 self.model = Some(model.into());
73 self
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn creates_default_video_request() {
83 let request = VideoRequest::new("Golden-hour timelapse over a mountain ridge");
84
85 assert_eq!(request.duration_seconds, 8);
86 assert_eq!(request.aspect_ratio, AspectRatio::Widescreen);
87 }
88
89 #[test]
90 fn updates_video_request_fields() {
91 let request = VideoRequest::new("A handheld shot walking through a rainy alley")
92 .aspect_ratio(AspectRatio::Vertical)
93 .duration_seconds(12)
94 .negative_prompt("blurry")
95 .model("muse-video");
96
97 assert_eq!(request.duration_seconds, 12);
98 assert_eq!(request.aspect_ratio, AspectRatio::Vertical);
99 assert_eq!(request.negative_prompt, Some("blurry".to_string()));
100 assert_eq!(request.model, Some("muse-video".to_string()));
101 }
102}