From c9410c9c91452a9ac4fe31bf62e75208249ef2bd Mon Sep 17 00:00:00 2001 From: Cameron Date: Mon, 26 Jan 2026 10:55:15 -0500 Subject: [PATCH] Add rotation check to video transcoding logic Seems like vertical videos aren't preserving rotation logic on copy. --- src/video/actors.rs | 47 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 3 deletions(-) diff --git a/src/video/actors.rs b/src/video/actors.rs index 51721a9..a6c59e9 100644 --- a/src/video/actors.rs +++ b/src/video/actors.rs @@ -138,6 +138,36 @@ async fn is_h264_encoded(video_path: &str) -> bool { } } +/// Check if a video has rotation metadata +/// Returns the rotation angle in degrees (0, 90, 180, 270) or 0 if none detected +async fn get_video_rotation(video_path: &str) -> i32 { + let output = tokio::process::Command::new("ffprobe") + .arg("-v") + .arg("error") + .arg("-select_streams") + .arg("v:0") + .arg("-show_entries") + .arg("stream_tags=rotate") + .arg("-of") + .arg("default=noprint_wrappers=1:nokey=1") + .arg(video_path) + .output() + .await; + + match output { + Ok(output) if output.status.success() => { + let rotation_str = String::from_utf8_lossy(&output.stdout); + let rotation_str = rotation_str.trim(); + if rotation_str.is_empty() { + 0 + } else { + rotation_str.parse::().unwrap_or(0) + } + } + _ => 0, + } +} + pub struct VideoPlaylistManager { playlist_dir: PathBuf, playlist_generator: Addr, @@ -346,9 +376,19 @@ impl Handler for PlaylistGenerator { // Check if video is already h264 encoded let is_h264 = is_h264_encoded(&video_file).await; - let use_copy = is_h264; - if use_copy { + // Check for rotation metadata + let rotation = get_video_rotation(&video_file).await; + let has_rotation = rotation != 0; + + let use_copy = is_h264 && !has_rotation; + + if has_rotation { + info!("Video {} has rotation metadata ({}°), transcoding to apply rotation", video_file, rotation); + span.add_event("Transcoding due to rotation", vec![ + KeyValue::new("rotation_degrees", rotation as i64) + ]); + } else if use_copy { info!("Video {} is already h264, using stream copy", video_file); span.add_event("Using stream copy (h264 detected)", vec![]); } else { @@ -362,10 +402,11 @@ impl Handler for PlaylistGenerator { if use_copy { // Video is already h264, just copy the stream + // Note: rotation metadata will be preserved in the stream cmd.arg("-c:v").arg("copy"); cmd.arg("-c:a").arg("aac"); // Still need to ensure audio is compatible } else { - // Need to transcode + // Need to transcode - autorotate is enabled by default and will apply rotation cmd.arg("-c:v").arg("h264"); cmd.arg("-crf").arg("21"); cmd.arg("-preset").arg("veryfast");