File size: 2,696 Bytes
0121d89
8f895a6
 
0121d89
 
 
 
 
 
 
1a61348
 
 
 
 
 
 
0121d89
 
 
 
1a61348
1ce5c71
0121d89
 
 
 
 
 
1a61348
0121d89
 
 
1a61348
 
0121d89
1a61348
0121d89
 
 
 
1a61348
0121d89
 
 
 
 
 
 
 
1a61348
 
 
0121d89
 
 
 
be5c87b
 
0121d89
091927f
 
 
 
 
 
 
 
be5c87b
0121d89
091927f
be5c87b
0121d89
 
be5c87b
0121d89
 
 
be5c87b
 
 
0121d89
 
 
27ebb91
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
import os
import certifi
os.environ['SSL_CERT_FILE'] = certifi.where()
import yt_dlp
import tempfile
from fastapi import FastAPI, HTTPException
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import FileResponse
from ytmusicapi import YTMusic

# Initialize with a common browser header to avoid 500 errors in datacenters
try:
    ytm = YTMusic()
except Exception as e:
    print(f"Init Error: {e}")
    ytm = None

app = FastAPI()

app.add_middleware(
    CORSMiddleware,
    allow_origins=["*"],
    allow_credentials=False,
    allow_methods=["*"],
    allow_headers=["*"],
)

@app.get("/")
async def root():
    return {"status": "Online", "mode": "HuggingFace"}

@app.get("/search")
async def search(q: str):
    if not ytm:
        return {"error": "YTMusic not initialized"}
    try:
        # We add a try-except here to catch the specific 500 error
        raw_results = ytm.search(q, filter="songs")
        results = []
        for res in raw_results:
            artists = ", ".join([a['name'] for a in res.get('artists', [])])
            thumb = res['thumbnails'][-1]['url'] if res.get('thumbnails') else ""
            results.append({
                "id": res['videoId'],
                "title": res['title'],
                "artist": artists or "Unknown Artist",
                "thumbnail": thumb
            })
        return results
    except Exception as e:
        # This will show the real error in your Hugging Face Logs tab
        print(f"Search Crash: {e}")
        return {"error": str(e), "tip": "Check Hugging Face logs"}

@app.get("/get_audio")
async def get_audio(id: str):
    video_url = f"https://www.youtube.com/watch?v={id}"
    
    # These extra arguments trick YouTube into seeing a phone browser, not a server
    ydl_opts = {
    'format': 'bestaudio/best',
    'nocheckcertificate': True,  # This stops the protocol error you're seeing
    'quiet': True,
    'no_warnings': True,
    'extractor_args': {
        'youtube': {
            'player_client': ['android'], # Android is often more stable than iOS for this
            'skip': ['dash', 'hls']
        }
    }
}
    
    with yt_dlp.YoutubeDL(ydl_opts) as ydl:
        try:
            # Adding a retry loop for stability in the cloud
            info = ydl.extract_info(video_url, download=False)
            return {"url": info['url']}
        except Exception as e:
            print(f"Extraction failed: {e}")
            # If it still fails, we send the error back to see it on the phone
            return {"error": str(e), "status": "YouTube blocked this request"}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=7860)