64 lines
2.6 KiB
Python
64 lines
2.6 KiB
Python
from fastapi import APIRouter, HTTPException, Depends
|
|
from fastapi.responses import StreamingResponse
|
|
from backend.services.youtube import YouTubeService
|
|
import requests
|
|
|
|
router = APIRouter()
|
|
|
|
def get_youtube_service():
|
|
return YouTubeService()
|
|
|
|
@router.get("/stream")
|
|
async def stream_audio(id: str, yt: YouTubeService = Depends(get_youtube_service)):
|
|
try:
|
|
data = yt.get_stream_url(id)
|
|
if isinstance(data, dict):
|
|
stream_url = data.get("url")
|
|
headers = data.get("headers", {})
|
|
else:
|
|
# Fallback for old cached string values
|
|
stream_url = data
|
|
headers = {
|
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
|
|
}
|
|
|
|
def iterfile():
|
|
with requests.get(stream_url, headers=headers, stream=True, timeout=10) as r:
|
|
r.raise_for_status()
|
|
for chunk in r.iter_content(chunk_size=64*1024):
|
|
yield chunk
|
|
|
|
return StreamingResponse(iterfile(), media_type="audio/mpeg")
|
|
except Exception as e:
|
|
print(f"Stream Error: {e}")
|
|
# Return detail if it's a request error
|
|
if isinstance(e, requests.exceptions.HTTPError):
|
|
print(f"Upstream Status: {e.response.status_code}")
|
|
raise HTTPException(status_code=500, detail=str(e))
|
|
|
|
@router.get("/download")
|
|
async def download_audio(id: str, title: str = "audio", yt: YouTubeService = Depends(get_youtube_service)):
|
|
try:
|
|
data = yt.get_stream_url(id)
|
|
if isinstance(data, dict):
|
|
stream_url = data.get("url")
|
|
headers = data.get("headers", {})
|
|
else:
|
|
stream_url = data
|
|
headers = {
|
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
|
|
}
|
|
|
|
def iterfile():
|
|
with requests.get(stream_url, headers=headers, stream=True, timeout=10) as r:
|
|
r.raise_for_status()
|
|
for chunk in r.iter_content(chunk_size=1024*1024):
|
|
yield chunk
|
|
|
|
safe_filename = "".join([c for c in title if c.isalnum() or c in (' ', '-', '_')]).strip()
|
|
final_headers = {
|
|
"Content-Disposition": f'attachment; filename="{safe_filename}.mp3"'
|
|
}
|
|
return StreamingResponse(iterfile(), media_type="audio/mpeg", headers=final_headers)
|
|
except Exception as e:
|
|
raise HTTPException(status_code=500, detail=str(e))
|