nnilayy commited on
Commit
bd09639
·
1 Parent(s): a17935c

Add po-token logic

Browse files
Files changed (3) hide show
  1. Dockerfile +15 -5
  2. app.py +70 -11
  3. tokens.json +1 -0
Dockerfile CHANGED
@@ -1,7 +1,17 @@
1
- # Use Python 3.10 base image
2
  FROM python:3.10-slim
3
 
4
- # Create a non-root user for security
 
 
 
 
 
 
 
 
 
 
5
  RUN useradd -m -u 1000 user
6
  USER user
7
  ENV PATH="/home/user/.local/bin:${PATH}"
@@ -9,15 +19,15 @@ ENV PATH="/home/user/.local/bin:${PATH}"
9
  # Set working directory
10
  WORKDIR /app
11
 
12
- # Install Python dependencies first for layer caching
13
  COPY --chown=user requirements.txt .
14
  RUN pip install --no-cache-dir --upgrade -r requirements.txt
15
 
16
  # Copy application code
17
  COPY --chown=user . .
18
 
19
- # Expose Gradio's default port
20
  EXPOSE 7860
21
 
22
- # Launch the application with Spaces-compatible settings
23
  CMD ["python", "app.py"]
 
1
+ # Use Python 3.10 slim base image
2
  FROM python:3.10-slim
3
 
