from typing import Optional from fastapi import FastAPI, HTTPException, Query from youtube_transcript_api import YouTubeTranscriptApi from youtube_transcript_api.formatters import SRTFormatter from youtube_transcript_api._errors import TranscriptsDisabled, NoTranscriptFound from yt_dlp import YoutubeDL app = FastAPI( title="YouTube Transcript & Metadata API", version="1.0.0" ) def extract_video_id(url: str) -> str: import re match = re.search(r"(?:v=|youtu\.be/)([A-Za-z0-9_-]{11})", url) if not match: raise ValueError("URL inválida do YouTube") return match.group(1) @app.get("/get-transcript") def get_transcript( url: Optional[str] = Query(None, description="URL completa do vídeo"), videoId: Optional[str] = Query(None, alias="videoId", description="ID do vídeo no YouTube") ): if not url and not videoId: raise HTTPException(status_code=400, detail="Informe 'url' ou 'videoId'") if url: try: video_id = extract_video_id(url) except ValueError as e: raise HTTPException(status_code=400, detail=str(e)) else: video_id = videoId try: ytt_api = YouTubeTranscriptApi() result = ytt_api.fetch(video_id, languages=['pt']) formatter = SRTFormatter() if not result: raise NoTranscriptFound("Nenhuma transcrição encontrada para este vídeo") except TranscriptsDisabled: raise HTTPException(status_code=404, error="Transcrição desativada para este vídeo") except NoTranscriptFound: raise HTTPException(status_code=404, error="Nenhuma transcrição encontrada") except Exception as e: raise HTTPException(status_code=500, error=f"Erro ao obter transcrição: {e}") return { "video_id": video_id, "transcript": formatter.format_transcript(result), } @app.get("/get-video-metadata") def get_video_metadata( url: Optional[str] = Query(None, description="URL completa do vídeo"), videoId: Optional[str] = Query(None, alias="videoId", description="ID do vídeo no YouTube") ): if not url and not videoId: raise HTTPException(status_code=400, detail="Informe 'url' ou 'videoId'") if url: target = url else: target = f"https://www.youtube.com/watch?v={videoId}" ydl_opts = { "quiet": True, "skip_download": True, "nocheckcertificate": True, "restrictfilenames": True, "simulate": True, "forcejson": True, } try: with YoutubeDL(ydl_opts) as ydl: info = ydl.extract_info(target, download=False) except Exception as e: raise HTTPException(status_code=500, detail=f"Erro ao extrair metadata: {e}") return info