music / app.py
FarelDeveloper's picture
Update app.py
f483bb7 verified
Raw History Blame Contribute Delete
3.86 kB
from fastapi import FastAPI, Query
from fastapi.responses import JSONResponse
from fastapi.middleware.cors import CORSMiddleware
from ytmusicapi import YTMusic
import yt_dlp
app = FastAPI(
title="Farel Music API + Audio Link",
description="Backend API Farel Music menggunakan Docker di HF Spaces",
version="2.0.0"
)
# Aktifkan CORS
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# --- PERBAIKAN DI SINI: Menyisipkan User-Agent agar tidak diblokir SSL/EOF oleh YouTube ---
# Kita buat object YTMusic kosong, lalu isi headers-nya secara manual sebelum dipakai.
try:
yt = YTMusic()
# Ganti headers bawaan dengan user-agent browser modern
yt.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
"Accept": "*/*",
"Accept-Language": "en-US,en;q=0.9",
"Content-Type": "application/json",
"X-Goog-AuthUser": "0",
"Origin": "https://music.youtube.com"
}
except Exception as e:
yt = None
print(f"Gagal menginisialisasi YTMusic: {e}")
def get_direct_audio_url(video_id: str):
ydl_opts = {
'format': 'bestaudio/best',
'quiet': True,
'no_warnings': True,
'nocheckcertificate': True,
'preferredcodec': 'm4a',
# Tambahkan juga HTTP Headers untuk yt-dlp agar tidak diblokir saat ambil audio
'http_headers': {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.9',
}
}
youtube_url = f"https://www.youtube.com/watch?v={video_id}"
try:
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(youtube_url, download=False)
return info.get('url')
except Exception as e:
print(f"Gagal ekstraksi audio: {e}")
return None
@app.get("/")
def home():
return {
"status": "Online via Docker",
"message": "Farel Music API Ready!",
"endpoint": "/search?q=judul_lagu"
}
@app.get("/search")
def search_music(q: str = Query(..., description="Kata kunci pencarian lagu")):
if not q.strip():
return JSONResponse(status_code=400, content={"error": "Query tidak boleh kosong."})
if yt is None:
return JSONResponse(status_code=500, content={"error": "YTMusic API bermasalah saat inisialisasi."})
try:
# Melakukan pencarian
results = yt.search(q, filter="songs")
formatted_results = []
for item in results[:5]:
video_id = item.get('videoId')
if not video_id:
continue
audio_url = get_direct_audio_url(video_id)
thumbnails = item.get('thumbnails', [])
thumbnail_url = thumbnails[-1]['url'] if thumbnails else None
artists = [a['name'] for a in item.get('artists', [])]
formatted_results.append({
"id": video_id,
"title": item.get('title'),
"artists": artists,
"album": item.get('album', {}).get('name', 'Single'),
"duration": item.get('duration'),
"thumbnail": thumbnail_url,
"youtube_url": f"https://www.youtube.com/watch?v={video_id}",
"audio_url": audio_url
})
return {
"query": q,
"total_results": len(formatted_results),
"results": formatted_results
}
except Exception as e:
return JSONResponse(status_code=500, content={"error": f"Terjadi kesalahan: {str(e)}"})