viewpoint_core/page/video_io/
mod.rs1use std::path::{Path, PathBuf};
6
7use tracing::info;
8
9use crate::error::PageError;
10
11use super::video::Video;
12
13impl Video {
14 pub async fn save_as(&self, path: impl AsRef<Path>) -> Result<(), PageError> {
24 let current_path = self.path().await?;
25 let target_path = path.as_ref();
26
27 if let Some(parent) = target_path.parent() {
29 tokio::fs::create_dir_all(parent)
30 .await
31 .map_err(|e| PageError::EvaluationFailed(format!("Failed to create directory: {e}")))?;
32 }
33
34 tokio::fs::copy(¤t_path, target_path)
36 .await
37 .map_err(|e| PageError::EvaluationFailed(format!("Failed to copy video: {e}")))?;
38
39 let state = self.state.read().await;
41 if let Some(ref video_path) = state.video_path {
42 if let Ok(content) = tokio::fs::read_to_string(video_path).await {
44 if let Ok(metadata) = serde_json::from_str::<serde_json::Value>(&content) {
45 if let Some(frames_dir) = metadata.get("frames_dir").and_then(|v| v.as_str()) {
46 let source_frames = PathBuf::from(frames_dir);
47 if source_frames.exists() {
48 let target_frames = target_path.with_extension("frames");
49 copy_dir_recursive(&source_frames, &target_frames).await?;
50 }
51 }
52 }
53 }
54 }
55
56 info!("Video saved to {:?}", target_path);
57 Ok(())
58 }
59
60 pub async fn delete(&self) -> Result<(), PageError> {
70 let state = self.state.read().await;
71
72 if let Some(ref video_path) = state.video_path {
73 if let Ok(content) = tokio::fs::read_to_string(video_path).await {
75 if let Ok(metadata) = serde_json::from_str::<serde_json::Value>(&content) {
76 if let Some(frames_dir) = metadata.get("frames_dir").and_then(|v| v.as_str()) {
77 let frames_path = PathBuf::from(frames_dir);
78 if frames_path.exists() {
79 let _ = tokio::fs::remove_dir_all(&frames_path).await;
80 }
81 }
82 }
83 }
84
85 tokio::fs::remove_file(video_path)
87 .await
88 .map_err(|e| PageError::EvaluationFailed(format!("Failed to delete video: {e}")))?;
89
90 info!("Video deleted");
91 }
92
93 Ok(())
94 }
95}
96
97pub(super) async fn copy_dir_recursive(src: &Path, dst: &Path) -> Result<(), PageError> {
99 tokio::fs::create_dir_all(dst)
100 .await
101 .map_err(|e| PageError::EvaluationFailed(format!("Failed to create directory: {e}")))?;
102
103 let mut entries = tokio::fs::read_dir(src)
104 .await
105 .map_err(|e| PageError::EvaluationFailed(format!("Failed to read directory: {e}")))?;
106
107 while let Some(entry) = entries.next_entry().await.map_err(|e| {
108 PageError::EvaluationFailed(format!("Failed to read directory entry: {e}"))
109 })? {
110 let src_path = entry.path();
111 let dst_path = dst.join(entry.file_name());
112
113 if src_path.is_dir() {
114 Box::pin(copy_dir_recursive(&src_path, &dst_path)).await?;
115 } else {
116 tokio::fs::copy(&src_path, &dst_path)
117 .await
118 .map_err(|e| PageError::EvaluationFailed(format!("Failed to copy file: {e}")))?;
119 }
120 }
121
122 Ok(())
123}