Skip to content

Commit 2d74529

Browse files
committed
video example
1 parent 2728dd7 commit 2d74529

File tree

4 files changed

+117
-0
lines changed

4 files changed

+117
-0
lines changed

examples/video/Cargo.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
[package]
2+
name = "video"
3+
version = "0.1.0"
4+
edition = "2021"
5+
publish = false
6+
7+
[dependencies]
8+
async-openai = {path = "../../async-openai"}
9+
tokio = { version = "1.43.0", features = ["full"] }
10+
bytes = "1.9.0"
11+

examples/video/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Image Credits:
2+
3+
https://cdn.openai.com/API/docs/images/sora/monster_original_720p.jpeg
338 KB
Loading

examples/video/src/main.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
use async_openai::{
2+
config::OpenAIConfig,
3+
types::{CreateVideoRequestArgs, VideoJob, VideoSize, VideoVariant},
4+
Client,
5+
};
6+
use bytes::Bytes;
7+
use std::error::Error;
8+
9+
pub async fn save<P: AsRef<std::path::Path>>(
10+
bytes: Bytes,
11+
file_path: P,
12+
) -> Result<(), Box<dyn Error>> {
13+
let dir = file_path.as_ref().parent();
14+
if let Some(dir) = dir {
15+
tokio::fs::create_dir_all(dir).await?;
16+
}
17+
18+
tokio::fs::write(file_path, &bytes).await?;
19+
20+
Ok(())
21+
}
22+
23+
async fn create_video(client: &Client<OpenAIConfig>) -> Result<VideoJob, Box<dyn Error>> {
24+
let request = CreateVideoRequestArgs::default()
25+
.model("sora-2")
26+
.prompt("Fridge opens, cat walks out, and celebrates a birthday party")
27+
.input_reference("./input/monster_original_720p.jpeg")
28+
.size(VideoSize::S1280x720) // size of input image
29+
.build()?;
30+
31+
println!("Generating video...");
32+
let response = client.videos().create(request).await?;
33+
34+
println!("Video generation started!");
35+
println!("Video ID: {}", response.id);
36+
println!("Status: {}", response.status);
37+
println!("Model: {}", response.model);
38+
println!("Size: {}", response.size);
39+
println!("Duration: {} seconds", response.seconds);
40+
41+
// Poll for completion
42+
let video_id = &response.id;
43+
loop {
44+
let status_response = client.videos().retrieve(video_id).await?;
45+
println!("Current status: {}", status_response.status);
46+
47+
match status_response.status.as_str() {
48+
"completed" => {
49+
println!("Video generation completed!");
50+
break;
51+
}
52+
"failed" => {
53+
println!("Video generation failed!");
54+
if let Some(error) = status_response.error {
55+
println!("Error: {:?}", error);
56+
}
57+
return Err("Video generation failed".into());
58+
}
59+
_ => {
60+
println!("Progress: {}%", status_response.progress);
61+
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
62+
}
63+
}
64+
}
65+
66+
Ok(response)
67+
}
68+
69+
#[tokio::main]
70+
async fn main() -> Result<(), Box<dyn Error>> {
71+
let client = Client::new();
72+
let _video = create_video(&client).await?;
73+
// wait for above video to be "completed"
74+
tokio::time::sleep(tokio::time::Duration::from_secs(5)).await;
75+
let videos = client.videos().list(&[("limit", "100")]).await?;
76+
77+
for video in &videos.data {
78+
println!("Video: {:#?}", video);
79+
80+
if video.status == "completed" {
81+
let content = client
82+
.videos()
83+
.download_content(&video.id, VideoVariant::Video)
84+
.await;
85+
if let Ok(content) = content {
86+
let output_path = &format!("./data/{}.mp4", video.id);
87+
save(content, output_path).await?;
88+
println!("Video saved to {}", output_path);
89+
} else {
90+
println!("cannot download video: {:?}", content);
91+
}
92+
}
93+
}
94+
95+
for video in videos.data {
96+
println!(
97+
"\nVideo deleted: {:?}",
98+
client.videos().delete(&video.id).await?
99+
);
100+
}
101+
102+
Ok(())
103+
}

0 commit comments

Comments
 (0)