Spaces:
Sleeping
Sleeping
Commit ·
baf044b
1
Parent(s): 416a974
feat: YouTube support via yt-proxy helper Space
Browse files- YouTube URLs detected by regex, routed to HeshamHaroon/yt-proxy Space
- Proxy runs on free CPU, downloads video, returns file via Gradio Client
- ZeroGPU Space connects via huggingface.co API (DNS accessible)
- Non-YouTube URLs still use direct yt-dlp download
- Updated UI labels to reflect YouTube support
- app.py +2 -2
- pipeline_runner.py +24 -1
app.py
CHANGED
|
@@ -283,11 +283,11 @@ with gr.Blocks(
|
|
| 283 |
gr.Markdown("### SOURCE")
|
| 284 |
source_url = gr.Textbox(
|
| 285 |
label="Video URL",
|
| 286 |
-
placeholder="
|
| 287 |
lines=1,
|
| 288 |
max_lines=2,
|
| 289 |
)
|
| 290 |
-
gr.Markdown("<center style='color:var(--text-secondary);font-size:0.85rem'>
|
| 291 |
source_upload = gr.File(
|
| 292 |
label="Upload video or audio",
|
| 293 |
file_types=["video", "audio"],
|
|
|
|
| 283 |
gr.Markdown("### SOURCE")
|
| 284 |
source_url = gr.Textbox(
|
| 285 |
label="Video URL",
|
| 286 |
+
placeholder="YouTube URL or direct video/audio link...",
|
| 287 |
lines=1,
|
| 288 |
max_lines=2,
|
| 289 |
)
|
| 290 |
+
gr.Markdown("<center style='color:var(--text-secondary);font-size:0.85rem'>YouTube links download via proxy — or upload directly</center>")
|
| 291 |
source_upload = gr.File(
|
| 292 |
label="Upload video or audio",
|
| 293 |
file_types=["video", "audio"],
|
pipeline_runner.py
CHANGED
|
@@ -14,11 +14,15 @@ import time
|
|
| 14 |
from typing import Any, Generator
|
| 15 |
|
| 16 |
import spaces # provided by HF ZeroGPU runtime
|
|
|
|
| 17 |
|
| 18 |
# ---------------------------------------------------------------------------
|
| 19 |
# Constants
|
| 20 |
# ---------------------------------------------------------------------------
|
| 21 |
|
|
|
|
|
|
|
|
|
|
| 22 |
HF_TOKEN: str = os.environ.get("HF_TOKEN", "")
|
| 23 |
LLM_BASE_URL: str = "https://router.huggingface.co/v1"
|
| 24 |
LLM_MODEL_TEXT: str = "Qwen/Qwen2.5-72B-Instruct"
|
|
@@ -68,6 +72,20 @@ def _make_client(model: str = LLM_MODEL_TEXT):
|
|
| 68 |
return build_client(api_key=HF_TOKEN, base_url=LLM_BASE_URL)
|
| 69 |
|
| 70 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
# ---------------------------------------------------------------------------
|
| 72 |
# Helper: call with exponential backoff on 429
|
| 73 |
# ---------------------------------------------------------------------------
|
|
@@ -285,7 +303,12 @@ def run_pipeline(
|
|
| 285 |
|
| 286 |
try:
|
| 287 |
if download.is_url(source):
|
| 288 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 289 |
download.extract_audio(proj.video, proj.audio)
|
| 290 |
elif download.is_audio_file(source):
|
| 291 |
download.ingest_local_audio(source, proj.audio)
|
|
|
|
| 14 |
from typing import Any, Generator
|
| 15 |
|
| 16 |
import spaces # provided by HF ZeroGPU runtime
|
| 17 |
+
import re
|
| 18 |
|
| 19 |
# ---------------------------------------------------------------------------
|
| 20 |
# Constants
|
| 21 |
# ---------------------------------------------------------------------------
|
| 22 |
|
| 23 |
+
YT_PROXY_SPACE = "HeshamHaroon/yt-proxy"
|
| 24 |
+
_YT_RE = re.compile(r'(?:youtube\.com/watch\?v=|youtu\.be/|youtube\.com/shorts/)([a-zA-Z0-9_-]{11})')
|
| 25 |
+
|
| 26 |
HF_TOKEN: str = os.environ.get("HF_TOKEN", "")
|
| 27 |
LLM_BASE_URL: str = "https://router.huggingface.co/v1"
|
| 28 |
LLM_MODEL_TEXT: str = "Qwen/Qwen2.5-72B-Instruct"
|
|
|
|
| 72 |
return build_client(api_key=HF_TOKEN, base_url=LLM_BASE_URL)
|
| 73 |
|
| 74 |
|
| 75 |
+
def _is_youtube_url(url: str) -> bool:
|
| 76 |
+
return bool(_YT_RE.search(url))
|
| 77 |
+
|
| 78 |
+
|
| 79 |
+
def _download_via_proxy(url: str, output_path: str) -> str:
|
| 80 |
+
"""Download a YouTube video via the yt-proxy helper Space."""
|
| 81 |
+
from gradio_client import Client
|
| 82 |
+
client = Client(YT_PROXY_SPACE, hf_token=HF_TOKEN)
|
| 83 |
+
result = client.predict(url=url, api_name="/download_video")
|
| 84 |
+
# result is a file path on the proxy; gradio_client downloads it locally
|
| 85 |
+
shutil.copy2(result, output_path)
|
| 86 |
+
return output_path
|
| 87 |
+
|
| 88 |
+
|
| 89 |
# ---------------------------------------------------------------------------
|
| 90 |
# Helper: call with exponential backoff on 429
|
| 91 |
# ---------------------------------------------------------------------------
|
|
|
|
| 303 |
|
| 304 |
try:
|
| 305 |
if download.is_url(source):
|
| 306 |
+
if _is_youtube_url(source):
|
| 307 |
+
# YouTube: use proxy Space (ZeroGPU blocks youtube.com DNS)
|
| 308 |
+
yield stage, f"[{STAGE_NAMES[stage - 1]}] Downloading via YouTube proxy...", {}
|
| 309 |
+
_download_via_proxy(source, proj.video)
|
| 310 |
+
else:
|
| 311 |
+
download.download_video(source, proj.video)
|
| 312 |
download.extract_audio(proj.video, proj.audio)
|
| 313 |
elif download.is_audio_file(source):
|
| 314 |
download.ingest_local_audio(source, proj.audio)
|