VideoCompressor / app.py
167AliRaza's picture
Update app.py
0f146e7 verified
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("""
<style>
/* Center title */
.title-center {
text-align: center;
font-size: 1.8em;
font-weight: bold;
margin-bottom: 20px;
}
/* Center all buttons */
div.stButton > button {
font-weight: bold;
width: 80%;
border-radius: 8px;
padding: 10px 0;
font-size: 1.1em;
display: block;
margin: 0 auto;
}
/* Center download button */
div.stDownloadButton > button {
font-weight: bold;
width: 80%;
border-radius: 8px;
padding: 10px 0;
font-size: 1.1em;
display: block;
margin: 0 auto;
}
/* Bigger + and - buttons in number input */
div[data-baseweb="input"] button {
width: 40px !important;
height: 40px !important;
font-size: 1.2em !important;
}
</style>
""", unsafe_allow_html=True)
# Title
st.markdown('<p class="title-center">🎬 Video Speed Tool</p>', 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)