Saqib commited on
Commit
4550586
1 Parent(s): b675688

Update modules/app.py

Browse files
Files changed (1) hide show
  1. modules/app.py +47 -104
modules/app.py CHANGED
@@ -1,17 +1,15 @@
1
- from fastapi import FastAPI, HTTPException, Request, Depends
2
  from fastapi.staticfiles import StaticFiles
3
  from pytubefix import YouTube
4
  from pytubefix.exceptions import PytubeFixError
5
  from concurrent.futures import ThreadPoolExecutor
6
  import ffmpeg
7
- from pydantic import BaseModel, HttpUrl
8
- from typing import List
9
  import asyncio
 
 
10
  import requests
11
  import tempfile
12
- import time
13
  import uuid
14
- import aiohttp
15
  import base64
16
  import io
17
  import os
@@ -22,14 +20,7 @@ import json
22
 
23
  app = FastAPI()
24
 
25
- whisper_origin = os.getenv("WHISPER_ORIGIN")
26
- whisper_base_url = os.getenv("WHISPER_BASE_URL")
27
- img2location_name = os.getenv("IMG2LOCATION_NAME")
28
- img2location_origin = os.getenv("IMG2LOCATION_ORIGIN")
29
- img2location_base_url = os.getenv("IMG2LOCATION_BASE_URL")
30
- pixart_sigma_base_url = os.getenv("PIXART_SIGMA_BASE_URL")
31
- allowed_user_agent = os.getenv("ALLOWED_USER_AGENT")
32
-
33
 
34
  def generate_hash(length=12):
35
  # Characters that can appear in the hash
@@ -56,13 +47,6 @@ app.mount("/audio", StaticFiles(directory=AUDIO_DIR), name="audio")
56
  # Mount the output directory
57
  app.mount("/output", StaticFiles(directory=OUTPUT_DIR), name="output")
58
 
59
- class AudioImageInput(BaseModel):
60
- image_url: HttpUrl
61
- audio_url: HttpUrl
62
-
63
- class VideosInput(BaseModel):
64
- video_urls: List[HttpUrl]
65
-
66
  thread_pool = ThreadPoolExecutor(max_workers=2)
67
 
68
  async def run_ffmpeg_async(ffmpeg_command):
@@ -79,27 +63,21 @@ async def download_file(url: str, suffix: str):
79
  return temp_file.name
80
 
81
  @app.post("/add_audio_to_image")
82
- async def add_audio_to_image(input_data: AudioImageInput):
83
  try:
84
- # Download image and audio files
85
- temp_image_path = await download_file(str(input_data.image_url), ".png")
86
- temp_audio_path = await download_file(str(input_data.audio_url), ".mp3")
87
-
88
  # Generate a unique filename
89
  output_filename = f"{uuid.uuid4()}.mp4"
90
  output_path = os.path.join(OUTPUT_DIR, output_filename)
91
 
92
- # Use ffmpeg to combine image and audio into a video
93
- input_image = ffmpeg.input(temp_image_path, loop=1, t=5) # 5 seconds duration
94
- input_audio = ffmpeg.input(temp_audio_path)
95
- ffmpeg_command = ffmpeg.concat(input_image, input_audio, v=1, a=1).output(output_path, vcodec='libx264', acodec='aac')
96
-
97
- # Run ffmpeg asynchronously
98
- await run_ffmpeg_async(ffmpeg_command.run)
99
-
100
- # Clean up temporary files
101
- os.unlink(temp_image_path)
102
- os.unlink(temp_audio_path)
103
 
104
  # Return the URL path to the output file
105
  return f"https://sxqib-api.hf.space/output/{output_filename}"
@@ -109,86 +87,51 @@ async def add_audio_to_image(input_data: AudioImageInput):
109
  raise HTTPException(status_code=500, detail=f"An unexpected error occurred: {str(e)}")
110
 
111
  @app.post("/concatenate_videos")
112
- async def concatenate_videos(input_data: VideosInput):
113
  try:
114
- temp_video_paths = []
115
- # Download videos to temporary files
116
- for video_url in input_data.video_urls:
117
- temp_video_paths.append(await download_file(str(video_url), ".mp4"))
118
-
119
  # Generate a unique filename for the output
120
  output_filename = f"{uuid.uuid4()}.mp4"
