Spaces:
Sleeping
Sleeping
Update streamlit_app.py
Browse files- streamlit_app.py +77 -18
streamlit_app.py
CHANGED
|
@@ -274,26 +274,85 @@ if st.sidebar.button("Load Video"):
|
|
| 274 |
st.session_state["last_error"] = f"Download failed: {e}"
|
| 275 |
st.sidebar.error(st.session_state["last_error"])
|
| 276 |
|
| 277 |
-
|
| 278 |
-
|
| 279 |
-
|
| 280 |
-
|
| 281 |
-
|
| 282 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 283 |
|
| 284 |
-
|
| 285 |
-
|
| 286 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 287 |
else:
|
| 288 |
-
|
| 289 |
-
|
| 290 |
-
|
| 291 |
-
st.session_state["videos"] = path
|
| 292 |
-
st.session_state["last_error"] = ""
|
| 293 |
-
st.sidebar.success("Video extracted from tweet and loaded.")
|
| 294 |
-
except Exception as e:
|
| 295 |
-
st.session_state["last_error"] = f"Tweet extraction failed: {e}"
|
| 296 |
-
st.sidebar.error(st.session_state["last_error"])
|
| 297 |
|
| 298 |
if st.session_state["videos"]:
|
| 299 |
try:
|
|
|
|
| 274 |
st.session_state["last_error"] = f"Download failed: {e}"
|
| 275 |
st.sidebar.error(st.session_state["last_error"])
|
| 276 |
|
| 277 |
+
# --------------------------------------------------------------
|
| 278 |
+
# 📥 Twitter video extractor – hidden inside an expander
|
| 279 |
+
# --------------------------------------------------------------
|
| 280 |
+
with st.sidebar.expander("🔎 Extract video(s) from a Tweet", expanded=False):
|
| 281 |
+
tweet_url = st.text_input(
|
| 282 |
+
"Tweet URL (e.g. https://twitter.com/user/status/1234567890)",
|
| 283 |
+
key="tweet_url",
|
| 284 |
+
)
|
| 285 |
+
|
| 286 |
+
# ------------------------------------------------------------------
|
| 287 |
+
# Step 1 – Scrape the tweet and collect every video URL
|
| 288 |
+
# ------------------------------------------------------------------
|
| 289 |
+
if st.button("Find videos in tweet"):
|
| 290 |
+
if not tweet_url:
|
| 291 |
+
st.error("Paste a tweet URL first.")
|
| 292 |
+
else:
|
| 293 |
+
try:
|
| 294 |
+
tweet_id = tweet_url.split("/")[-1].split("?")[0]
|
| 295 |
+
video_urls: list[str] = []
|
| 296 |
+
|
| 297 |
+
for tweet in sntwitter.TwitterTweetScraper(tweet_id).get_items():
|
| 298 |
+
# media objects (video, gif, etc.)
|
| 299 |
+
if getattr(tweet, "media", None):
|
| 300 |
+
for m in tweet.media:
|
| 301 |
+
if getattr(m, "video_url", None):
|
| 302 |
+
video_urls.append(m.video_url)
|
| 303 |
+
|
| 304 |
+
# expanded URLs that already end with a video extension
|
| 305 |
+
for u in getattr(tweet, "urls", []):
|
| 306 |
+
if u.expandedUrl.lower().endswith(
|
| 307 |
+
(".mp4", ".mov", ".webm", ".mkv", ".avi", ".flv")
|
| 308 |
+
):
|
| 309 |
+
video_urls.append(u.expandedUrl)
|
| 310 |
+
|
| 311 |
+
# deduplicate while preserving order
|
| 312 |
+
video_urls = list(dict.fromkeys(video_urls))
|
| 313 |
+
|
| 314 |
+
if not video_urls:
|
| 315 |
+
raise RuntimeError("No video URLs detected in this tweet.")
|
| 316 |
+
|
| 317 |
+
# store a friendly label + raw URL for the selector
|
| 318 |
+
st.session_state["tweet_video_options"] = [
|
| 319 |
+
(f"Video {i+1} – {url.split('/')[-1][:30]}...", url)
|
| 320 |
+
for i, url in enumerate(video_urls)
|
| 321 |
+
]
|
| 322 |
+
st.success(f"Found {len(video_urls)} video(s). Choose one below.")
|
| 323 |
+
except Exception as e:
|
| 324 |
+
st.session_state["tweet_video_options"] = []
|
| 325 |
+
st.error(f"Tweet scrape failed: {e}")
|
| 326 |
+
|
| 327 |
+
# ------------------------------------------------------------------
|
| 328 |
+
# Step 2 – Let the user pick one of the discovered videos
|
| 329 |
+
# ------------------------------------------------------------------
|
| 330 |
+
if st.session_state.get("tweet_video_options"):
|
| 331 |
+
display_names, raw_urls = zip(*st.session_state["tweet_video_options"])
|
| 332 |
+
sel_idx = st.selectbox(
|
| 333 |
+
"Select video to download",
|
| 334 |
+
options=range(len(display_names)),
|
| 335 |
+
format_func=lambda i: display_names[i],
|
| 336 |
+
key="tweet_video_select",
|
| 337 |
+
)
|
| 338 |
|
| 339 |
+
# ------------------------------------------------------------------
|
| 340 |
+
# Step 3 – Download the chosen video
|
| 341 |
+
# ------------------------------------------------------------------
|
| 342 |
+
if st.button("Download selected video"):
|
| 343 |
+
chosen_url = raw_urls[sel_idx]
|
| 344 |
+
try:
|
| 345 |
+
path = download_video(chosen_url, str(DATA_DIR))
|
| 346 |
+
st.session_state["videos"] = path
|
| 347 |
+
st.session_state["last_error"] = ""
|
| 348 |
+
st.success("Video downloaded and loaded.")
|
| 349 |
+
except Exception as e:
|
| 350 |
+
st.session_state["last_error"] = f"Download failed: {e}"
|
| 351 |
+
st.error(st.session_state["last_error"])
|
| 352 |
else:
|
| 353 |
+
st.info(
|
| 354 |
+
"Paste a tweet URL and click **Find videos in tweet** to discover available videos."
|
| 355 |
+
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 356 |
|
| 357 |
if st.session_state["videos"]:
|
| 358 |
try:
|