yt-clipper-new / app.py
yasvanthkumar's picture
Update app.py
007006b verified
# app.py
import streamlit as st
import os, traceback
from clipper import (
process_uploaded_file,
process_youtube_link,
NetworkBlockedError,
)
st.set_page_config(page_title="Smart Clipper", layout="centered")
st.title("Smart Clipper β€” Upload MP4 (test) & optional YouTube link")
st.markdown(
"Upload MP4 to auto-create 40–60s vertical Shorts with zoom, auto-captions (Whisper if installed), "
"and a viral-likelihood score. After MP4 works, try the YouTube link if your environment allows downloads."
)
# Sidebar controls
st.sidebar.header("Clip settings")
min_clip = st.sidebar.number_input("Min clip length (s)", value=50, min_value=30, max_value=120, step=1)
max_clip = st.sidebar.number_input("Max clip length (s)", value=60, min_value=30, max_value=300, step=1)
if min_clip > max_clip:
min_clip, max_clip = max_clip, min_clip
num_max = st.sidebar.slider("Maximum candidate clips", 1, 6, 5)
st.sidebar.markdown("---")
st.sidebar.header("YouTube (optional)")
yt_enabled = st.sidebar.checkbox("Enable YouTube download (only use if environment allows)", value=False)
st.sidebar.caption("If network blocked (Spaces often block), use Upload MP4 instead.")
st.sidebar.markdown("---")
st.sidebar.header("Advanced")
use_whisper = st.sidebar.checkbox("Use Whisper for captions (if installed)", value=False)
st.sidebar.caption("If Whisper not installed, app uses a lightweight fallback for captions.")
st.sidebar.markdown("---")
st.info("Tip: Start by uploading an MP4 (Upload MP4). If that works, try YouTube link if you know your env allows downloads.")
OUT_DIR = "outputs"
os.makedirs(OUT_DIR, exist_ok=True)
# --- Upload MP4 flow (recommended to test first)
st.header("1) Upload MP4 (recommended for testing)")
uploaded = st.file_uploader("Choose an MP4/MOV/MKV file", type=["mp4", "mov", "mkv"])
srt = st.file_uploader("Optional: Upload SRT (will be used as captions)", type=["srt"])
manual_caption = st.text_input("Optional: A short caption (will show on each clip if provided)")
if uploaded:
save_folder = "uploads"
os.makedirs(save_folder, exist_ok=True)
video_path = os.path.join(save_folder, uploaded.name)
with open(video_path, "wb") as f:
f.write(uploaded.getbuffer())
st.success(f"Saved upload to: {video_path}")
if st.button("Generate clips from uploaded video"):
status = st.empty()
try:
status.info("Processing β€” detecting highlights and generating clips. This can take a while.")
clips = process_uploaded_file(
video_path,
out_dir=OUT_DIR,
min_clip=min_clip,
max_clip=max_clip,
max_candidates=num_max,
srt_path=(srt.name if srt else None),
manual_caption=(manual_caption.strip() if manual_caption else None),
use_whisper=use_whisper,
)
if not clips:
status.warning("No clips generated. Try a different video or expand max candidates.")
else:
status.success(f"Generated {len(clips)} clips.")
for info in clips:
# info is dict: {'path','score','start','end','duration'}
st.subheader(os.path.basename(info["path"]))
try:
st.video(info["path"])
except:
st.write("Preview not available for this clip.")
st.write(f"Start: {info['start']}s End: {info['end']}s Duration: {info['duration']}s")
st.write(f"Viral-likelihood: **{info['score']}%**")
with open(info["path"], "rb") as fh:
st.download_button("Download clip", fh.read(), file_name=os.path.basename(info["path"]))
except NetworkBlockedError as ne:
status.error("Network blocked for downloads: " + str(ne))
st.info("Use Upload MP4 or run locally/VPS for YouTube downloads.")
except Exception as e:
status.error("Processing failed: " + repr(e))
st.code(traceback.format_exc(), language="python")
st.markdown("---")
# --- YouTube link flow (optional)
st.header("2) YouTube link (if your environment can download)")
yt_url = st.text_input("Paste full YouTube URL here")
proxy = st.text_input("Optional proxy for yt-dlp (e.g. socks5://user:pass@host:port)", value="")
if st.button("Download & Generate from YouTube") and yt_url:
status = st.empty()
try:
status.info("Attempting to download video; checking network...")
clips = process_youtube_link(
yt_url,
out_dir=OUT_DIR,
min_clip=min_clip,
max_clip=max_clip,
max_candidates=num_max,
ytdlp_opts={"proxy": proxy} if proxy else None,
use_whisper=use_whisper,
)
if not clips:
status.warning("No clips generated from YouTube.")
else:
status.success(f"Generated {len(clips)} clips from YouTube.")
for info in clips:
st.subheader(os.path.basename(info["path"]))
try:
st.video(info["path"])
except:
st.write("Preview not available.")
st.write(f"Start: {info['start']}s End: {info['end']}s Duration: {info['duration']}s")
st.write(f"Viral-likelihood: **{info['score']}%**")
with open(info["path"], "rb") as fh:
st.download_button("Download clip", fh.read(), file_name=os.path.basename(info["path"]))
except NetworkBlockedError as ne:
status.error("Network appears blocked for downloads: " + str(ne))
st.info("Use Upload MP4 option instead.")
except Exception as e:
status.error("Failed: " + repr(e))
st.code(traceback.format_exc(), language="python")
st.markdown("---")
st.caption("Viral-likelihood is a heuristic (audio/motion/face presence). It is not a guarantee β€” but it helps rank candidate clips.")