Spaces:
Sleeping
Sleeping
Add Chrome cookies.txt upload and yt_dlp refactor
Browse filesEnable uploading Chrome cookies.txt in the Gradio UI for improved YouTube access. Refactor yt_audio_get_tracks.py to always use yt_dlp, preferring cookies.txt if available and falling back to browser cookies. Remove Piped API fallback and update progress handling.
- app.py +17 -1
- modules/cookies.txt +4 -3
- modules/yt_audio_get_tracks.py +30 -75
app.py
CHANGED
|
@@ -182,6 +182,7 @@ def process_video(video_id: str, progress=gr.Progress(track_tqdm=True)) -> str:
|
|
| 182 |
def process_video_with_progress(
|
| 183 |
video_id: str,
|
| 184 |
uploaded_audio: str | None,
|
|
|
|
| 185 |
progress=gr.Progress(track_tqdm=True),
|
| 186 |
):
|
| 187 |
status_lines = []
|
|
@@ -190,6 +191,8 @@ def process_video_with_progress(
|
|
| 190 |
status_lines.append(message)
|
| 191 |
|
| 192 |
try:
|
|
|
|
|
|
|
| 193 |
if uploaded_audio:
|
| 194 |
progress(0.05, desc="Preparing uploaded audio")
|
| 195 |
yield "", "Preparing uploaded audio..."
|
|
@@ -252,6 +255,19 @@ with gr.Blocks(title="SeparateTracks") as demo:
|
|
| 252 |
scale=4,
|
| 253 |
)
|
| 254 |
run_btn = gr.Button("Separate Tracks", variant="primary", scale=1)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 255 |
|
| 256 |
upload_input = gr.File(
|
| 257 |
label="Audio File Override (.wav or .mp3)",
|
|
@@ -265,7 +281,7 @@ with gr.Blocks(title="SeparateTracks") as demo:
|
|
| 265 |
|
| 266 |
run_btn.click(
|
| 267 |
fn=process_video_with_progress,
|
| 268 |
-
inputs=[video_id_input, upload_input],
|
| 269 |
outputs=[audio_output, progress_output],
|
| 270 |
)
|
| 271 |
|
|
|
|
| 182 |
def process_video_with_progress(
|
| 183 |
video_id: str,
|
| 184 |
uploaded_audio: str | None,
|
| 185 |
+
cookies_upload: str | None,
|
| 186 |
progress=gr.Progress(track_tqdm=True),
|
| 187 |
):
|
| 188 |
status_lines = []
|
|
|
|
| 191 |
status_lines.append(message)
|
| 192 |
|
| 193 |
try:
|
| 194 |
+
if cookies_upload is not None:
|
| 195 |
+
shutil.copy(cookies_upload, "modules/cookies.txt")
|
| 196 |
if uploaded_audio:
|
| 197 |
progress(0.05, desc="Preparing uploaded audio")
|
| 198 |
yield "", "Preparing uploaded audio..."
|
|
|
|
| 255 |
scale=4,
|
| 256 |
)
|
| 257 |
run_btn = gr.Button("Separate Tracks", variant="primary", scale=1)
|
| 258 |
+
with gr.Row():
|
| 259 |
+
cookies_upload = gr.File(
|
| 260 |
+
label="Upload Chrome cookies.txt (Netscape format)",
|
| 261 |
+
file_types=[".txt"],
|
| 262 |
+
type="filepath",
|
| 263 |
+
)
|
| 264 |
+
gr.Markdown("""
|
| 265 |
+
**How to get cookies.txt:**
|
| 266 |
+
1. Install [Get cookies.txt LOCALLY](https://chromewebstore.google.com/detail/get-cookiestxt-locally/cclelndahbckbenkjhflpdbgdldlbecc)
|
| 267 |
+
2. Log into YouTube in Chrome
|
| 268 |
+
3. Click extension → Export cookies
|
| 269 |
+
4. Upload the file here
|
| 270 |
+
""")
|
| 271 |
|
| 272 |
upload_input = gr.File(
|
| 273 |
label="Audio File Override (.wav or .mp3)",
|
|
|
|
| 281 |
|
| 282 |
run_btn.click(
|
| 283 |
fn=process_video_with_progress,
|
| 284 |
+
inputs=[video_id_input, upload_input, cookies_upload],
|
| 285 |
outputs=[audio_output, progress_output],
|
| 286 |
)
|
| 287 |
|
modules/cookies.txt
CHANGED
|
@@ -7,9 +7,10 @@
|
|
| 7 |
.youtube.com TRUE / TRUE 1809665126 __Secure-1PSIDTS sidts-CjQBhkeRd2zWGbcDaL6SNNxU-DnNCLJWYODQ2KzKAcsoR_FM29OpDU_NudXF0BGvxu3-4ilCEAA
|
| 8 |
.youtube.com TRUE / TRUE 1809665126 __Secure-3PSIDTS sidts-CjQBhkeRd2zWGbcDaL6SNNxU-DnNCLJWYODQ2KzKAcsoR_FM29OpDU_NudXF0BGvxu3-4ilCEAA
|
| 9 |
.youtube.com TRUE / TRUE 1809665900 __Secure-3PSIDCC AKEyXzWiyEqsbs6vWksfuhqkVix8gfb29gWxUBcn-A_zxFpN_jSGtqbMuekeAysH5txR5v_tqg
|
| 10 |
-
.youtube.com TRUE / TRUE
|
| 11 |
-
.youtube.com TRUE / TRUE
|
| 12 |
.youtube.com TRUE / TRUE 1793681123 __Secure-ROLLOUT_TOKEN CObY3I_n2pG-tQEQ1bTnseyZkwMYx9-alq-mlAM%3D
|
| 13 |
.youtube.com TRUE / TRUE 1793681123 __Secure-YNID 18.YT=Tx0A40MPkqhXx1ssHRZzuknGzSYMu4HquWBxKZVhu_0va9vVL6-pj-hgIxnNj494GkolBTXqTIRUTUC6fOJCobVAekeq8te87cIsbGIO2g_jPtJnm9zE0kpjWOKceLvXzON4m1GZqXSjj5c-IjmVR2V8_43Iqnn5sEdQDd9cDor11A7gsHRNqJVIsOMuKB2n1Np9oHkp3xMIZWg38MUB13NSur0Rr3SgGIvHZBEZ1z_MTrqCYndzX5CPDbSdhT1QfUR6lC85Y1o29OlpOE3hsSUq8xROpXOX016gCc8PsSbpu54DQOw2FHydbuW4FcWEtODp1vJ3ob5QbdAN6oYeeQ
|
| 14 |
.youtube.com TRUE / TRUE 0 SOCS CAI
|
| 15 |
-
.youtube.com TRUE / TRUE
|
|
|
|
|
|
| 7 |
.youtube.com TRUE / TRUE 1809665126 __Secure-1PSIDTS sidts-CjQBhkeRd2zWGbcDaL6SNNxU-DnNCLJWYODQ2KzKAcsoR_FM29OpDU_NudXF0BGvxu3-4ilCEAA
|
| 8 |
.youtube.com TRUE / TRUE 1809665126 __Secure-3PSIDTS sidts-CjQBhkeRd2zWGbcDaL6SNNxU-DnNCLJWYODQ2KzKAcsoR_FM29OpDU_NudXF0BGvxu3-4ilCEAA
|
| 9 |
.youtube.com TRUE / TRUE 1809665900 __Secure-3PSIDCC AKEyXzWiyEqsbs6vWksfuhqkVix8gfb29gWxUBcn-A_zxFpN_jSGtqbMuekeAysH5txR5v_tqg
|
| 10 |
+
.youtube.com TRUE / TRUE 1793688861 VISITOR_INFO1_LIVE 0HOxtcrbVL8
|
| 11 |
+
.youtube.com TRUE / TRUE 1793688861 VISITOR_PRIVACY_METADATA CgJVUxIEGgAgaw%3D%3D
|
| 12 |
.youtube.com TRUE / TRUE 1793681123 __Secure-ROLLOUT_TOKEN CObY3I_n2pG-tQEQ1bTnseyZkwMYx9-alq-mlAM%3D
|
| 13 |
.youtube.com TRUE / TRUE 1793681123 __Secure-YNID 18.YT=Tx0A40MPkqhXx1ssHRZzuknGzSYMu4HquWBxKZVhu_0va9vVL6-pj-hgIxnNj494GkolBTXqTIRUTUC6fOJCobVAekeq8te87cIsbGIO2g_jPtJnm9zE0kpjWOKceLvXzON4m1GZqXSjj5c-IjmVR2V8_43Iqnn5sEdQDd9cDor11A7gsHRNqJVIsOMuKB2n1Np9oHkp3xMIZWg38MUB13NSur0Rr3SgGIvHZBEZ1z_MTrqCYndzX5CPDbSdhT1QfUR6lC85Y1o29OlpOE3hsSUq8xROpXOX016gCc8PsSbpu54DQOw2FHydbuW4FcWEtODp1vJ3ob5QbdAN6oYeeQ
|
| 14 |
.youtube.com TRUE / TRUE 0 SOCS CAI
|
| 15 |
+
.youtube.com TRUE / TRUE 1778138661 GPS 1
|
| 16 |
+
.youtube.com TRUE / TRUE 0 YSC nu8y7GrJi5c
|
modules/yt_audio_get_tracks.py
CHANGED
|
@@ -13,86 +13,41 @@ def _emit_progress(progress_callback, message):
|
|
| 13 |
cookie_path = os.path.join(os.path.dirname(__file__), 'cookies.txt')
|
| 14 |
|
| 15 |
def download_audio(url, video_id, progress_callback=None):
|
| 16 |
-
try:
|
| 17 |
-
temp_dir = 'separated'
|
| 18 |
-
os.makedirs(temp_dir, exist_ok=True)
|
| 19 |
-
_emit_progress(progress_callback, 'Downloading audio from YouTube...')
|
| 20 |
-
compat_opts = ['no-youtube-unavailable-videoplayback']
|
| 21 |
-
|
| 22 |
-
is_hf = bool(os.getenv("SPACE_ID") or os.getenv("HF_SPACE") or os.path.exists("/.dockerenv"))
|
| 23 |
-
|
| 24 |
-
ydl_opts = {
|
| 25 |
-
'format': 'bestaudio/best',
|
| 26 |
-
'outtmpl': os.path.join(temp_dir, f'{video_id}.%(ext)s'),
|
| 27 |
-
'postprocessors': [{'key': 'FFmpegExtractAudio', 'preferredcodec': 'wav'}],
|
| 28 |
-
'keepvideo': True,
|
| 29 |
-
'quiet': False,
|
| 30 |
-
'no_warnings': False,
|
| 31 |
-
'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
| 32 |
-
'http_headers': {'Referer': 'https://www.youtube.com/'},
|
| 33 |
-
'socket_timeout': 30,
|
| 34 |
-
'retry_sleep': [1, 2, 5, 10],
|
| 35 |
-
'max_retries': 3,
|
| 36 |
-
'compat_opts': compat_opts,
|
| 37 |
-
}
|
| 38 |
-
|
| 39 |
-
if is_hf or os.path.exists(cookie_path):
|
| 40 |
-
ydl_opts['cookiefile'] = cookie_path
|
| 41 |
-
ydl_opts['nocheckcertificate'] = True
|
| 42 |
-
else:
|
| 43 |
-
ydl_opts['cookiesfrombrowser'] = ('chrome', None, None, None)
|
| 44 |
-
|
| 45 |
-
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
| 46 |
-
ydl.download([url])
|
| 47 |
-
_emit_progress(progress_callback, 'Converting downloaded audio to WAV...')
|
| 48 |
-
return os.path.join(temp_dir, f'{video_id}.wav')
|
| 49 |
-
except Exception:
|
| 50 |
-
return download_audio_piped(url, video_id, progress_callback)
|
| 51 |
-
|
| 52 |
-
def download_audio_piped(url, video_id, progress_callback=None):
|
| 53 |
temp_dir = 'separated'
|
| 54 |
os.makedirs(temp_dir, exist_ok=True)
|
| 55 |
_emit_progress(progress_callback, 'Downloading audio from YouTube...')
|
| 56 |
-
|
| 57 |
-
#
|
| 58 |
-
|
| 59 |
-
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
| 65 |
-
|
| 66 |
-
|
| 67 |
-
|
| 68 |
-
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 73 |
else:
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
# Best audio
|
| 77 |
-
audio_streams = [s for s in data.get("audioStreams", []) if not s.get("videoOnly")]
|
| 78 |
-
if not audio_streams:
|
| 79 |
-
raise Exception("No audio stream")
|
| 80 |
-
best = max(audio_streams, key=lambda x: int(x.get("bitrate", 0)))
|
| 81 |
-
|
| 82 |
-
# Download
|
| 83 |
-
m4a_path = os.path.join(temp_dir, f'{video_id}.m4a')
|
| 84 |
-
with requests.get(best["url"], stream=True, timeout=60) as r:
|
| 85 |
-
r.raise_for_status()
|
| 86 |
-
with open(m4a_path, 'wb') as f:
|
| 87 |
-
for chunk in r.iter_content(8192):
|
| 88 |
-
f.write(chunk)
|
| 89 |
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL, check=True)
|
| 95 |
-
return wav_path
|
| 96 |
|
| 97 |
def separate_tracks(input_wav, video_id, progress_callback=None):
|
| 98 |
if not os.path.exists(input_wav):
|
|
|
|
| 13 |
cookie_path = os.path.join(os.path.dirname(__file__), 'cookies.txt')
|
| 14 |
|
| 15 |
def download_audio(url, video_id, progress_callback=None):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 16 |
temp_dir = 'separated'
|
| 17 |
os.makedirs(temp_dir, exist_ok=True)
|
| 18 |
_emit_progress(progress_callback, 'Downloading audio from YouTube...')
|
| 19 |
+
compat_opts = ['no-youtube-unavailable-videoplayback']
|
| 20 |
+
# if shutil.which('deno') is None:
|
| 21 |
+
# print("⚠️ Deno not found.")
|
| 22 |
+
# compat_opts.append('no-youtube-js')
|
| 23 |
+
|
| 24 |
+
is_hf = bool(os.getenv("SPACE_ID") or os.getenv("HF_SPACE") or os.path.exists("/.dockerenv"))
|
| 25 |
+
|
| 26 |
+
ydl_opts = {
|
| 27 |
+
'format': 'bestaudio/best',
|
| 28 |
+
'outtmpl': os.path.join(temp_dir, f'{video_id}.%(ext)s'),
|
| 29 |
+
'postprocessors': [{'key': 'FFmpegExtractAudio', 'preferredcodec': 'wav'}],
|
| 30 |
+
'keepvideo': True,
|
| 31 |
+
'quiet': False,
|
| 32 |
+
'no_warnings': False,
|
| 33 |
+
'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
|
| 34 |
+
'http_headers': {'Referer': 'https://www.youtube.com/'},
|
| 35 |
+
'socket_timeout': 30,
|
| 36 |
+
'retry_sleep': [1, 2, 5, 10],
|
| 37 |
+
'max_retries': 3,
|
| 38 |
+
'compat_opts': compat_opts,
|
| 39 |
+
}
|
| 40 |
+
|
| 41 |
+
if is_hf or os.path.exists(cookie_path):
|
| 42 |
+
ydl_opts['cookiefile'] = cookie_path
|
| 43 |
+
ydl_opts['nocheckcertificate'] = True
|
| 44 |
else:
|
| 45 |
+
ydl_opts['cookiesfrombrowser'] = ('chrome', None, None, None)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
+
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
| 48 |
+
ydl.download([url])
|
| 49 |
+
_emit_progress(progress_callback, 'Converting downloaded audio to WAV...')
|
| 50 |
+
return os.path.join(temp_dir, f'{video_id}.wav')
|
|
|
|
|
|
|
| 51 |
|
| 52 |
def separate_tracks(input_wav, video_id, progress_callback=None):
|
| 53 |
if not os.path.exists(input_wav):
|