import streamlit as st import tempfile import subprocess import os import re # Page settings st.set_page_config(page_title="Video Speed Tool", layout="centered") # CSS styling for mobile st.markdown(""" """, unsafe_allow_html=True) # Title st.markdown('
🎬 Video Speed Tool
', unsafe_allow_html=True) # Upload file uploaded_file = st.file_uploader("Upload video", type=["mp4", "mov", "avi", "mkv"]) # Speed input speed = st.number_input( "Speed (0.25x - 4x)", min_value=0.25, max_value=4.0, value=1.5, step=0.05 ) if uploaded_file is not None: st.video(uploaded_file) if st.button("PROCESS VIDEO"): with st.spinner("Processing... Please wait"): with tempfile.NamedTemporaryFile(delete=False, suffix=".mp4") as tmp_input: tmp_input.write(uploaded_file.read()) input_path = tmp_input.name output_path = tempfile.NamedTemporaryFile(delete=False, suffix=".mp4").name video_speed = 1 / speed audio_speed = speed # Always compress cmd = [ "ffmpeg", "-i", input_path, "-filter_complex", f"[0:v]setpts={video_speed}*PTS[v];[0:a]atempo={audio_speed}[a]", "-map", "[v]", "-map", "[a]", "-vcodec", "libx264", "-crf", "28", "-preset", "fast", "-movflags", "+faststart", "-y", output_path ] # Progress bar progress_text = st.empty() progress_bar = st.progress(0) # Get video duration probe = subprocess.run( ["ffprobe", "-v", "error", "-show_entries", "format=duration", "-of", "default=noprint_wrappers=1:nokey=1", input_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True ) try: total_duration = float(probe.stdout.strip()) except: total_duration = None # Run ffmpeg with live progress process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, bufsize=1) for line in process.stdout: if "time=" in line and total_duration: match = re.search(r"time=(\d+:\d+:\d+\.\d+)", line) if match: h, m, s = match.group(1).split(":") elapsed = int(h) * 3600 + int(m) * 60 + float(s) percent = min(int((elapsed / total_duration) * 100), 100) progress_bar.progress(percent) progress_text.text(f"Processing... {percent}%") process.wait() progress_bar.progress(100) progress_text.text("✅ Processing complete!") # Show processed video st.video(output_path) # Download button centered with open(output_path, "rb") as f: st.download_button( label="DOWNLOAD VIDEO", data=f, file_name="processed_video.mp4", mime="video/mp4" ) os.remove(input_path) os.remove(output_path)