Pepguy commited on
Commit
a662741
Β·
verified Β·
1 Parent(s): fa37cef

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +18 -23
app.py CHANGED
@@ -8,9 +8,9 @@ import uuid
8
  import shutil
9
  import yt_dlp
10
  import socket
 
11
 
12
- # ── 1. SOCKET HACK: FORCE IPv4 ──
13
- # Prevents "[Errno -5] No address associated with hostname" on cloud hosts
14
  orig_getaddrinfo = socket.getaddrinfo
15
  def hooked_getaddrinfo(*args, **kwargs):
16
  res = orig_getaddrinfo(*args, **kwargs)
@@ -21,7 +21,7 @@ app = FastAPI()
21
 
22
  class VideoRequest(BaseModel):
23
  url: str
24
- platform: str # 'tiktok' or 'instagram'
25
  is_pro: bool = False
26
  fps: int = 2
27
 
@@ -30,7 +30,11 @@ def file_to_base64(filepath):
30
  with open(filepath, "rb") as f:
31
  return base64.b64encode(f.read()).decode('utf-8')
32
 
33
- # ── 2. TEST UI ROUTE ──
 
 
 
 
34
  @app.get("/", response_class=HTMLResponse)
35
  def index():
36
  return """
@@ -70,7 +74,7 @@ def index():
70
  const results = document.getElementById('results');
71
 
72
  btn.disabled = true;
73
- btn.innerText = "Processing... (may take 20s)";
74
  status.innerText = "Downloading and extracting frames...";
75
  results.innerHTML = "";
76
 
@@ -87,11 +91,11 @@ def index():
87
  const data = await res.json();
88
  if(data.success) {
89
  status.innerText = "Success! Extracted " + data.total_frames + " frames.";
90
- data.frames.slice(0, 8).forEach(img => {
91
  results.innerHTML += `<img src="data:image/jpeg;base64,${img}" class="rounded-lg">`;
92
  });
93
  } else {
94
- status.innerText = "Error: " + data.detail;
95
  }
96
  } catch(e) {
97
  status.innerText = "Network Error: " + e.message;
@@ -104,7 +108,6 @@ def index():
104
  </html>
105
  """
106
 
107
- # ── 3. MEDIA PROCESSING ROUTE ──
108
  @app.post("/process-video")
109
  def process_video(req: VideoRequest):
110
  job_id = str(uuid.uuid4())
@@ -114,28 +117,24 @@ def process_video(req: VideoRequest):
114
  video_path = os.path.join(work_dir, "video.mp4")
115
  audio_path = os.path.join(work_dir, "audio.mp3")
116
 
 
 
117
  try:
118
- # TikTok/IG require specific headers to not get 403 Forbidden
119
  ydl_opts = {
120
- 'format': 'bestvideo[height<=720]+bestaudio/best[height<=720]',
121
  'outtmpl': video_path,
122
  'quiet': True,
123
  'no_warnings': True,
124
  'nocheckcertificate': True,
125
- # Disguise as a standard mobile browser
126
- 'user_agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 16_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/16.0 Mobile/15E148 Safari/604.1',
127
- 'add_header': [
128
- 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
129
- 'Accept-Language: en-us',
130
- 'Connection: keep-alive',
131
- ]
132
  }
133
 
134
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
135
- ydl.download([req.url])
136
 
137
  if not os.path.exists(video_path):
138
- # Find the actual file if extension differed
139
  files = os.listdir(work_dir)
140
  if files: video_path = os.path.join(work_dir, files[0])
141
  else: raise ValueError("Download failed - No file saved.")
@@ -164,10 +163,7 @@ def process_video(req: VideoRequest):
164
  "-q:a", "0", "-map", "a", "-ac", "1", "-b:a", "64k", audio_path
165
  ], check=True, capture_output=True)
166
 
167
- # COLLECT DATA
168
  frame_files = sorted([f for f in os.listdir(work_dir) if f.startswith("frame_") and f.endswith(".jpg")])
169
-
170
- # Max limit for AI context windows
171
  if len(frame_files) > 80: frame_files = frame_files[:80]