121
  output_path = os.path.join(OUTPUT_DIR, output_filename)
122
 
123
- # Separate video and audio streams
124
- video_and_audio_streams = []
125
- for path in temp_video_paths:
126
- video = ffmpeg.input(path).video
127
- audio = ffmpeg.input(path).audio
128
- video_and_audio_streams.append(video)
129
- video_and_audio_streams.append(audio)
130
-
131
- # Concatenate video and audio streams
132
- joined = ffmpeg.concat(*video_and_audio_streams, v=1, a=1).node
133
-
134
- # Merge video and audio
135
- ffmpeg_command = ffmpeg.output(joined[0], joined[1], output_path, vcodec='libx264', acodec='aac')
136
-
137
- # Run ffmpeg asynchronously
138
- await run_ffmpeg_async(ffmpeg_command.run)
139
-
140
- # Clean up temporary files
141
- for path in temp_video_paths:
142
- os.remove(path)
143
 
144
  # Return the URL path to the output file
145
  return f"https://sxqib-api.hf.space/output/{output_filename}"
 
146
  except Exception as e:
147
  print(f"An error occurred: {str(e)}")
148
  print(traceback.format_exc())
149
  raise HTTPException(status_code=500, detail=f"An unexpected error occurred: {str(e)}")
150
 
151
  @app.get("/get_audio")
152
- async def get_audio(url: str):
153
- if not url:
154
- raise HTTPException(status_code=400, detail="URL is required")
155
-
156
  try:
157
- print(f"Attempting to process YouTube URL: {url}")
158
- yt = YouTube(url)
159
- video = yt.streams.filter(only_audio=True).first()
160
-
161
- if not video:
162
- print(f"No audio stream found for URL: {url}")
163
- raise HTTPException(status_code=404, detail="No audio stream found for this video")
164
-
165
  # Generate a unique filename
166
  unique_filename = f"{uuid.uuid4().hex}.mp3"
167
  out_file = os.path.join(AUDIO_DIR, unique_filename)
168
 
169
- print((f"Downloading audio to: {out_file}"))
170
-
171
- # Download the audio
172
- video.download(output_path=AUDIO_DIR, filename=unique_filename, timeout=30)
173
-
174
- file_stats = os.stat(out_file)
175
- print(f'Size of audio file in Bytes: {file_stats.st_size}')
176
-
177
- if file_stats.st_size <= 30000000:
178
- # Construct the URL for the MP3 file
179
- mp3_url = f"https://sxqib-api.hf.space/audio/{unique_filename}"
180
- return mp3_url
181
- else:
182
- os.remove(out_file)
183
- raise HTTPException(status_code=413, detail="Audio file is too large. Limited to about 1.5 hours.")
184
- except PytubeFixError as e:
185
- print(f"PytubeError occurred: {str(e)}")
186
- raise HTTPException(status_code=400, detail=f"Error processing YouTube video: {str(e)}")
187
- except HTTPException as he:
188
- # Re-raise HTTP exceptions
189
- raise he
190
  except Exception as e:
191
- print(f"Unexpected error occurred: {str(e)}")
192
  print(traceback.format_exc())
193
  raise HTTPException(status_code=500, detail=f"An unexpected error occurred: {str(e)}")
194
 
@@ -206,9 +149,9 @@ async def whisper(request: Request):
206
  'Connection': 'keep-alive',
207
  'Content-Type': 'application/json',
208
  'DNT': '1',
209
- 'Origin': whisper_origin,
210
  'Pragma': 'no-cache',
211
- 'Referer': f'{whisper_origin}/',
212
  'Sec-Fetch-Dest': 'empty',
213
  'Sec-Fetch-Mode': 'cors',
214
  'Sec-Fetch-Site': 'same-site',
@@ -231,7 +174,7 @@ async def whisper(request: Request):
231
  json_data = '{"audio": "' + audio_base64 + '"}'
232
 
233
  # Post request to the API
234
- async with session.post(f'{whisper_base_url}/v1/inference/openai/whisper-large', headers=headers, data=json_data) as post_resp:
235
  if post_resp.status != 200:
236
  return f"API request failed: {post_resp.status}"
237
  return await post_resp.json()
@@ -249,10 +192,10 @@ async def img2location(request: Request):
249
  'accept-language': 'en-US,en;q=0.9',
