Chrunos commited on
Commit
9675676
·
verified ·
1 Parent(s): 9aed14f

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +167 -0
app.py ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import tempfile
3
+ import urllib.parse
4
+ from datetime import datetime
5
+ from pathlib import Path
6
+ import logging
7
+
8
+ from fastapi import FastAPI, Request
9
+ from fastapi.concurrency import run_in_threadpool
10
+ import yt_dlp
11
+ import cloudscraper
12
+ from dotenv import load_dotenv
13
+
14
+ # Setup logging
15
+ logging.basicConfig(level=logging.INFO)
16
+ logger = logging.getLogger(__name__)
17
+
18
+ tmp_dir = tempfile.gettempdir()
19
+ BASE_URL = "https://chrunos-kai.hf.space"
20
+
21
+ load_dotenv()
22
+ app = FastAPI()
23
+
24
+ # Define a global temporary download directory
25
+ global_download_dir = tempfile.mkdtemp()
26
+
27
+ EXTRACT_API = os.getenv("EXTRACT_API")
28
+ ALT_API = os.getenv("ALT_API")
29
+
30
+
31
+ def extract_video_info(video_url: str) -> dict:
32
+ """Extract video information from the provided URL using fallback APIs."""
33
+ api_urls = [f'{ALT_API}?url={video_url}', f'{EXTRACT_API}?url={video_url}']
34
+
35
+ for api_url in api_urls:
36
+ logger.info(f"Trying API: {api_url}")
37
+ session = cloudscraper.create_scraper()
38
+
39
+ try:
40
+ response = session.get(api_url, timeout=20)
41
+
42
+ if response.status_code == 200:
43
+ json_response = response.json()
44
+ result = []
45
+
46
+ if 'formats' in json_response:
47
+ for format_item in json_response['formats']:
48
+ format_url = format_item.get('url')
49
+ format_id = format_item.get('format_id')
50
+ p_cookies = format_item.get('cookies')
51
+
52
+ if format_id and format_url:
53
+ result.append({
54
+ "url": format_url,
55
+ "format_id": format_id,
56
+ "cookies": p_cookies
57
+ })
58
+
59
+ title = json_response.get('title')
60
+ logger.info(f"Video title: {title}")
61
+
62
+ if "ornhub.com" in video_url:
63
+ p_result = [item for item in result if 'hls' in item['format_id']]
64
+ return p_result
65
+ else:
66
+ if len(result) == 1:
67
+ new_item = {
68
+ "format_id": "This is Fake, Don't Choose This One",
69
+ "url": "none"
70
+ }
71
+ result.append(new_item)
72
+ return result
73
+
74
+ else:
75
+ if 'url' in json_response:
76
+ d_url = json_response.get('url')
77
+ t_url = json_response.get('thumbnail')
78
+ result.append({
79
+ "url": d_url,
80
+ "format_id": "video"
81
+ })
82
+ result.append({
83
+ "url": t_url,
84
+ "format_id": "thumbnail"
85
+ })
86
+ return result
87
+ else:
88
+ return {"error": "No formats available"}
89
+ else:
90
+ logger.warning(f"Request failed with status code {response.status_code}, API: {api_url}")
91
+
92
+ except Exception as e:
93
+ logger.error(f"An error occurred with API {api_url}: {e}")
94
+
95
+ return {"error": "Both APIs failed to provide valid results."}
96
+
97
+
98
+ @app.post("/pripper")
99
+ async def test_download(request: Request):
100
+ """Test endpoint to extract video information."""
101
+ try:
102
+ data = await request.json()
103
+ video_url = data.get('url')
104
+
105
+ if not video_url:
106
+ return {"error": "URL parameter is required"}
107
+
108
+ response = extract_video_info(video_url)
109
+ return response
110
+ except Exception as e:
111
+ logger.error(f"Error in test_download: {e}")
112
+ return {"error": f"Failed to process request: {str(e)}"}
113
+
114
+
115
+ @app.post("/hls")
116
+ async def download_hls_video(request: Request):
117
+ """Download HLS video and return download URL."""
118
+ try:
119
+ data = await request.json()
120
+ hls_url = data.get('url')
121
+
122
+ if not hls_url:
123
+ return {"error": "URL parameter is required"}
124
+
125
+ timestamp = datetime.now().strftime('%Y%m%d%H%M%S')
126
+ output_template = str(Path(global_download_dir) / f'%(title)s_{timestamp}.%(ext)s')
127
+
128
+ ydl_opts = {
129
+ 'format': 'best',
130
+ 'outtmpl': output_template,
131
+ 'quiet': True,
132
+ 'no_warnings': True,
133
+ 'noprogress': True,
134
+ 'merge_output_format': 'mp4'
135
+ }
136
+
137
+ try:
138
+ await run_in_threadpool(lambda: yt_dlp.YoutubeDL(ydl_opts).download([hls_url]))
139
+ except Exception as e:
140
+ logger.error(f"yt-dlp download failed: {e}")
141
+ return {"error": f"Download failed: {str(e)}"}
142
+
143
+ downloaded_files = list(Path(global_download_dir).glob(f"*_{timestamp}.mp4"))
144
+ if not downloaded_files:
145
+ return {"error": "Download failed - no files found"}
146
+
147
+ downloaded_file = downloaded_files[0]
148
+ encoded_filename = urllib.parse.quote(downloaded_file.name)
149
+ download_url = f"{BASE_URL}/file/{encoded_filename}"
150
+
151
+ logger.info(f"Download successful: {download_url}")
152
+ return {"url": download_url}
153
+
154
+ except Exception as e:
155
+ logger.error(f"Error in download_hls_video: {e}")
156
+ return {"error": f"Failed to process request: {str(e)}"}
157
+
158
+
159
+ @app.get("/health")
160
+ async def health_check():
161
+ """Health check endpoint."""
162
+ return {"status": "healthy", "message": "Service is running"}
163
+
164
+
165
+ if __name__ == "__main__":
166
+ import uvicorn
167
+ uvicorn.run(app, host="0.0.0.0", port=8000)