172
 
173
  frames_b64 = [file_to_base64(os.path.join(work_dir, f)) for f in frame_files]
@@ -186,6 +182,5 @@ def process_video(req: VideoRequest):
186
  return {"success": False, "error": str(e)}
187
 
188
  finally:
189
- # 🚨 GARBAGE COLLECTION
190
  if os.path.exists(work_dir):
191
  shutil.rmtree(work_dir, ignore_errors=True)
 
8
  import shutil
9
  import yt_dlp
10
  import socket
11
+ import re
12
 
13
+ # Force IPv4
 
14
  orig_getaddrinfo = socket.getaddrinfo
15
  def hooked_getaddrinfo(*args, **kwargs):
16
  res = orig_getaddrinfo(*args, **kwargs)
 
21
 
22
  class VideoRequest(BaseModel):
23
  url: str
24
+ platform: str
25
  is_pro: bool = False
26
  fps: int = 2
27
 
 
30
  with open(filepath, "rb") as f:
31
  return base64.b64encode(f.read()).decode('utf-8')
32
 
33
+ def clean_url(url: str):
34
+ # Removes trailing text like "This post is shared via..."
35
+ match = re.search(r'(https?://[^\s]+)', url)
36
+ return match.group(0) if match else url
37
+
38
  @app.get("/", response_class=HTMLResponse)
39
  def index():
40
  return """
 
74
  const results = document.getElementById('results');
75
 
76
  btn.disabled = true;
77
+ btn.innerText = "Processing...";
78
  status.innerText = "Downloading and extracting frames...";
79
  results.innerHTML = "";
80
 
 
91
  const data = await res.json();
92
  if(data.success) {
93
  status.innerText = "Success! Extracted " + data.total_frames + " frames.";
94
+ data.frames.slice(0, 12).forEach(img => {
95
  results.innerHTML += `<img src="data:image/jpeg;base64,${img}" class="rounded-lg">`;
96
  });
97
  } else {
98
+ status.innerText = "Error: " + data.error;
99
  }
100
  } catch(e) {
101
  status.innerText = "Network Error: " + e.message;
 
108
  </html>
109
  """
110
 
 
111
  @app.post("/process-video")
112
  def process_video(req: VideoRequest):
113
  job_id = str(uuid.uuid4())
 
117
  video_path = os.path.join(work_dir, "video.mp4")
118
  audio_path = os.path.join(work_dir, "audio.mp3")
119
 
120
+ target_url = clean_url(req.url)
121
+
122
  try:
123
+ # 🚨 FORMAT FIX: Use 'best' to avoid split-stream errors on TikTok/IG
124
  ydl_opts = {
125
+ 'format': 'best[height<=720]',
126
  'outtmpl': video_path,
127
  'quiet': True,
128
  'no_warnings': True,
129
  'nocheckcertificate': True,
130
+ 'user_agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36',
131
+ 'extractor_args': {'youtube': ['player_client=android,web']}
 
 
 
 
 
132
  }
133
 
134
  with yt_dlp.YoutubeDL(ydl_opts) as ydl:
135
+ ydl.download([target_url])
136
 
137
  if not os.path.exists(video_path):
 
138
  files = os.listdir(work_dir)
139
  if files: video_path = os.path.join(work_dir, files[0])
140
  else: raise ValueError("Download failed - No file saved.")
 
163
  "-q:a", "0", "-map", "a", "-ac", "1", "-b:a", "64k", audio_path
164
  ], check=True, capture_output=True)
165
 
 
166
  frame_files = sorted([f for f in os.listdir(work_dir) if f.startswith("frame_") and f.endswith(".jpg")])
 
 
167
  if len(frame_files) > 80: frame_files = frame_files[:80]
168
 
169
  frames_b64 = [file_to_base64(os.path.join(work_dir, f)) for f in frame_files]
 
182
  return {"success": False, "error": str(e)}
183
 
184
  finally:
 
185
  if os.path.exists(work_dir):
186
  shutil.rmtree(work_dir, ignore_errors=True)