|
from fastapi import FastAPI, HTTPException, Request, Depends |
|
from fastapi.staticfiles import StaticFiles |
|
from pytubefix import YouTube |
|
from pytubefix.exceptions import PytubeError |
|
import time |
|
import uuid |
|
import logging |
|
import aiohttp |
|
import base64 |
|
import io |
|
import os |
|
import random |
|
import traceback |
|
import string |
|
import json |
|
|
|
app = FastAPI() |
|
|
|
whisper_origin = os.getenv("WHISPER_ORIGIN") |
|
whisper_base_url = os.getenv("WHISPER_BASE_URL") |
|
img2location_name = os.getenv("IMG2LOCATION_NAME") |
|
img2location_origin = os.getenv("IMG2LOCATION_ORIGIN") |
|
img2location_base_url = os.getenv("IMG2LOCATION_BASE_URL") |
|
pixart_sigma_base_url = os.getenv("PIXART_SIGMA_BASE_URL") |
|
allowed_user_agent = os.getenv("ALLOWED_USER_AGENT") |
|
|
|
|
|
def generate_hash(length=12): |
|
|
|
characters = string.ascii_lowercase + string.digits |
|
|
|
hash_string = ''.join(random.choice(characters) for _ in range(length)) |
|
return hash_string |
|
|
|
@app.get("/") |
|
async def read_root(): |
|
return {"message": "Saqib's API"} |
|
|
|
|
|
AUDIO_DIR = "audio_files" |
|
os.makedirs(AUDIO_DIR, exist_ok=True) |
|
|
|
|
|
app.mount("/audio", StaticFiles(directory=AUDIO_DIR), name="audio") |
|
|
|
@app.get("/get_audio") |
|
async def get_audio(url: str): |
|
if not url: |
|
raise HTTPException(status_code=400, detail="URL is required") |
|
|
|
try: |
|
print(f"Attempting to process YouTube URL: {url}") |
|
yt = YouTube(url) |
|
video = yt.streams.filter(only_audio=True).first() |
|
|
|
if not video: |
|
print(f"No audio stream found for URL: {url}") |
|
raise HTTPException(status_code=404, detail="No audio stream found for this video") |
|
|
|
|
|
unique_filename = f"{uuid.uuid4().hex}.mp3" |
|
out_file = os.path.join(AUDIO_DIR, unique_filename) |
|
|
|
print((f"Downloading audio to: {out_file}")) |
|
|
|
|
|
video.download(output_path=AUDIO_DIR, filename=unique_filename) |
|
|
|
file_stats = os.stat(out_file) |
|
logging.info(f'Size of audio file in Bytes: {file_stats.st_size}') |
|
|
|
if file_stats.st_size <= 30000000: |
|
|
|
mp3_url = f"/audio/{unique_filename}" |
|
return mp3_url |
|
else: |
|
os.remove(out_file) |
|
raise HTTPException(status_code=413, detail="Audio file is too large. Limited to about 1.5 hours.") |
|
except PytubeError as e: |
|
print(f"PytubeError occurred: {str(e)}") |
|
raise HTTPException(status_code=400, detail=f"Error processing YouTube video: {str(e)}") |
|
except HTTPException as he: |
|
|
|
raise he |
|
except Exception as e: |
|
print(f"Unexpected error occurred: {str(e)}") |
|
print(traceback.format_exc()) |
|
raise HTTPException(status_code=500, detail=f"An unexpected error occurred: {str(e)}") |
|
|
|
@app.post("/whisper") |
|
async def whisper(request: Request): |
|
data = await request.json() |
|
if "audio_url" not in data: |
|
raise HTTPException(status_code=400, detail="audio_url not found in request") |
|
url = data["audio_url"] |
|
|
|
headers = { |
|
'Accept': 'application/json, text/plain, */*', |
|
'Accept-Language': 'en-US,en;q=0.9', |
|
'Cache-Control': 'no-cache', |
|
'Connection': 'keep-alive', |
|
'Content-Type': 'application/json', |
|
'DNT': '1', |
|
'Origin': whisper_origin, |
|
'Pragma': 'no-cache', |
|
'Referer': f'{whisper_origin}/', |
|
'Sec-Fetch-Dest': 'empty', |
|
'Sec-Fetch-Mode': 'cors', |
|
'Sec-Fetch-Site': 'same-site', |
|
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0', |
|
'sec-ch-ua': '"Chromium";v="124", "Microsoft Edge";v="124", "Not-A.Brand";v="99"', |
|
'sec-ch-ua-mobile': '?0', |
|
'sec-ch-ua-platform': '"Windows"', |
|
} |
|
|
|
|
|
async with aiohttp.ClientSession() as session: |
|
async with session.get(url) as resp: |
|
if resp.status != 200: |
|
return f"Failed to download audio: {resp.status}" |
|
audio_data = await resp.read() |
|
|
|
|
|
audio_base64 = base64.b64encode(audio_data).decode("utf-8") |
|
|
|
json_data = '{"audio": "' + audio_base64 + '"}' |
|
|
|
|
|
async with session.post(f'{whisper_base_url}/v1/inference/openai/whisper-large', headers=headers, data=json_data) as post_resp: |
|
if post_resp.status != 200: |
|
return f"API request failed: {post_resp.status}" |
|
return await post_resp.json() |
|
|
|
@app.post("/img2location") |
|
async def img2location(request: Request): |
|
request_json = await request.json() |
|
image_url = request_json.get("image_url", None) |
|
|
|
if not image_url: |
|
raise HTTPException(status_code=400, detail="image_url not found in request") |
|
|
|
headers = { |
|
'accept': '*/*', |
|
'accept-language': 'en-US,en;q=0.9', |
|
'cache-control': 'no-cache', |
|
'dnt': '1', |
|
'origin': img2location_origin, |
|
'pragma': 'no-cache', |
|
'priority': 'u=1, i', |
|
'referer': f'{img2location_origin}/', |
|
'sec-ch-ua': '"Chromium";v="124", "Microsoft Edge";v="124", "Not-A.Brand";v="99"', |
|
'sec-ch-ua-mobile': '?0', |
|
'sec-ch-ua-platform': '"Windows"', |
|
'sec-fetch-dest': 'empty', |
|
'sec-fetch-mode': 'cors', |
|
'sec-fetch-site': 'cross-site', |
|
'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36 Edg/124.0.0.0', |
|
} |
|
|
|
async with aiohttp.ClientSession() as session: |
|
|
|
async with session.get(image_url) as img_response: |
|
if img_response.status != 200: |
|
return f"Failed to fetch image: HTTP {img_response.status}" |
|
image_data = await img_response.read() |
|
|
|
|
|
data = aiohttp.FormData() |
|
data.add_field('image', io.BytesIO(image_data), filename="image.png", content_type='image/png') |
|
|
|
|
|
async with session.post(img2location_base_url, headers=headers, data=data) as response: |
|
if response.status != 200: |
|
return f"Failed to upload image: HTTP {response.status}" |
|
json_response = await response.json() |
|
if json_response["message"]["latitude"] and json_response["message"]["longitude"]: |
|
json_response["message"]["latitude"] = str(json_response["message"]["latitude"]) |
|
json_response["message"]["longitude"] = str(json_response["message"]["longitude"]) |
|
return json_response |
|
|
|
@app.post("/pixart-sigma") |
|
async def pixart_sigma(request: Request): |
|
request_json = await request.json() |
|
prompt = request_json.get("prompt", None) |
|
negative_prompt = request_json.get("negative_prompt", "") |
|
style = request_json.get("style", "(No style)") |
|
use_negative_prompt = request_json.get("use_negative_prompt", True) |
|
num_imgs = request_json.get("num_imgs", 1) |
|
seed = request_json.get("seed", 0) |
|
width = request_json.get("width", 1024) |
|
height = request_json.get("height", 1024) |
|
schedule = request_json.get("schedule", "DPM-Solver") |
|
dpms_guidance_scale = request_json.get("dpms_guidance_scale", 4.5) |
|
sas_guidance_scale = request_json.get("sas_guidance_scale", 3) |
|
dpms_inference_steps = request_json.get("dpms_inference_steps", 14) |
|
sas_inference_steps = request_json.get("sas_inference_steps", 25) |
|
randomize_seed = request_json.get("randomize_seed", True) |
|
|
|
hash = generate_hash() |
|
|
|
headers = { |
|
'accept': '*/*' |
|
} |
|
|
|
params = { |
|
'__theme': 'light', |
|
} |
|
|
|
json_data = { |
|
'data': [ |
|
prompt, |
|
negative_prompt, |
|
style, |
|
use_negative_prompt, |
|
num_imgs, |
|
seed, |
|
width, |
|
height, |
|
schedule, |
|
dpms_guidance_scale, |
|
sas_guidance_scale, |
|
dpms_inference_steps, |
|
sas_inference_steps, |
|
randomize_seed, |
|
], |
|
'event_data': None, |
|
'fn_index': 3, |
|
'trigger_id': 7, |
|
'session_hash': hash, |
|
} |
|
|
|
async with aiohttp.ClientSession() as session: |
|
async with session.post(f'{pixart_sigma_base_url}/queue/join', params=params, headers=headers, json=json_data, ssl=False) as response: |
|
print(response.status) |
|
|
|
params = { |
|
'session_hash': hash, |
|
} |
|
|
|
async with session.get(f'{pixart_sigma_base_url}/queue/data', params=params, headers=headers, ssl=False) as response: |
|
async for line in response.content: |
|
try: |
|
if line: |
|
line = line.decode('utf-8') |
|
line = line.replace('data: ', '') |
|
line_json = json.loads(line) |
|
if line_json["msg"] == "process_completed": |
|
image_url = line_json["output"]["data"][0][0]["image"]["url"] |
|
return {"image_url": image_url} |
|
except: |
|
pass |
|
|
|
|
|
|
|
|