sreepathi-ravikumar commited on
Commit
2f97d5f
·
verified ·
1 Parent(s): 11113c7

Update rust_combiner/src/lib.rs

Browse files
Files changed (1) hide show
  1. rust_combiner/src/lib.rs +29 -97
rust_combiner/src/lib.rs CHANGED
@@ -1,97 +1,29 @@
1
- use pyo3::prelude::*;
2
- use std::process::Command;
3
- use std::path::Path;
4
-
5
- #[pyfunction]
6
- fn render_video(
7
- id: usize,
8
- image_path: String,
9
- audio_path: String,
10
- duration: f64,
11
- words: Vec<(String, (u32, u32, u32, u32))>,
12
- output_dir: String,
13
- ) -> PyResult<String> {
14
- // Validate paths
15
- if !Path::new(&image_path).exists() {
16
- return Err(pyo3::exceptions::PyFileNotFoundError::new_err(format!(
17
- "Image not found: {}",
18
- image_path
19
- )));
20
- }
21
- if !Path::new(&audio_path).exists() {
22
- return Err(pyo3::exceptions::PyFileNotFoundError::new_err(format!(
23
- "Audio not found: {}",
24
- audio_path
25
- )));
26
- }
27
-
28
- let output_path = format!("{}/clip{}.mp4", output_dir, id);
29
- let duration_str = duration.to_string();
30
- let n_words = words.len() as f64;
31
- let highlight_duration = duration / n_words;
32
-
33
- // Build complex filter graph
34
- let mut filter_complex = String::new();
35
- let mut last_output = "0:v".to_string();
36
-
37
- for (i, (_, (x, y, w, h))) in words.iter().enumerate() {
38
- let start = i as f64 * highlight_duration;
39
- let end = start + highlight_duration;
40
-
41
- filter_complex.push_str(&format!(
42
- "[{last_out}]drawbox=x={x}:y={y}:w={w}:h={h}:[email protected]:t=fill:enable='between(t,{start:.3},{end:.3})'[v{i}];",
43
- last_out = last_output,
44
- x = x,
45
- y = y,
46
- w = w,
47
- h = h,
48
- start = start,
49
- end = end,
50
- i = i
51
- ));
52
- last_output = format!("[v{i}]");
53
- }
54
-
55
- // Remove trailing semicolon
56
- filter_complex.pop();
57
-
58
- // FFmpeg command
59
- let status = Command::new("ffmpeg")
60
- .args(&[
61
- "-y",
62
- "-hwaccel", "auto",
63
- "-loop", "1",
64
- "-i", &image_path,
65
- "-i", &audio_path,
66
- "-filter_complex", &filter_complex,
67
- "-map", &last_output,
68
- "-map", "1:a",
69
- "-c:v", "libx264",
70
- "-preset", "fast",
71
- "-crf", "18",
72
- "-pix_fmt", "yuv420p",
73
- "-movflags", "+faststart",
74
- "-c:a", "aac",
75
- "-b:a", "192k",
76
- "-r", "60",
77
- "-t", &duration_str,
78
- "-vsync", "2",
79
- &output_path,
80
- ])
81
- .status();
82
-
83
- match status {
84
- Ok(exit_status) if exit_status.success() => Ok(output_path),
85
- Ok(_) => Err(pyo3::exceptions::PyRuntimeError::new_err("FFmpeg command failed")),
86
- Err(e) => Err(pyo3::exceptions::PyRuntimeError::new_err(format!(
87
- "Failed to execute FFmpeg: {}",
88
- e
89
- ))),
90
- }
91
- }
92
-
93
- #[pymodule]
94
- fn rust_highlight(_py: Python, m: &PyModule) -> PyResult<()> {
95
- m.add_function(wrap_pyfunction!(render_video, m)?)?;
96
- Ok(())
97
- }
 
1
+ // rust_combiner/src/lib.rs use pyo3::prelude::*; use pyo3::wrap_pyfunction; use std::fs::File; use std::io::Write; use std::process::Command; use uuid::Uuid;
2
+
3
+ #[pyfunction] fn combine_clips(clips: Vec<String>) -> PyResult<String> { let paths: Vec<&str> = clips.iter().map(|s| s.as_str()).collect(); concat_videos(paths) }
4
+
5
+ fn concat_videos(clips: Vec<&str>) -> PyResult<String> { // Step 1: Write file list let list_file = format!("/tmp/clips_{}.txt", Uuid::new_v4()); let mut file = File::create(&list_file) .map_err(|e| pyo3::exceptions::PyIOError::new_err(e.to_string()))?; for clip in &clips { writeln!(file, "file '{}'", clip) .map_err(|e| pyo3::exceptions::PyIOError::new_err(e.to_string()))?; }
6
+
7
+ // Step 2: Run FFmpeg
8
+ let output_file = format!("/tmp/final_video_{}.mp4", Uuid::new_v4());
9
+ let status = Command::new("ffmpeg")
10
+ .args(&[
11
+ "-y",
12
+ "-f", "concat",
13
+ "-safe", "0",
14
+ "-i", &list_file,
15
+ "-c", "copy",
16
+ &output_file,
17
+ ])
18
+ .status()
19
+ .map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(e.to_string()))?;
20
+
21
+ if status.success() {
22
+ Ok(output_file)
23
+ } else {
24
+ Err(pyo3::exceptions::PyRuntimeError::new_err("FFmpeg command failed"))
25
+ }
26
+
27
+ }
28
+
29
+ #[pymodule] fn rust_combiner(_py: Python, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(combine_clips, m)?)?; Ok(()) }