@@ -275,38 +275,16 @@ async fn process_job(job: Job) -> Result<()> {
275275 let filter_complex = build_filter_complex ( & job. selection ) ?;
276276 info ! ( "FFmpeg filter: {}" , filter_complex) ;
277277
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- }
278+ // Local output path for FFmpeg
279+ let local_output_path = format ! ( "{}/output.mp4" , temp_dir) ;
280+ info ! ( "Local output path: {}" , local_output_path) ;
281+
282+ info ! ( "Starting FFmpeg (output to local file)..." ) ;
291283
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..." ) ;
304-
305- // Run FFmpeg command - output directly to WebDAV
306- // Use fragmented MP4 with empty_moov so we can stream without seeking
284+ // Run FFmpeg command - output to local file first
307285 let ffmpeg_result = tokio:: process:: Command :: new ( "ffmpeg" )
308286 . arg ( "-y" ) // Overwrite output
309- . arg ( "-i" ) . arg ( & video_url) // Input video
287+ . arg ( "-i" ) . arg ( & video_url) // Input video (streaming from WebDAV)
310288 . arg ( "-i" ) . arg ( bg_image_path) // Background image
311289 . arg ( "-filter_complex" ) . arg ( & filter_complex)
312290 . arg ( "-map" ) . arg ( "[outv]" )
@@ -315,10 +293,8 @@ async fn process_job(job: Job) -> Result<()> {
315293 . arg ( "-crf" ) . arg ( "18" )
316294 . arg ( "-preset" ) . arg ( "veryfast" )
317295 . arg ( "-threads" ) . arg ( "0" )
318- . arg ( "-c:a" ) . arg ( "aac" ) // Re-encode audio for fragmented mp4 compatibility
319- . arg ( "-movflags" ) . arg ( "frag_keyframe+empty_moov" ) // Fragmented MP4 for streaming
320- . arg ( "-method" ) . arg ( "PUT" ) // Use HTTP PUT for WebDAV
321- . arg ( & output_url)
296+ . arg ( "-c:a" ) . arg ( "copy" )
297+ . arg ( & local_output_path)
322298 . output ( )
323299 . await ;
324300
@@ -335,20 +311,57 @@ async fn process_job(job: Job) -> Result<()> {
335311 }
336312
337313 if output. status . success ( ) {
338- info ! ( "FFmpeg processing and direct WebDAV upload successful!" ) ;
339- info ! ( "Job {} completed successfully" , job. id) ;
314+ info ! ( "FFmpeg processing successful!" ) ;
340315
341- // Update job to completed via queue URL
342- if let Some ( queue_url) = & job. webdav_config . queue_url {
343- info ! ( "Updating job status to completed at: {}" , queue_url) ;
344- match update_job_status_remote ( queue_url, & job. id , JobStatus :: Completed , None ) . await {
345- Ok ( _) => info ! ( "Status update successful" ) ,
346- Err ( e) => error ! ( "Status update failed: {}" , e) ,
316+ // Check output file size
317+ match fs:: metadata ( & local_output_path) {
318+ Ok ( meta) => info ! ( "Output file size: {} bytes" , meta. len( ) ) ,
319+ Err ( e) => error ! ( "Failed to stat output file: {}" , e) ,
320+ }
321+
322+ // Now upload to WebDAV
323+ info ! ( "Reading output file for upload..." ) ;
324+ let output_data = fs:: read ( & local_output_path) ?;
325+ info ! ( "Read {} bytes, uploading to WebDAV..." , output_data. len( ) ) ;
326+
327+ let dav_client = WebDavClient :: new ( & job. webdav_config ) ?;
328+
329+ // Create the output folder on WebDAV if needed
330+ // job.output_path is like "processed/filename.mp4"
331+ if let Some ( folder_end) = job. output_path . rfind ( '/' ) {
332+ let folder = & job. output_path [ ..folder_end] ;
333+ if !folder. is_empty ( ) {
334+ info ! ( "Ensuring folder exists: {}" , folder) ;
335+ if let Err ( e) = dav_client. ensure_folder_exists ( folder) . await {
336+ warn ! ( "Could not create folder {}: {} (may already exist)" , folder, e) ;
337+ }
338+ }
339+ }
340+
341+ info ! ( "Uploading to: {}" , job. output_path) ;
342+ match dav_client. upload_file ( & job. output_path , output_data) . await {
343+ Ok ( _) => {
344+ info ! ( "Upload successful!" ) ;
345+ info ! ( "Job {} completed successfully" , job. id) ;
346+
347+ // Update job to completed via queue URL
348+ if let Some ( queue_url) = & job. webdav_config . queue_url {
349+ info ! ( "Updating job status to completed at: {}" , queue_url) ;
350+ match update_job_status_remote ( queue_url, & job. id , JobStatus :: Completed , None ) . await {
351+ Ok ( _) => info ! ( "Status update successful" ) ,
352+ Err ( e) => error ! ( "Status update failed: {}" , e) ,
353+ }
354+ }
355+ }
356+ Err ( e) => {
357+ error ! ( "Upload FAILED: {}" , e) ;
358+ if let Some ( queue_url) = & job. webdav_config . queue_url {
359+ let _ = update_job_status_remote ( queue_url, & job. id , JobStatus :: Failed , None ) . await ;
360+ }
347361 }
348362 }
349363 } else {
350364 error ! ( "FFmpeg FAILED with exit code: {}" , output. status) ;
351- error ! ( "Direct WebDAV output failed - check FFmpeg stderr above for details" ) ;
352365
353366 if let Some ( queue_url) = & job. webdav_config . queue_url {
354367 let _ = update_job_status_remote ( queue_url, & job. id , JobStatus :: Failed , None ) . await ;
@@ -423,19 +436,6 @@ fn build_webdav_download_url(config: &WebDavConfig, path: &str) -> String {
423436 )
424437 . replacen ( "://" , & format ! ( "://{}:{}@" , encode( & config. username) , encode( & config. password) ) , 1 )
425438}
426-
427- fn build_webdav_upload_url ( config : & WebDavConfig , output_path : & str ) -> String {
428- // Build full WebDAV URL for uploading
429- // config.url is like: https://cloud.example.com/remote.php/dav/files/user/VideoTest
430- // output_path is like: processed/filename.mp4
431- // Result: https://user:pass@cloud.example.com/remote.php/dav/files/user/VideoTest/processed/filename.mp4
432-
433- let base_url = config. url . trim_end_matches ( '/' ) ;
434- let full_url = format ! ( "{}/{}" , base_url, output_path) ;
435-
436- full_url. replacen ( "://" , & format ! ( "://{}:{}@" , encode( & config. username) , encode( & config. password) ) , 1 )
437- }
438-
439439async fn update_job_status_remote (
440440 queue_url : & str ,
441441 job_id : & str ,
0 commit comments