use pyo3::prelude::*; use pyo3::wrap_pyfunction; use std::fs::File; use std::io::Write; use std::process::Command; use uuid::Uuid; #[pyfunction] fn combine_clips(clips: Vec) -> PyResult { let paths: Vec<&str> = clips.iter().map(|s| s.as_str()).collect(); concat_videos(paths) } fn concat_videos(clips: Vec<&str>) -> PyResult { // 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()))?; } // Step 2: Run FFmpeg let output_file = format!("/tmp/final_video_{}.mp4", Uuid::new_v4()); let status = Command::new("ffmpeg") .args(&[ "-y", "-f", "concat", "-safe", "0", "-i", &list_file, "-c", "copy", &output_file, ]) .status() .map_err(|e| pyo3::exceptions::PyRuntimeError::new_err(e.to_string()))?; if status.success() { Ok(output_file) } else { Err(pyo3::exceptions::PyRuntimeError::new_err("FFmpeg command failed")) } } #[pymodule] fn rust_combiner(_py: Python, m: &PyModule) -> PyResult<()> { m.add_function(wrap_pyfunction!(combine_clips, m)?)?; Ok(()) }