250
  'cache-control': 'no-cache',
251
  'dnt': '1',
252
- 'origin': img2location_origin,
253
  'pragma': 'no-cache',
254
  'priority': 'u=1, i',
255
- 'referer': f'{img2location_origin}/',
256
  'sec-ch-ua': '"Chromium";v="124", "Microsoft Edge";v="124", "Not-A.Brand";v="99"',
257
  'sec-ch-ua-mobile': '?0',
258
  'sec-ch-ua-platform': '"Windows"',
@@ -274,7 +217,7 @@ async def img2location(request: Request):
274
  data.add_field('image', io.BytesIO(image_data), filename="image.png", content_type='image/png')
275
 
276
  # Sending the POST request
277
- async with session.post(img2location_base_url, headers=headers, data=data) as response:
278
  if response.status != 200:
279
  return f"Failed to upload image: HTTP {response.status}"
280
  json_response = await response.json()
@@ -335,14 +278,14 @@ async def pixart_sigma(request: Request):
335
  }
336
 
337
  async with aiohttp.ClientSession() as session:
338
- async with session.post(f'{pixart_sigma_base_url}/queue/join', params=params, headers=headers, json=json_data, ssl=False) as response:
339
  print(response.status)
340
 
341
  params = {
342
  'session_hash': hash,
343
  }
344
 
345
- async with session.get(f'{pixart_sigma_base_url}/queue/data', params=params, headers=headers, ssl=False) as response:
346
  async for line in response.content:
347
  try:
348
  if line:
 
1
+ from fastapi import FastAPI, HTTPException, Request
2
  from fastapi.staticfiles import StaticFiles
3
  from pytubefix import YouTube
4
  from pytubefix.exceptions import PytubeFixError
5
  from concurrent.futures import ThreadPoolExecutor
6
  import ffmpeg
 
 
7
  import asyncio
8
+ import aiohttp
9
+ import aiofiles
10
  import requests
11
  import tempfile
 
12
  import uuid
 
13
  import base64
14
  import io
15
  import os
 
20
 
21
  app = FastAPI()
22
 
23
+ MODAL_BASE_URL = "https://sxqib--api-fastapi-app.modal.run"
 
 
 
 
 
 
 
24
 
25
  def generate_hash(length=12):
26
  # Characters that can appear in the hash
 
47
  # Mount the output directory
48
  app.mount("/output", StaticFiles(directory=OUTPUT_DIR), name="output")
49
 
 
 
 
 
 
 
 
50
  thread_pool = ThreadPoolExecutor(max_workers=2)
51
 
52
  async def run_ffmpeg_async(ffmpeg_command):
 
63
  return temp_file.name
64
 
65
  @app.post("/add_audio_to_image")
66
+ async def add_audio_to_image(request: Request):
67
  try:
 
 
 
 
68
  # Generate a unique filename
69
  output_filename = f"{uuid.uuid4()}.mp4"
70
  output_path = os.path.join(OUTPUT_DIR, output_filename)
71
 
72
+ # Call the modal API with the request data and download the output file
73
+ data = await request.json()
74
+ async with aiohttp.ClientSession() as session:
75
+ async with session.post(f"{MODAL_BASE_URL}/add_audio_to_image", json=data) as response:
76
+ if response.status != 200:
77
+ raise HTTPException(status_code=500, detail="Failed to process request")
78
+ output_data = await response.read()
79
+ async with aiofiles.open(output_path, "wb") as f:
80
+ await f.write(output_data)
 
 
81
 
82
  # Return the URL path to the output file
83
  return f"https://sxqib-api.hf.space/output/{output_filename}"
 
87
  raise HTTPException(status_code=500, detail=f"An unexpected error occurred: {str(e)}")
88
 
89
  @app.post("/concatenate_videos")
90
+ async def concatenate_videos(request: Request):
91
  try:
 
 
 
 
 
92
  # Generate a unique filename for the output
93
  output_filename = f"{uuid.uuid4()}.mp4"
94
  output_path = os.path.join(OUTPUT_DIR, output_filename)
95
 
