import os import glob import subprocess import uuid import re import select import shutil import time import streamlit as st def run_command_with_progress(command, status_placeholder, progress_bar, tool_name, is_trimming=False): process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True, universal_newlines=True) status_placeholder.text(f"Using {tool_name}...") output_lines = [] error_lines = [] duration = None while True: reads = [process.stdout.fileno(), process.stderr.fileno()] ret = select.select(reads, [], [], 0.1) for fd in ret[0]: if fd == process.stdout.fileno(): read = process.stdout.readline() if read: output_lines.append(read.strip()) status_placeholder.text(f"{tool_name}: {read.strip()}") if '[download]' in read: match = re.search(r'(\d+\.\d+)%', read) if match: progress = min(float(match.group(1)), 100) / 100 progress_bar.progress(progress) if fd == process.stderr.fileno(): read = process.stderr.readline() if read: error_lines.append(read.strip()) # Parse ffmpeg output if tool_name == "ffmpeg": duration_match = re.search(r'Duration: (\d{2}):(\d{2}):(\d{2}\.\d{2})', read) if duration_match: hours, minutes, seconds = map(float, duration_match.groups()) duration = hours * 3600 + minutes * 60 + seconds time_match = re.search(r'time=(\d{2}):(\d{2}):(\d{2}\.\d{2})', read) if time_match and duration: hours, minutes, seconds = map(float, time_match.groups()) current_time = hours * 3600 + minutes * 60 + seconds progress = min((current_time / duration), 1) status_placeholder.text(f"{tool_name}: {progress*100:.2f}% complete") progress_bar.progress(progress) if process.poll() is not None: break return_code = process.poll() if return_code != 0: st.error(f"Error occurred during {tool_name} processing:") for line in error_lines[-10:]: # Display last 10 error lines st.error(line) return return_code def process_video(url, status_callback=None): session_id = str(uuid.uuid4()) output_dir = f"./output_folder_{session_id}" os.makedirs(output_dir, exist_ok=True) for file in glob.glob(f"{output_dir}/*"): os.remove(file) content_type = "playlist" if "list=" in url else "video" format = "bestvideo[height<=1080][ext=mp4]+bestaudio[ext=m4a]/best[height<=1080][ext=mp4]" download_command = f'yt-dlp --cookies cookies.txt -f "{format}" -N 64 -o "{output_dir}/%(title)s.%(ext)s" "{url}"' status_placeholder = st.empty() if status_callback is None else status_callback progress_bar = st.progress(0) return_code = run_command_with_progress(download_command, status_placeholder, progress_bar, "yt-dlp") if return_code != 0: return None, "Error occurred during download." if content_type == "video": video_file = glob.glob(f"{output_dir}/*.mp4")[0] trimmed_file = video_file.replace(".mp4", "_trimmed.mp4") progress_bar.progress(0) auto_editor_command = f'auto-editor "{video_file}" --margin 0.5sec --output "{trimmed_file}"' return_code = run_command_with_progress(auto_editor_command, status_placeholder, progress_bar, "auto-editor", is_trimming=True) if return_code != 0: return None, "Error occurred during trimming." final_file = trimmed_file.replace("_trimmed.mp4", f"_f_{session_id}.mp4") progress_bar.progress(0) ffmpeg_command = f'ffmpeg -y -i "{trimmed_file}" -map 0:v:0 -map 0:a:0 -c:v libx264 -preset ultrafast -crf 23 -maxrate 25M -vf "scale=-1:1080" -c:a aac -b:a 192k -ac 2 -strict -2 "{final_file}"' return_code = run_command_with_progress(ffmpeg_command, status_placeholder, progress_bar, "ffmpeg") if return_code != 0: return None, "Error occurred during final processing." return final_file, None elif content_type == "playlist": trimmed_dir = f"{output_dir}/trimmed" os.makedirs(trimmed_dir, exist_ok=True) for video_file in glob.glob(f"{output_dir}/*.mp4"): video_name = os.path.basename(video_file).replace(".mp4", "") trimmed_file = f"{trimmed_dir}/{video_name}_trimmed.mp4" progress_bar.progress(0) auto_editor_command = f'auto-editor "{video_file}" --margin 0.5sec --output "{trimmed_file}" --verbose' return_code = run_command_with_progress(auto_editor_command, status_placeholder, progress_bar, "auto-editor", is_trimming=True) if return_code != 0: continue final_file = f"{trimmed_dir}/{video_name}_f.mp4" progress_bar.progress(0) ffmpeg_command = f'ffmpeg -y -i "{trimmed_file}" -map 0:v:0 -map 0:a:0 -c:v libx264 -preset ultrafast -crf 23 -maxrate 25M -vf "scale=-1:1080" -c:a aac -b:a 192k -ac 2 -strict -2 "{final_file}"' return_code = run_command_with_progress(ffmpeg_command, status_placeholder, progress_bar, "ffmpeg") if return_code != 0: continue return trimmed_dir, None def get_job_status(session_id): output_dir = f"./output_folder_{session_id}" if not os.path.exists(output_dir): return "Job not found" if glob.glob(f"{output_dir}/*_f_{session_id}.mp4"): return "Completed" elif glob.glob(f"{output_dir}/trimmed/*_f.mp4"): return "Completed" elif glob.glob(f"{output_dir}/*.mp4"): return "Processing" else: return "Downloading" def get_job_result(session_id): output_dir = f"./output_folder_{session_id}" if not os.path.exists(output_dir): return None single_video = glob.glob(f"{output_dir}/*_f_{session_id}.mp4") if single_video: return single_video[0] playlist_dir = f"{output_dir}/trimmed" if os.path.exists(playlist_dir): return playlist_dir return None