import os
import yt_dlp
import logging
from typing import Dict, Any, Tuple, Optional
from youtube_mcp_server.config import Config
logger = logging.getLogger("youtube-mcp-server")
class DownloadService:
def get_metadata(self, url: str) -> Optional[Dict[str, Any]]:
"""Fetches metadata without downloading."""
logger.info(f"Fetching video metadata for: {url}")
ydl_opts = {
'quiet': True,
'no_warnings': True,
'extract_flat': False,
}
try:
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=False)
return {
"id": info.get("id"),
"title": info.get("title"),
"description": info.get("description"),
"uploader": info.get("uploader"),
"upload_date": info.get("upload_date"),
"view_count": info.get("view_count"), # Info tool keeps view_count
"like_count": info.get("like_count"),
"duration": info.get("duration"),
"thumbnail": info.get("thumbnail"),
"webpage_url": info.get("webpage_url"),
"tags": info.get("tags"),
"categories": info.get("categories"),
}
except Exception as e:
logger.error(f"Error fetching metadata: {e}")
raise e
def get_video_id(self, url: str) -> Optional[str]:
"""Extracts video ID quickly."""
try:
with yt_dlp.YoutubeDL({'quiet': True}) as ydl:
info = ydl.extract_info(url, download=False, process=False)
return info.get('id')
except Exception as e:
logger.warning(f"Could not extract ID: {e}")
return None
def download_audio(self, url: str, output_dir: str) -> Tuple[str, Dict[str, Any]]:
"""Downloads audio as MP3."""
logger.info(f"Downloading audio from {url}...")
ydl_opts = {
'format': 'bestaudio/best',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '192',
}],
'outtmpl': os.path.join(output_dir, '%(id)s.%(ext)s'),
'quiet': True,
}
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
info = ydl.extract_info(url, download=True)
filename = ydl.prepare_filename(info)
base, _ = os.path.splitext(filename)
final_path = base + ".mp3"
logger.info(f"Audio downloaded to {final_path}")
return final_path, info