darkvibe314 commited on
Commit
66e27d9
Β·
verified Β·
1 Parent(s): e6380fe

Create main.py

Browse files
Files changed (1) hide show
  1. main.py +116 -0
main.py ADDED
@@ -0,0 +1,116 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import time
3
+ import asyncio
4
+ import aiohttp
5
+ import subprocess
6
+ import urllib.parse
7
+ from fastapi import FastAPI, BackgroundTasks, HTTPException
8
+ from fastapi.responses import FileResponse, JSONResponse
9
+ from fastapi.middleware.cors import CORSMiddleware
10
+
11
+ # ==========================================
12
+ # πŸš€ API SETUP & DOCUMENTATION
13
+ # ==========================================
14
+ app = FastAPI(
15
+ title="SILENT TECH Media API",
16
+ description="High-Speed API for YouTube Searching, MP4 fetching, and ultra-fast FFmpeg MP3 Extraction.",
17
+ version="1.0.0"
18
+ )
19
+
20
+ # Allow your bots to connect from anywhere
21
+ app.add_middleware(
22
+ CORSMiddleware,
23
+ allow_origins=["*"],
24
+ allow_methods=["*"],
25
+ allow_headers=["*"],
26
+ )
27
+
28
+ # Background task to clean up storage after sending the file
29
+ def cleanup_files(files: list):
30
+ for f in files:
31
+ if os.path.exists(f):
32
+ try:
33
+ os.remove(f)
34
+ except:
35
+ pass
36
+
37
+ # ==========================================
38
+ # πŸ“‘ ENDPOINTS
39
+ # ==========================================
40
+
41
+ @app.get("/")
42
+ def read_root():
43
+ return {"status": "Online", "message": "SILENT TECH Engine is running. Visit /docs for the API Documentation!"}
44
+
45
+ @app.get("/api/search")
46
+ async def search_yt(query: str):
47
+ """πŸ” Search YouTube and return metadata."""
48
+ async with aiohttp.ClientSession() as session:
49
+ url = f"https://apis.davidcyril.name.ng/play?query={urllib.parse.quote(query)}"
50
+ async with session.get(url) as resp:
51
+ data = await resp.json()
52
+ if not data.get("status"):
53
+ raise HTTPException(status_code=404, detail="Not found")
54
+ return data
55
+
56
+ @app.get("/api/ytmp4")
57
+ async def get_ytmp4(url: str):
58
+ """🎬 Get a direct MP4 Download URL."""
59
+ async with aiohttp.ClientSession() as session:
60
+ api_url = f"https://apis.davidcyril.name.ng/download/ytmp4?url={urllib.parse.quote(url)}"
61
+ async with session.get(api_url) as resp:
62
+ data = await resp.json()
63
+ if not data.get("success"):
64
+ raise HTTPException(status_code=400, detail="Failed to fetch video link")
65
+ return data
66
+
67
+ @app.get("/api/ytmp3")
68
+ async def get_ytmp3(url: str, background_tasks: BackgroundTasks):
69
+ """🎡 Download MP4, convert to MP3 instantly via FFmpeg, and return the audio file."""
70
+ timestamp = int(time.time() * 1000)
71
+ temp_vid = f"temp_vid_{timestamp}.mp4"
72
+ temp_aud = f"temp_aud_{timestamp}.mp3"
73
+
74
+ # Tell the API to delete these files AFTER the user finishes downloading them
75
+ background_tasks.add_task(cleanup_files, [temp_vid, temp_aud])
76
+
77
+ try:
78
+ # 1. Fetch the raw MP4 stream link
79
+ async with aiohttp.ClientSession() as session:
80
+ api_url = f"https://apis.davidcyril.name.ng/download/ytmp4?url={urllib.parse.quote(url)}"
81
+ async with session.get(api_url) as resp:
82
+ data = await resp.json()
83
+ if not data.get("success") or not data.get("result", {}).get("download_url"):
84
+ raise HTTPException(status_code=400, detail="Failed to fetch stream")
85
+
86
+ download_url = data["result"]["download_url"]
87
+ title = data["result"].get("title", "Silent_Tech_Audio").replace("/", "_")
88
+
89
+ # 2. Download the MP4 file to Hugging Face Disk
90
+ async with session.get(download_url) as video_resp:
91
+ with open(temp_vid, 'wb') as f:
92
+ while True:
93
+ chunk = await video_resp.content.read(2 * 1024 * 1024) # 2MB chunks
94
+ if not chunk: break
95
+ f.write(chunk)
96
+
97
+ # 3. SuperSonic FFmpeg Conversion
98
+ command = [
99
+ "ffmpeg", "-y", "-i", temp_vid,
100
+ "-vn", "-acodec", "libmp3lame", "-q:a", "2",
101
+ temp_aud
102
+ ]
103
+ process = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
104
+ if process.returncode != 0:
105
+ raise Exception("FFmpeg audio extraction failed.")
106
+
107
+ # 4. Stream the MP3 directly back to the user/bot
108
+ return FileResponse(
109
+ path=temp_aud,
110
+ media_type="audio/mpeg",
111
+ filename=f"{title}.mp3"
112
+ )
113
+
114
+ except Exception as e:
115
+ background_tasks.add_task(cleanup_files, [temp_vid, temp_aud]) # Cleanup on error
116
+ raise HTTPException(status_code=500, detail=str(e))