Skip to content

Commit 54a743e

Browse files
Merge pull request #4 from Traverse-Research/jasper-bekkers/processed-folder-output
Jasper bekkers/processed folder output
2 parents 59b6f27 + fd5574a commit 54a743e

File tree

3 files changed

+66
-37
lines changed

3 files changed

+66
-37
lines changed

src/jobs.rs

Lines changed: 43 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -271,16 +271,38 @@ async fn process_job(job: Job) -> Result<()> {
271271
}
272272
}
273273

274-
let output_path = format!("{}/output.mp4", temp_dir);
275-
info!("Output path: {}", output_path);
276-
277274
// Build FFmpeg filter complex based on quadrant selection
278275
let filter_complex = build_filter_complex(&job.selection)?;
279276
info!("FFmpeg filter: {}", filter_complex);
280277

281-
info!("Starting FFmpeg...");
278+
// Create the output folder on WebDAV if needed (before FFmpeg runs)
279+
// job.output_path is like "processed/filename.mp4"
280+
if let Some(folder_end) = job.output_path.rfind('/') {
281+
let folder = &job.output_path[..folder_end];
282+
if !folder.is_empty() {
283+
info!("Creating WebDAV client to ensure folder exists...");
284+
let dav_client = WebDavClient::new(&job.webdav_config)?;
285+
info!("Ensuring folder exists: {}", folder);
286+
if let Err(e) = dav_client.ensure_folder_exists(folder).await {
287+
warn!("Could not create folder {}: {} (may already exist)", folder, e);
288+
}
289+
}
290+
}
291+
292+
// Build WebDAV URL for direct output from FFmpeg
293+
let output_url = build_webdav_upload_url(&job.webdav_config, &job.output_path);
294+
info!("FFmpeg will output directly to WebDAV: {}", job.output_path);
295+
// Log URL without credentials for debugging
296+
let output_url_safe = output_url.replacen(
297+
&format!("://{}:{}@", encode(&job.webdav_config.username), encode(&job.webdav_config.password)),
298+
"://[credentials]@",
299+
1
300+
);
301+
info!("Output URL (redacted): {}", output_url_safe);
302+
303+
info!("Starting FFmpeg with direct WebDAV output...");
282304

283-
// Run FFmpeg command
305+
// Run FFmpeg command - output directly to WebDAV
284306
let ffmpeg_result = tokio::process::Command::new("ffmpeg")
285307
.arg("-y") // Overwrite output
286308
.arg("-i").arg(&video_url) // Input video
@@ -293,7 +315,8 @@ async fn process_job(job: Job) -> Result<()> {
293315
.arg("-preset").arg("veryfast")
294316
.arg("-threads").arg("0")
295317
.arg("-c:a").arg("copy")
296-
.arg(&output_path)
318+
.arg("-method").arg("PUT") // Use HTTP PUT for WebDAV
319+
.arg(&output_url)
297320
.output()
298321
.await;
299322

@@ -310,36 +333,7 @@ async fn process_job(job: Job) -> Result<()> {
310333
}
311334

312335
if output.status.success() {
313-
info!("FFmpeg processing successful!");
314-
315-
// Check output file
316-
match fs::metadata(&output_path) {
317-
Ok(meta) => info!("Output file size: {} bytes", meta.len()),
318-
Err(e) => error!("Failed to stat output file: {}", e),
319-
}
320-
321-
// Upload result back to WebDAV
322-
info!("Reading output file...");
323-
let output_data = fs::read(&output_path)?;
324-
info!("Output file read, size: {} bytes", output_data.len());
325-
326-
info!("Creating WebDAV client...");
327-
let dav_client = WebDavClient::new(&job.webdav_config)?;
328-
329-
// Extract just the filename from the full path for upload
330-
// output_path is like /remote.php/dav/files/jasper/VideoTest/test-2s_processed.mp4
331-
// We need just the filename: test-2s_processed.mp4
332-
let upload_filename = job.output_path
333-
.rsplit('/')
334-
.next()
335-
.unwrap_or(&job.output_path);
336-
337-
info!("Uploading processed video as: {} (from path: {})", upload_filename, job.output_path);
338-
match dav_client.upload_file(upload_filename, output_data).await {
339-
Ok(_) => info!("Upload successful!"),
340-
Err(e) => error!("Upload FAILED: {}", e),
341-
}
342-
336+
info!("FFmpeg processing and direct WebDAV upload successful!");
343337
info!("Job {} completed successfully", job.id);
344338

345339
// Update job to completed via queue URL
@@ -352,6 +346,7 @@ async fn process_job(job: Job) -> Result<()> {
352346
}
353347
} else {
354348
error!("FFmpeg FAILED with exit code: {}", output.status);
349+
error!("Direct WebDAV output failed - check FFmpeg stderr above for details");
355350

356351
if let Some(queue_url) = &job.webdav_config.queue_url {
357352
let _ = update_job_status_remote(queue_url, &job.id, JobStatus::Failed, None).await;
@@ -427,6 +422,18 @@ fn build_webdav_download_url(config: &WebDavConfig, path: &str) -> String {
427422
.replacen("://", &format!("://{}:{}@", encode(&config.username), encode(&config.password)), 1)
428423
}
429424

425+
fn build_webdav_upload_url(config: &WebDavConfig, output_path: &str) -> String {
426+
// Build full WebDAV URL for uploading
427+
// config.url is like: https://cloud.example.com/remote.php/dav/files/user/VideoTest
428+
// output_path is like: processed/filename.mp4
429+
// Result: https://user:pass@cloud.example.com/remote.php/dav/files/user/VideoTest/processed/filename.mp4
430+
431+
let base_url = config.url.trim_end_matches('/');
432+
let full_url = format!("{}/{}", base_url, output_path);
433+
434+
full_url.replacen("://", &format!("://{}:{}@", encode(&config.username), encode(&config.password)), 1)
435+
}
436+
430437
async fn update_job_status_remote(
431438
queue_url: &str,
432439
job_id: &str,

src/webdav.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,26 @@ impl WebDavClient {
114114

115115
Ok(())
116116
}
117+
118+
pub async fn create_folder(&self, path: &str) -> Result<()> {
119+
self.client
120+
.mkcol(path)
121+
.await
122+
.map_err(|e| anyhow!("Failed to create folder: {:?}", e))?;
123+
124+
Ok(())
125+
}
126+
127+
pub async fn ensure_folder_exists(&self, path: &str) -> Result<()> {
128+
// Try to create the folder - if it already exists, mkcol will fail but that's OK
129+
match self.client.mkcol(path).await {
130+
Ok(_) => Ok(()),
131+
Err(_) => {
132+
// Folder might already exist, which is fine
133+
Ok(())
134+
}
135+
}
136+
}
117137
}
118138

119139
pub async fn list_videos(

templates/index.html

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,9 @@ <h3>${video.name}</h3>
581581
const username = document.getElementById('webdav-username').value;
582582
const password = document.getElementById('webdav-password').value;
583583

584-
const output_path = videoPath.replace(/\.(mp4|mkv|mov|avi|webm)$/, '_processed.mp4');
584+
// Put output in /processed/ subfolder with same filename but .mp4 extension
585+
const filename = videoPath.split('/').pop().replace(/\.(mp4|mkv|mov|avi|webm)$/, '.mp4');
586+
const output_path = 'processed/' + filename;
585587

586588
try {
587589
const response = await fetch('/api/jobs', {

0 commit comments

Comments
 (0)