96
+ # Call the modal API with the request data and download the output file
97
+ data = await request.json()
98
+ async with aiohttp.ClientSession() as session:
99
+ async with session.post(f"{MODAL_BASE_URL}/concatenate_videos", json=data) as response:
100
+ if response.status != 200:
101
+ raise HTTPException(status_code=500, detail="Failed to process request")
102
+ output_data = await response.read()
103
+ async with aiofiles.open(output_path, "wb") as f:
104
+ await f.write(output_data)
 
 
 
 
 
 
 
 
 
 
 
105
 
106
  # Return the URL path to the output file
107
  return f"https://sxqib-api.hf.space/output/{output_filename}"
108
+
109
  except Exception as e:
110
  print(f"An error occurred: {str(e)}")
111
  print(traceback.format_exc())
112
  raise HTTPException(status_code=500, detail=f"An unexpected error occurred: {str(e)}")
113
 
114
  @app.get("/get_audio")
115
+ async def get_audio(request: Request):
 
 
 
116
  try:
 
 
 
 
 
 
 
 
117
  # Generate a unique filename
118
  unique_filename = f"{uuid.uuid4().hex}.mp3"
119
  out_file = os.path.join(AUDIO_DIR, unique_filename)
120
 
121
+ # Call the modal API with the request data and download the output file
122
+ data = await request.json()
123
+ async with aiohttp.ClientSession() as session:
124
+ async with session.post(f"{MODAL_BASE_URL}/get_audio", json=data) as response:
125
+ if response.status != 200:
126
+ raise HTTPException(status_code=500, detail="Failed to process request")
127
+ output_data = await response.read()
128
+ async with aiofiles.open(out_file, "wb") as f:
129
+ await f.write(output_data)
130
+
131
+ # Return the URL path to the output file
132
+ return f"https://sxqib-api.hf.space/audio/{unique_filename}"
 
 
 
 
 
 
 
 
 
133
  except Exception as e:
134
+ print(f"An error occurred: {str(e)}")
135
  print(traceback.format_exc())
136
  raise HTTPException(status_code=500, detail=f"An unexpected error occurred: {str(e)}")
137
 
 
149
  'Connection': 'keep-alive',
150
  'Content-Type': 'application/json',
151
  'DNT': '1',
152
+ 'Origin': 'https://deepinfra.com',
153
  'Pragma': 'no-cache',
154
+ 'Referer': 'https://deepinfra.com/',
155
  'Sec-Fetch-Dest': 'empty',
156
  'Sec-Fetch-Mode': 'cors',
157
  'Sec-Fetch-Site': 'same-site',
 
174
  json_data = '{"audio": "' + audio_base64 + '"}'
175
 
176
  # Post request to the API
177
+ async with session.post(f'https://api.deepinfra.com/v1/inference/openai/whisper-large', headers=headers, data=json_data) as post_resp:
178
  if post_resp.status != 200:
179
  return f"API request failed: {post_resp.status}"
180
  return await post_resp.json()
 
192
  'accept-language': 'en-US,en;q=0.9',
193
  'cache-control': 'no-cache',
194
  'dnt': '1',
195
+ 'origin': 'https://geospy.ai',
196
  'pragma': 'no-cache',
197
  'priority': 'u=1, i',
198
+ 'referer': 'https://geospy.ai/',
199
  'sec-ch-ua': '"Chromium";v="124", "Microsoft Edge";v="124", "Not-A.Brand";v="99"',
200
  'sec-ch-ua-mobile': '?0',
201
  'sec-ch-ua-platform': '"Windows"',
 
217
  data.add_field('image', io.BytesIO(image_data), filename="image.png", content_type='image/png')
218
 
219
  # Sending the POST request
220
+ async with session.post("https://locate-image-7cs5mab6na-uc.a.run.app/", headers=headers, data=data) as response:
221
  if response.status != 200:
222
  return f"Failed to upload image: HTTP {response.status}"
223
  json_response = await response.json()
 
278
  }
279
 
280
  async with aiohttp.ClientSession() as session:
281
+ async with session.post(f'https://pixart-alpha-pixart-sigma.hf.space/queue/join', params=params, headers=headers, json=json_data, ssl=False) as response:
282
  print(response.status)
283
 
284
  params = {
285
  'session_hash': hash,
286
  }
287
 
288
+ async with session.get(f'https://pixart-alpha-pixart-sigma.hf.space/queue/data', params=params, headers=headers, ssl=False) as response:
289
  async for line in response.content:
290
  try:
291
  if line: