Surn commited on
Commit
329e3fb
·
1 Parent(s): 93b168d

Add Chrome cookies.txt upload and yt_dlp refactor

Browse files

Enable 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.

Files changed (3) hide show
  1. app.py +17 -1
  2. modules/cookies.txt +4 -3
  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 1793686088 VISITOR_INFO1_LIVE 0HOxtcrbVL8
11
- .youtube.com TRUE / TRUE 1793686088 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 1778135888 GPS 1
 
 
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
- # Try multiple Piped instances
58
- instances = [
59
- "https://pipedapi.tokhmi.xyz",
60
- "https://piped-api.lunar.icu",
61
- "https://pipedapi.moomoo.me",
62
- "https://pipedapi.leptons.xyz"
63
- ]
64
-
65
- for piped_api in instances:
66
- try:
67
- resp = requests.get(f"{piped_api}/streams/{video_id}", timeout=20)
68
- resp.raise_for_status()
69
- data = resp.json()
70
- break
71
- except Exception:
72
- continue
 
 
 
 
 
 
 
 
73
  else:
74
- raise Exception("All Piped instances failed")
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
- # Convert
91
- _emit_progress(progress_callback, 'Converting to WAV...')
92
- wav_path = os.path.join(temp_dir, f'{video_id}.wav')
93
- subprocess.run(['ffmpeg', '-y', '-i', m4a_path, '-acodec', 'pcm_s16le', '-ar', '44100', wav_path],
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):