Spaces:
Paused
Paused
| import os | |
| import glob | |
| import time | |
| import subprocess | |
| from fastapi import FastAPI, Query, HTTPException, BackgroundTasks | |
| from fastapi.responses import FileResponse | |
| app = FastAPI( | |
| title="⚡ Studio Engine API", | |
| description="High-speed media acquisition endpoint returning JSON payload.", | |
| version="3.0.0", | |
| docs_url="/", | |
| redoc_url=None | |
| ) | |
| DOWNLOAD_DIR = "downloads" | |
| if not os.path.exists(DOWNLOAD_DIR): | |
| os.makedirs(DOWNLOAD_DIR) | |
| def delete_file_after_delay(file_path: str, delay: int = 300): | |
| """Menghapus file dari folder penyimpanan setelah 5 menit (300 detik)""" | |
| time.sleep(delay) | |
| if os.path.exists(file_path): | |
| try: | |
| os.remove(file_path) | |
| print(f"[Auto-Delete] File hangus berhasil dihapus: {file_path}") | |
| except Exception as e: | |
| print(f"[Auto-Delete] Gagal menghapus file {file_path}: {e}") | |
| def download_mp3( | |
| background_tasks: BackgroundTasks, | |
| url: str = Query(..., description="Target resource web URL (YouTube, TikTok, Instagram, etc.)") | |
| ): | |
| timestamp = int(time.time()) | |
| outtmpl = f"{DOWNLOAD_DIR}/audio_{timestamp}.%(ext)s" | |
| cmd = [ | |
| "yt-dlp", | |
| url, | |
| "-f", "bestaudio/best", | |
| "-o", outtmpl, | |
| "-x", "--audio-format", "mp3", "--audio-quality", "192K", | |
| "--no-playlist", | |
| "--no-warnings", | |
| "--no-check-certificate" | |
| ] | |
| try: | |
| result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) | |
| if result.returncode != 0: | |
| raise Exception(result.stderr) | |
| downloaded_files = glob.glob(f"{DOWNLOAD_DIR}/audio_{timestamp}.mp3") | |
| if not downloaded_files: | |
| downloaded_files = glob.glob(f"{DOWNLOAD_DIR}/*_{timestamp}*") | |
| if not downloaded_files: | |
| raise HTTPException(status_code=500, detail="Gagal menyimpan file audio ke server.") | |
| file_path = downloaded_files[0] | |
| file_name = os.path.basename(file_path) | |
| # Daftarkan background task untuk menghapus file dalam waktu 5 menit | |
| background_tasks.add_task(delete_file_after_delay, file_path, 300) | |
| return { | |
| "status": "success", | |
| "message": "File ready. Links are valid for 5 minutes.", | |
| "file_name": file_name, | |
| "format": "mp3", | |
| "auto_download_url": f"https://fareldevelopers-aio.hf.space/api/get-file/{file_name}?action=download", | |
| "play_in_browser_url": f"https://fareldevelopers-aio.hf.space/api/get-file/{file_name}?action=stream" | |
| } | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=f"Audio Engine Error: {str(e)}") | |
| def download_mp4( | |
| background_tasks: BackgroundTasks, | |
| url: str = Query(..., description="Target resource web URL (YouTube, TikTok, Instagram, etc.)"), | |
| resolution: str = Query("720", description="Resolution specification (Optional). Default: 720") | |
| ): | |
| timestamp = int(time.time()) | |
| outtmpl = f"{DOWNLOAD_DIR}/video_{timestamp}_{resolution}p.%(ext)s" | |
| yt_dlp_format = f"bestvideo[height<={resolution}]+bestaudio/best[height<={resolution}]/best" | |
| cmd = [ | |
| "yt-dlp", | |
| url, | |
| "-f", yt_dlp_format, | |
| "-o", outtmpl, | |
| "--merge-output-format", "mp4", | |
| "--no-playlist", | |
| "--no-warnings", | |
| "--no-check-certificate" | |
| ] | |
| try: | |
| result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) | |
| if result.returncode != 0: | |
| raise Exception(result.stderr) | |
| downloaded_files = glob.glob(f"{DOWNLOAD_DIR}/video_{timestamp}_{resolution}p.mp4") | |
| if not downloaded_files: | |
| downloaded_files = glob.glob(f"{DOWNLOAD_DIR}/*_{timestamp}*") | |
| if not downloaded_files: | |
| raise HTTPException(status_code=500, detail="Gagal menyimpan file video ke server.") | |
| file_path = downloaded_files[0] | |
| file_name = os.path.basename(file_path) | |
| # Daftarkan background task untuk menghapus file dalam waktu 5 minutes | |
| background_tasks.add_task(delete_file_after_delay, file_path, 300) | |
| return { | |
| "status": "success", | |
| "message": "File ready. Links are valid for 5 minutes.", | |
| "file_name": file_name, | |
| "format": "mp4", | |
| "resolution": resolution, | |
| "auto_download_url": f"https://fareldevelopers-aio.hf.space/api/get-file/{file_name}?action=download", | |
| "play_in_browser_url": f"https://fareldevelopers-aio.hf.space/api/get-file/{file_name}?action=stream" | |
| } | |
| except Exception as e: | |
| raise HTTPException(status_code=500, detail=f"Video Engine Error: {str(e)}") | |
| def get_file(file_name: str, action: str = Query("download", description="Options: 'download' or 'stream'")): | |
| """Endpoint core yang melayani file berdasarkan query parameter action""" | |
| file_path = os.path.join(DOWNLOAD_DIR, file_name) | |
| if not os.path.exists(file_path): | |
| raise HTTPException(status_code=404, detail="File tidak ditemukan atau sudah kedaluwarsa (terhapus otomatis setelah 5 menit).") | |
| # Deteksi tipe media berdasarkan extension | |
| media_type = "audio/mpeg" if file_name.endswith(".mp3") else "video/mp4" | |
| if action == "stream": | |
| # Menggunakan inline content disposition agar browser memutar langsung di web | |
| return FileResponse(file_path, media_type=media_type, content_disposition_type="inline") | |
| else: | |
| # Menggunakan attachment content disposition agar browser otomatis mendownload file | |
| return FileResponse(file_path, media_type="application/octet-stream", filename=file_name, content_disposition_type="attachment") |