Skip to main content
Glama
youtube.py5.38 kB
""" Herramientas para interactuar con YouTube (obtención de transcripciones). """ import re from typing import Optional from urllib.parse import parse_qs, urlparse from fastmcp import FastMCP from youtube_transcript_api import YouTubeTranscriptApi from youtube_transcript_api.formatters import TextFormatter def extract_video_id(url: str) -> str: """ Extrae el ID de un video de YouTube desde diferentes formatos de URL. """ # Patrones comunes de URL de YouTube patterns = [ r"(?:v=|\/)([0-9A-Za-z_-]{11}).*", r"(?:youtu\.be\/)([0-9A-Za-z_-]{11})", r"(?:embed\/)([0-9A-Za-z_-]{11})", ] # Intentar parsear URL estándar primero parsed_url = urlparse(url) if parsed_url.hostname in ("www.youtube.com", "youtube.com"): if parsed_url.path == "/watch": params = parse_qs(parsed_url.query) if "v" in params: return params["v"][0] if parsed_url.path.startswith("/shorts/"): return parsed_url.path.split("/shorts/")[1] # Intentar con regex para otros casos (youtu.be, embeds, etc) for pattern in patterns: match = re.search(pattern, url) if match: return match.group(1) # Si la entrada ya parece un ID (11 chars) if len(url) == 11 and re.match(r"^[0-9A-Za-z_-]{11}$", url): return url return "" def get_transcript_text(url: str, language: Optional[str] = None) -> str: """ Obtiene la transcripción de un video de YouTube. Args: url: URL del video de YouTube o ID del video. language: Código del idioma preferido. Si es None, intenta detectar el idioma original o usa el generadado automáticamente. Returns: El texto completo de la transcripción o un mensaje de error. """ video_id = extract_video_id(url) if not video_id: return ( "❌ Error: No se pudo extraer un ID de video válido " "de la URL proporcionada." ) try: # Instanciar la API api = YouTubeTranscriptApi() # Obtener lista de transcripciones disponibles transcript_list = api.list(video_id) target_transcript = None if language: # Si se especificó un idioma, intentar encontrarlo (manual o generado) try: target_transcript = transcript_list.find_transcript([language]) except Exception: # Si falla, intentar traducirlo try: # Buscar cualquiera y traducir # (Esto es simplificado, idealmente buscaríamos el mejor origen) # Por ahora fallamos al catch general si no existe el idioma directo pass except Exception: pass else: # Lógica "Auto": Priorizar manual en idioma cualquiera, o generado. # Normalmente la lista viene con manuales primero o podemos iterar. # 1. Buscar manuales (is_generated=False) for t in transcript_list: if not t.is_generated: target_transcript = t break # 2. Si no hay manual, usar el primero (que será generado) if not target_transcript: # Iterar para tomar el primero disponible. # transcript_list es iterable for t in transcript_list: target_transcript = t break if not target_transcript: # Fallback a lógica antigua de "fetch" con defaults si algo falló arriba # aunque transcript_list debería lanzar error si está vacío. languages = ["es", "en"] if not language else [language] target_transcript = transcript_list.find_transcript(languages) # Hacer fetch de la transcripción seleccionada transcript_data = target_transcript.fetch() # Formatear a texto plano formatter = TextFormatter() text_formatted = formatter.format_transcript(transcript_data) metadata = ( f"Idioma: {target_transcript.language} ({target_transcript.language_code})" ) if target_transcript.is_generated: metadata += " [Autogenerado]" else: metadata += " [Manual]" return ( f"✅ Transcripción obtenida para video {video_id}\n" f"ℹ️ {metadata}:\n\n{text_formatted}" ) except Exception as e: return f"❌ Error al obtener transcripción para {video_id}: {e}" def register_youtube_tools(mcp: FastMCP) -> None: """ Registra las herramientas de YouTube en el servidor MCP. """ @mcp.tool() def get_youtube_transcript(url: str, language: Optional[str] = None) -> str: """ Obtiene la transcripción de un video de YouTube. Args: url: URL del video de YouTube o ID del video. language: Código del idioma opcional (ej: 'es', 'en'). Si se omite, busca subtítulos manuales en el idioma original, o falla al autogenerado del video. Returns: El texto completo de la transcripción o un mensaje de error. """ return get_transcript_text(url, language)

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/Vasallo94/obsidian-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server