Spaces:
Sleeping
Sleeping
CI: deploy Docker/PDM Space
Browse files- Dockerfile +4 -1
- services/app_service/pages/signal_watch.py +117 -12
Dockerfile
CHANGED
|
@@ -29,6 +29,9 @@ ENV PIP_NO_CACHE_DIR=1 \
|
|
| 29 |
RUN mkdir -p /tmp/.streamlit /tmp/.cache /tmp/matplotlib /tmp/Ultralytics \
|
| 30 |
&& chmod -R 777 /tmp/.streamlit /tmp/.cache /tmp/matplotlib /tmp/Ultralytics
|
| 31 |
|
|
|
|
|
|
|
|
|
|
| 32 |
# Python deps (CUDA-enabled PyTorch wheels + all other dependencies)
|
| 33 |
RUN python -m pip install --upgrade pip setuptools wheel && \
|
| 34 |
pip install --no-cache-dir \
|
|
@@ -67,4 +70,4 @@ EXPOSE 7860
|
|
| 67 |
HEALTHCHECK CMD curl --fail http://localhost:${PORT}/_stcore/health || exit 1
|
| 68 |
|
| 69 |
# Use $PORT instead of hard-coding 8501
|
| 70 |
-
ENTRYPOINT ["sh", "-c", "streamlit run app.py --server.port=$PORT --server.address=0.0.0.0"]
|
|
|
|
| 29 |
RUN mkdir -p /tmp/.streamlit /tmp/.cache /tmp/matplotlib /tmp/Ultralytics \
|
| 30 |
&& chmod -R 777 /tmp/.streamlit /tmp/.cache /tmp/matplotlib /tmp/Ultralytics
|
| 31 |
|
| 32 |
+
# Create Streamlit config file to disable XSRF protection for Hugging Face Spaces
|
| 33 |
+
RUN echo "[server]\nenableXsrfProtection = false\n" > /tmp/.streamlit/config.toml
|
| 34 |
+
|
| 35 |
# Python deps (CUDA-enabled PyTorch wheels + all other dependencies)
|
| 36 |
RUN python -m pip install --upgrade pip setuptools wheel && \
|
| 37 |
pip install --no-cache-dir \
|
|
|
|
| 70 |
HEALTHCHECK CMD curl --fail http://localhost:${PORT}/_stcore/health || exit 1
|
| 71 |
|
| 72 |
# Use $PORT instead of hard-coding 8501
|
| 73 |
+
ENTRYPOINT ["sh", "-c", "streamlit run app.py --server.port=$PORT --server.address=0.0.0.0 --server.enableXsrfProtection=false"]
|
services/app_service/pages/signal_watch.py
CHANGED
|
@@ -89,6 +89,27 @@ with st.sidebar:
|
|
| 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(
|
|
@@ -292,6 +313,75 @@ def extract_youtube_stream_url(url: str, cookies_path: str | None = None) -> str
|
|
| 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:
|
|
@@ -330,21 +420,31 @@ def extract_youtube_stream_url(url: str, cookies_path: str | None = None) -> str
|
|
| 330 |
|
| 331 |
# Show helpful error message with instructions
|
| 332 |
st.error("""
|
| 333 |
-
**YouTube Authentication Required**
|
|
|
|
|
|
|
|
|
|
|
|
|
| 334 |
|
| 335 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 336 |
|
| 337 |
-
**
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
3. Export cookies to a file (usually cookies.txt)
|
| 341 |
-
4. Upload the cookies file using the file uploader below
|
| 342 |
|
| 343 |
-
**
|
| 344 |
-
|
|
|
|
| 345 |
|
| 346 |
-
**
|
| 347 |
-
|
|
|
|
|
|
|
|
|
|
| 348 |
""")
|
| 349 |
|
| 350 |
return None
|
|
@@ -370,12 +470,17 @@ def resolve_video_source(src_choice: str, cookies_path: str | None = None):
|
|
| 370 |
|
| 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:
|
| 378 |
-
st.error(f"Failed to
|
| 379 |
return None
|
| 380 |
|
| 381 |
# Check if it's a local video file
|
|
|
|
| 89 |
# Render device information
|
| 90 |
model_manager.render_device_info()
|
| 91 |
|
| 92 |
+
st.sidebar.markdown("---")
|
| 93 |
+
st.sidebar.header("YouTube Live Streams")
|
| 94 |
+
|
| 95 |
+
# Show helpful info about live streams
|
| 96 |
+
with st.sidebar.expander("βΉοΈ About Live Streams", expanded=False):
|
| 97 |
+
st.markdown("""
|
| 98 |
+
**Live streams may require authentication:**
|
| 99 |
+
|
| 100 |
+
π **Authentication Methods:**
|
| 101 |
+
- Upload cookies.txt file (recommended)
|
| 102 |
+
- Browser cookies (Chrome/Firefox/Safari/Edge)
|
| 103 |
+
|
| 104 |
+
πΊ **Available Live Streams:**
|
| 105 |
+
- Time Square Live Stream
|
| 106 |
+
- Dublin Live Stream
|
| 107 |
+
- Tokyo Live Stream
|
| 108 |
+
- Abbey Road Live Stream
|
| 109 |
+
|
| 110 |
+
β οΈ **Note:** Live streams have stricter access controls than regular videos.
|
| 111 |
+
""")
|
| 112 |
+
|
| 113 |
st.sidebar.markdown("---")
|
| 114 |
st.sidebar.header("YouTube cookies (optional)")
|
| 115 |
cookies_file = st.file_uploader(
|
|
|
|
| 313 |
f"Failed to use {browser} cookies: {result.stderr[:100]}..."
|
| 314 |
)
|
| 315 |
|
| 316 |
+
# Try with additional yt-dlp options for better compatibility
|
| 317 |
+
st.info("Trying with enhanced compatibility options...")
|
| 318 |
+
for fmt in format_options:
|
| 319 |
+
cmd = [
|
| 320 |
+
ytdlp_path,
|
| 321 |
+
"--get-url",
|
| 322 |
+
"--format",
|
| 323 |
+
fmt,
|
| 324 |
+
"--no-playlist",
|
| 325 |
+
"--no-warnings",
|
| 326 |
+
"--user-agent",
|
| 327 |
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
| 328 |
+
"--referer",
|
| 329 |
+
"https://www.youtube.com/",
|
| 330 |
+
"--add-header",
|
| 331 |
+
"Accept-Language:en-US,en;q=0.9",
|
| 332 |
+
"--add-header",
|
| 333 |
+
"Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
|
| 334 |
+
url,
|
| 335 |
+
]
|
| 336 |
+
|
| 337 |
+
result = subprocess.run(
|
| 338 |
+
cmd, check=False, capture_output=True, text=True, timeout=30
|
| 339 |
+
)
|
| 340 |
+
|
| 341 |
+
if result.returncode == 0:
|
| 342 |
+
stream_url = result.stdout.strip()
|
| 343 |
+
if stream_url and stream_url.startswith("http"):
|
| 344 |
+
st.success(
|
| 345 |
+
f"Successfully extracted YouTube stream URL with enhanced options! (format: {fmt})"
|
| 346 |
+
)
|
| 347 |
+
return stream_url
|
| 348 |
+
else:
|
| 349 |
+
st.warning(
|
| 350 |
+
f"Enhanced options failed with format {fmt}: {result.stderr[:100]}..."
|
| 351 |
+
)
|
| 352 |
+
|
| 353 |
+
# Try with live stream specific options
|
| 354 |
+
st.info("Trying with live stream specific options...")
|
| 355 |
+
for fmt in format_options:
|
| 356 |
+
cmd = [
|
| 357 |
+
ytdlp_path,
|
| 358 |
+
"--get-url",
|
| 359 |
+
"--format",
|
| 360 |
+
fmt,
|
| 361 |
+
"--no-playlist",
|
| 362 |
+
"--no-warnings",
|
| 363 |
+
"--live-from-start",
|
| 364 |
+
"--user-agent",
|
| 365 |
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
| 366 |
+
url,
|
| 367 |
+
]
|
| 368 |
+
|
| 369 |
+
result = subprocess.run(
|
| 370 |
+
cmd, check=False, capture_output=True, text=True, timeout=30
|
| 371 |
+
)
|
| 372 |
+
|
| 373 |
+
if result.returncode == 0:
|
| 374 |
+
stream_url = result.stdout.strip()
|
| 375 |
+
if stream_url and stream_url.startswith("http"):
|
| 376 |
+
st.success(
|
| 377 |
+
f"Successfully extracted YouTube live stream URL! (format: {fmt})"
|
| 378 |
+
)
|
| 379 |
+
return stream_url
|
| 380 |
+
else:
|
| 381 |
+
st.warning(
|
| 382 |
+
f"Live stream options failed with format {fmt}: {result.stderr[:100]}..."
|
| 383 |
+
)
|
| 384 |
+
|
| 385 |
# Try without cookies (might work for some videos)
|
| 386 |
st.info("Trying without authentication cookies...")
|
| 387 |
for fmt in format_options:
|
|
|
|
| 420 |
|
| 421 |
# Show helpful error message with instructions
|
| 422 |
st.error("""
|
| 423 |
+
**YouTube Live Stream Authentication Required**
|
| 424 |
+
|
| 425 |
+
YouTube is blocking access to this live stream. This is common for live content due to bot detection.
|
| 426 |
+
|
| 427 |
+
**π§ Solutions (try in order):**
|
| 428 |
|
| 429 |
+
**1. Upload YouTube Cookies (Recommended)**
|
| 430 |
+
- Install browser extension: "Get cookies.txt" or "cookies.txt"
|
| 431 |
+
- Go to YouTube.com and log in
|
| 432 |
+
- Export cookies to cookies.txt file
|
| 433 |
+
- Upload the file using the uploader above
|
| 434 |
|
| 435 |
+
**2. Browser Authentication**
|
| 436 |
+
- Make sure you're logged into YouTube in Chrome, Firefox, Safari, or Edge
|
| 437 |
+
- The app will try to use your browser cookies automatically
|
|
|
|
|
|
|
| 438 |
|
| 439 |
+
**3. Alternative Live Streams**
|
| 440 |
+
- Try different YouTube live streams (some are more accessible than others)
|
| 441 |
+
- Live streams may have different access restrictions
|
| 442 |
|
| 443 |
+
**4. Check Stream Status**
|
| 444 |
+
- Ensure the live stream is actually live and not ended
|
| 445 |
+
- Some streams may be region-restricted
|
| 446 |
+
|
| 447 |
+
**π‘ Pro Tip:** Live streams often require authentication more than regular videos.
|
| 448 |
""")
|
| 449 |
|
| 450 |
return None
|
|
|
|
| 470 |
|
| 471 |
if src_choice in youtube_urls:
|
| 472 |
youtube_url = youtube_urls[src_choice]
|
| 473 |
+
|
| 474 |
+
# Show live stream status
|
| 475 |
+
st.info(f"π₯ Processing live stream: {src_choice}")
|
| 476 |
+
|
| 477 |
# Extract the actual stream URL using yt-dlp
|
| 478 |
stream_url = extract_youtube_stream_url(youtube_url, cookies_path)
|
| 479 |
if stream_url:
|
| 480 |
+
st.success(f"β
Live stream ready: {src_choice}")
|
| 481 |
return stream_url
|
| 482 |
else:
|
| 483 |
+
st.error(f"β Failed to access live stream: {src_choice}")
|
| 484 |
return None
|
| 485 |
|
| 486 |
# Check if it's a local video file
|