4
+ # Install system dependencies
5
+ RUN apt-get update && apt-get install -y \
6
+ curl \
7
+ gnupg \
8
+ && rm -rf /var/lib/apt/lists/*
9
+
10
+ # Install Node.js for initial PoToken generation
11
+ RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - \
12
+ && apt-get install -y nodejs
13
+
14
+ # Create non-root user
15
  RUN useradd -m -u 1000 user
16
  USER user
17
  ENV PATH="/home/user/.local/bin:${PATH}"
 
19
  # Set working directory
20
  WORKDIR /app
21
 
22
+ # Copy requirements first for better caching
23
  COPY --chown=user requirements.txt .
24
  RUN pip install --no-cache-dir --upgrade -r requirements.txt
25
 
26
  # Copy application code
27
  COPY --chown=user . .
28
 
29
+ # Expose Gradio port
30
  EXPOSE 7860
31
 
32
+ # Start application
33
  CMD ["python", "app.py"]
app.py CHANGED
@@ -2,35 +2,86 @@ import gradio as gr
2
  from pytubefix import YouTube
3
  import tempfile
4
  import base64
 
 
 
5
  from io import BytesIO
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  def download_audio(url):
 
8
  try:
9
- # Initialize YouTube object
10
- yt = YouTube(url, 'WEB')
11
- title = yt.title
 
 
 
 
 
12
 
13
- # Get best audio stream
14
  audio_stream = yt.streams.filter(only_audio=True).order_by('abr').desc().first()
 
15
  if not audio_stream:
16
  return ["Error: No audio stream found", None, None]
17
 
18
- # Download to in-memory buffer
19
  buffer = BytesIO()
20
  audio_stream.stream_to_buffer(buffer)
21
  buffer.seek(0)
22
-
23
- # Create temporary file
24
  with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as tmp_file:
25
  tmp_file.write(buffer.read())
26
  tmp_path = tmp_file.name
27
 
28
- # Create HTML audio player with base64 encoding
29
  with open(tmp_path, "rb") as f:
30
  audio_bytes = f.read()
 
31
  audio_base64 = base64.b64encode(audio_bytes).decode("utf-8")
32
  audio_html = f"""
33
- <audio controls autoplay style="width: 100%">
34
  <source src="data:audio/mp3;base64,{audio_base64}" type="audio/mp3">
35
  Your browser does not support the audio element.
36
  </audio>
@@ -41,10 +92,18 @@ def download_audio(url):
41
  tmp_path,
42
  audio_html
43
  ]
44
-
45
  except Exception as e:
 
 
 
 
 
 
 
46
  return [f"Error: {str(e)}", None, None]
47
 
 
48
  with gr.Blocks(title="YouTube Audio Downloader") as demo:
49
  gr.Markdown("# YouTube Audio Downloader")
50
 
@@ -78,5 +137,5 @@ if __name__ == "__main__":
78
  server_name="0.0.0.0",
79
  server_port=7860,
80
  show_error=True,
81
- allowed_paths=["*"]
82
  )
 
2
  from pytubefix import YouTube
3
  import tempfile
4
  import base64
5
+ import os
6
+ import json
7
+ import logging
8
  from io import BytesIO
9
 
10
+ # Configure logging
11
+ logging.basicConfig(level=logging.INFO)
12
+ logger = logging.getLogger(__name__)
13
+
14
+ TOKEN_FILE = "tokens.json"
15
+
16
+ def get_or_create_tokens():
17
+ """Get cached tokens or create new ones with Node.js"""
18
+ try:
19
+ if os.path.exists(TOKEN_FILE):
20
+ with open(TOKEN_FILE) as f:
21
+ return json.load(f)
22
+
23
+ # Generate new tokens using dummy request
24
+ logger.info("Generating new YouTube tokens...")
25
+ yt = YouTube("https://www.youtube.com/watch?v=dQw4w9WgXcQ", 'WEB')
26
+ tokens = {
27
+ "po_token": yt.pot,
28
+ "visitor_data": yt._visitor_data
29
+ }
30
+ with open(TOKEN_FILE, 'w') as f:
31
+ json.dump(tokens, f)
32
+ return tokens
33
+ except Exception as e:
34
+ logger.error(f"Token generation failed: {str(e)}")
35
+ raise
36
+
37
+ def refresh_tokens():
38
+ """Force refresh tokens by deleting existing file"""
39
+ try:
40
+ if os.path.exists(TOKEN_FILE):
41
+ os.remove(TOKEN_FILE)
42
+ return get_or_create_tokens()
43
+ except Exception as e:
44
+ logger.error(f"Token refresh failed: {str(e)}")
45
+ raise
46
+
47
+ # Load initial tokens
48
+ tokens = get_or_create_tokens()
49
+
50
  def download_audio(url):
51
+ global tokens
52
  try:
53
+ # Try with current tokens
54
+ yt = YouTube(
55
+ url,
56
+ use_po_token=True,
57
+ po_token=tokens["po_token"],
58
+ visitor_data=tokens["visitor_data"],
59
+ allow_oauth_cache=True
60
+ )
61
 
62
+ title = yt.title
63
  audio_stream = yt.streams.filter(only_audio=True).order_by('abr').desc().first()
64
+
65
  if not audio_stream:
66
  return ["Error: No audio stream found", None, None]
67
 
68
+ # Download to memory
69
  buffer = BytesIO()
70
  audio_stream.stream_to_buffer(buffer)
71
  buffer.seek(0)
72
+
73
+ # Create temp file
74
  with tempfile.NamedTemporaryFile(suffix=".mp3", delete=False) as tmp_file:
75
  tmp_file.write(buffer.read())
76
  tmp_path = tmp_file.name
77
 
78
+ # Create HTML player
79
  with open(tmp_path, "rb") as f:
80
  audio_bytes = f.read()
81
+
82
  audio_base64 = base64.b64encode(audio_bytes).decode("utf-8")
83
  audio_html = f"""
84
+ <audio controls style="width: 100%">
85
  <source src="data:audio/mp3;base64,{audio_base64}" type="audio/mp3">
86
  Your browser does not support the audio element.
87
  </audio>
 
92
  tmp_path,
93
  audio_html
94
  ]
95
+
96
  except Exception as e:
97
+ if "bot" in str(e).lower():
98
+ logger.warning("Bot detected - refreshing tokens...")
99
+ try:
100
+ tokens = refresh_tokens()
101
+ return download_audio(url) # Retry with new tokens
102
+ except Exception as retry_error:
103
+ return [f"Error: Failed after token refresh - {str(retry_error)}", None, None]
104
  return [f"Error: {str(e)}", None, None]
105
 
106
+ # Gradio interface
107
  with gr.Blocks(title="YouTube Audio Downloader") as demo:
108
  gr.Markdown("# YouTube Audio Downloader")
109
 
 
137
  server_name="0.0.0.0",
138
  server_port=7860,
139
  show_error=True,
140
+ allowed_paths=["/"]
141
  )
tokens.json ADDED
@@ -0,0 +1 @@
 
 
1
+ {"po_token": "MngL5Ew7WfF2bAvY5UI1JXOsEEAgc9Q1A582budFuOgRPOrmvAHa5B8jTFFrOscLs_kEw7Q_TOtWdfwFBFmtUX3jSJZvDPd6aqSKJ6FYVG1zt7izKy0Og3wtvfS8WKvifZT1bcKu8GDNEHyB69klgkYzo0FvdhWFp0o=", "visitor_data": "CgtGaTQ1bWhySkVQayilwMG8BjIKCgJJThIEGgAgYA%3D%3D"}