legco_ai_assistant/backend/app/routers/youtube.py

84 lines
2.6 KiB
Python

import logging
import time
from functools import lru_cache
from fastapi import APIRouter, HTTPException
from app.models.youtube import YouTubeExtractRequest, YouTubeStreamResponse, StreamFormat
logger = logging.getLogger(__name__)
router = APIRouter(tags=["youtube"])
@lru_cache
def _get_youtube_service():
from app.core.config import get_settings
from app.services.youtube_service import YouTubeService
s = get_settings()
return YouTubeService(timeout=s.yt_dlp_timeout, cache_ttl=s.yt_dlp_cache_ttl)
@router.post("/youtube/extract", response_model=YouTubeStreamResponse)
async def extract_youtube_stream(req: YouTubeExtractRequest):
from app.core.config import get_settings
settings = get_settings()
if not settings.youtube_proxy_enabled:
raise HTTPException(status_code=503, detail="YouTube proxy is disabled")
service = _get_youtube_service()
started = time.monotonic()
logger.info("youtube-extract-started url=%s", req.url)
try:
data = await service.extract_streams(req.url)
except Exception as e:
logger.error("youtube-extract-failed url=%s error=%s", req.url, e)
raise HTTPException(status_code=500, detail=str(e))
if data.get("error"):
logger.warning(
"youtube-extract-error url=%s error=%s duration=%.1fs",
req.url,
data["error"],
time.monotonic() - started,
)
return YouTubeStreamResponse(
video_id=data.get("video_id", ""),
title=data.get("title", ""),
error=data["error"],
)
formats = [
StreamFormat(
format_id=f.get("format_id", ""),
url=f.get("url", ""),
resolution=f.get("resolution"),
is_audio_only=f.get("acodec", "none") != "none" and f.get("vcodec", "none") == "none",
is_video_only=f.get("vcodec", "none") != "none" and f.get("acodec", "none") == "none",
codec=f.get("vcodec") or f.get("acodec"),
)
for f in data.get("formats", [])
]
logger.info(
"youtube-extract-completed url=%s video_id=%s is_live=%s fmt_count=%d duration=%.1fs",
req.url,
data["video_id"],
data["is_live"],
len(formats),
time.monotonic() - started,
)
return YouTubeStreamResponse(
video_id=data["video_id"],
title=data["title"],
is_live=data["is_live"],
is_upcoming=data["is_upcoming"],
video_proxy_url=data.get("video_proxy_url"),
audio_proxy_url=data.get("audio_proxy_url"),
thumbnail_url=data.get("thumbnail_url"),
formats=formats,
)