lucid-hf commited on
Commit
9c3fc9f
·
verified ·
1 Parent(s): a65508e

CI: deploy Docker/PDM Space

Browse files
services/app_service/pages/signal_watch.py CHANGED
@@ -1,3 +1,4 @@
 
1
  import re
2
  import shutil
3
  import subprocess
@@ -88,6 +89,42 @@ with st.sidebar:
88
  # Render device information
89
  model_manager.render_device_info()
90
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
  def find_ytdlp_executable() -> str | None:
93
  """Find the yt-dlp executable, checking multiple possible locations."""
@@ -169,7 +206,7 @@ def is_live_youtube_stream(url: str) -> bool:
169
  return False
170
 
171
 
172
- def extract_youtube_stream_url(url: str) -> str | None:
173
  """Extract the actual stream URL from a YouTube URL using yt-dlp."""
174
  # Find yt-dlp executable
175
  ytdlp_path = find_ytdlp_executable()
@@ -186,9 +223,77 @@ def extract_youtube_stream_url(url: str) -> str | None:
186
  try:
187
  # Show progress message
188
  with st.spinner("Extracting YouTube stream URL..."):
189
- # Try multiple format options
190
  format_options = ["best[height<=720]", "best[height<=480]", "best", "worst"]
191
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
192
  for fmt in format_options:
