File size: 3,862 Bytes
4d60d14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f483bb7
 
4d60d14
 
f483bb7
 
 
 
 
 
 
 
 
4d60d14
 
 
 
 
 
 
 
 
 
f483bb7
 
 
 
 
 
 
4d60d14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f483bb7
4d60d14
 
f483bb7
4d60d14
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
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)}"})