193
  cmd = [
194
  ytdlp_path,
@@ -208,32 +313,12 @@ def extract_youtube_stream_url(url: str) -> str | None:
208
  stream_url = result.stdout.strip()
209
  if stream_url and stream_url.startswith("http"):
210
  st.success(
211
- f"Successfully extracted YouTube stream URL! (format: {fmt})"
212
  )
213
  return stream_url
214
- else:
215
- st.warning(
216
- f"Invalid stream URL extracted with format {fmt}: {stream_url}"
217
- )
218
  else:
219
  st.warning(f"yt-dlp failed with format {fmt}: {result.stderr}")
220
 
221
- # If all formats failed, try a different approach
222
- st.warning("Trying alternative extraction method...")
223
- cmd = [ytdlp_path, "--get-url", "--format", "best", "--no-playlist", url]
224
-
225
- result = subprocess.run(
226
- cmd, check=False, capture_output=True, text=True, timeout=30
227
- )
228
-
229
- if result.returncode == 0:
230
- stream_url = result.stdout.strip()
231
- if stream_url and stream_url.startswith("http"):
232
- st.success(
233
- "Successfully extracted YouTube stream URL with fallback method!"
234
- )
235
- return stream_url
236
-
237
  except subprocess.TimeoutExpired:
238
  st.error(
239
  "Timeout while extracting YouTube stream URL. The video might be unavailable."
@@ -243,6 +328,25 @@ def extract_youtube_stream_url(url: str) -> str | None:
243
  except Exception as e:
244
  st.error(f"Error extracting YouTube stream URL: {e!s}")
245
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
246
  return None
247
 
248
 
@@ -259,7 +363,7 @@ if "stop_processing" not in st.session_state:
259
  st.session_state.stop_processing = False
260
 
261
 
262
- def resolve_video_source(src_choice: str):
263
  """Resolve the video source, extracting YouTube stream URLs if needed."""
264
  if src_choice == "Webcam":
265
  return 0
@@ -267,7 +371,7 @@ def resolve_video_source(src_choice: str):
267
  if src_choice in youtube_urls:
268
  youtube_url = youtube_urls[src_choice]
269
  # Extract the actual stream URL using yt-dlp
270
- stream_url = extract_youtube_stream_url(youtube_url)
271
  if stream_url:
272
  return stream_url
273
  else:
@@ -441,7 +545,7 @@ def run_video_feed_detection(
441
 
442
 
443
  if run_detection:
444
- src = resolve_video_source(src_choice)
445
  if not src:
446
  st.warning("Please select a valid source (pick a file or enter a URL).")
447
  else:
 
1
+ import hashlib
2
  import re
3
  import shutil
4
  import subprocess
 
89
  # Render device information
90
  model_manager.render_device_info()
91
 
92
+ st.sidebar.markdown("---")
93
+ st.sidebar.header("YouTube cookies (optional)")
94
+ cookies_file = st.file_uploader(
95
+ "Upload YouTube cookies.txt (optional)",
96
+ type=["txt"],
97
+ key="yt_cookies_upload",
98
+ help=(
99
+ "**Required if YouTube blocks video access:**\n\n"
100
+ "1. Install browser extension: 'Get cookies.txt' or 'cookies.txt'\n"
101
+ "2. Go to YouTube.com and log in\n"
102
+ "3. Export cookies to cookies.txt file\n"
103
+ "4. Upload the file here\n\n"
104
+ "**Alternative:** Make sure you're logged into YouTube in Chrome/Firefox/Safari/Edge\n\n"
105
+ "⚠️ Keep cookies private; they contain your login session"
106
+ ),
107
+ )
108
+
109
+ if cookies_file is not None:
110
+ try:
111
+ cookie_bytes = cookies_file.getvalue()
112
+ if cookie_bytes:
113
+ cookie_hash = hashlib.sha256(cookie_bytes).hexdigest()[:16]
114
+ cookie_path_obj = (
115
+ Path(tempfile.gettempdir()) / f"yt_cookies_{cookie_hash}.txt"
116
+ )
117
+ cookie_path_obj.write_bytes(cookie_bytes)
118
+ cookies_path = str(cookie_path_obj)
119
+ else:
120
+ cookies_path = None
121
+ st.warning("Uploaded cookies file is empty; ignoring it.")
122
+ except Exception as exc:
123
+ cookies_path = None
124
+ st.error(f"Failed to cache uploaded cookies: {exc!s}")
125
+ else:
126
+ cookies_path = None
127
+
128
 
129
  def find_ytdlp_executable() -> str | None:
130
  """Find the yt-dlp executable, checking multiple possible locations."""
 
206
  return False
207
 
208
 
209
+ def extract_youtube_stream_url(url: str, cookies_path: str | None = None) -> str | None:
210
  """Extract the actual stream URL from a YouTube URL using yt-dlp."""
211
  # Find yt-dlp executable
212
  ytdlp_path = find_ytdlp_executable()
 
223
  try:
224
  # Show progress message
225
  with st.spinner("Extracting YouTube stream URL..."):
226
+ # Try multiple format options with different cookie strategies
227
  format_options = ["best[height<=720]", "best[height<=480]", "best", "worst"]
228
 
229
+ # First try with cookies if provided
230
+ if cookies_path and Path(cookies_path).exists():
231
+ st.info("Using provided cookies for YouTube authentication...")
232
+ for fmt in format_options:
233
+ cmd = [
234
+ ytdlp_path,
235
+ "--get-url",
236
+ "--format",
237
+ fmt,
238
+ "--no-playlist",
239
+ "--no-warnings",
240
+ "--cookies",
241
+ cookies_path,
242
+ url,
243
+ ]
244
+
245
+ result = subprocess.run(
246
+ cmd, check=False, capture_output=True, text=True, timeout=30
247
+ )
248
+
249
+ if result.returncode == 0:
250
+ stream_url = result.stdout.strip()
251
+ if stream_url and stream_url.startswith("http"):
252
+ st.success(
253
+ f"Successfully extracted YouTube stream URL! (format: {fmt})"
254
+ )
255
+ return stream_url
256
+ else:
257
+ st.warning(f"yt-dlp failed with format {fmt}: {result.stderr}")
258
+
259
+ # Try with browser cookies (Chrome, Firefox, Safari)
260
+ st.info("Trying to use browser cookies for YouTube authentication...")
261
+ browsers = ["chrome", "firefox", "safari", "edge"]
262
+
263
+ for browser in browsers:
264
+ for fmt in format_options:
265
+ cmd = [
266
+ ytdlp_path,
267
+ "--get-url",
268
+ "--format",
269
+ fmt,
270
+ "--no-playlist",
271
+ "--no-warnings",
272
+ "--cookies-from-browser",
273
+ browser,
274
+ url,
275
+ ]
276
+
277
+ result = subprocess.run(
278
+ cmd, check=False, capture_output=True, text=True, timeout=30
279
+ )
280
+
281
+ if result.returncode == 0:
282
+ stream_url = result.stdout.strip()
283
+ if stream_url and stream_url.startswith("http"):
284
+ st.success(
285
+ f"Successfully extracted YouTube stream URL using {browser} cookies! (format: {fmt})"
286
+ )
287
+ return stream_url
288
+ else:
289
+ # Only show warning for the first browser attempt
290
+ if fmt == format_options[0]:
291
+ st.warning(
292
+ f"Failed to use {browser} cookies: {result.stderr[:100]}..."
293
+ )
294
+
295
+ # Try without cookies (might work for some videos)
296
+ st.info("Trying without authentication cookies...")
297
  for fmt in format_options:
298
  cmd = [
299
  ytdlp_path,
 
313
  stream_url = result.stdout.strip()
314
  if stream_url and stream_url.startswith("http"):
315
  st.success(
316
+ f"Successfully extracted YouTube stream URL without cookies! (format: {fmt})"
317
  )
318
  return stream_url
 
 
 
 
319
  else:
320
  st.warning(f"yt-dlp failed with format {fmt}: {result.stderr}")
321
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
  except subprocess.TimeoutExpired:
323
  st.error(
324
  "Timeout while extracting YouTube stream URL. The video might be unavailable."
 
328
  except Exception as e:
329
  st.error(f"Error extracting YouTube stream URL: {e!s}")
330
 
331
+ # Show helpful error message with instructions
332
+ st.error("""
333
+ **YouTube Authentication Required**
334
+
335
+ YouTube is blocking the video download. To fix this, you need to provide authentication cookies:
336
+
337
+ **Option 1: Export cookies from your browser**
338
+ 1. Install a browser extension like "Get cookies.txt" or "cookies.txt"
339
+ 2. Go to YouTube.com and make sure you're logged in
340
+ 3. Export cookies to a file (usually cookies.txt)
341
+ 4. Upload the cookies file using the file uploader below
342
+
343
+ **Option 2: Use browser cookies directly**
344
+ Make sure you're logged into YouTube in Chrome, Firefox, Safari, or Edge
345
+
346
+ **Option 3: Try a different video**
347
+ Some YouTube videos are restricted and cannot be accessed programmatically
348
+ """)
349
+
350
  return None
351
 
352
 
 
363
  st.session_state.stop_processing = False
364
 
365
 
366
+ def resolve_video_source(src_choice: str, cookies_path: str | None = None):
367
  """Resolve the video source, extracting YouTube stream URLs if needed."""
368
  if src_choice == "Webcam":
369
  return 0
 
371
  if src_choice in youtube_urls:
372
  youtube_url = youtube_urls[src_choice]
373
  # Extract the actual stream URL using yt-dlp
374
+ stream_url = extract_youtube_stream_url(youtube_url, cookies_path)
375
  if stream_url:
376
  return stream_url
377
  else:
 
545
 
546
 
547
  if run_detection:
548
+ src = resolve_video_source(src_choice, cookies_path)
549
  if not src:
550
  st.warning("Please select a valid source (pick a file or enter a URL).")
551
  else: