from fastapi import FastAPI, HTTPException from fastapi.responses import FileResponse from pytube import YouTube from pytube.exceptions import PytubeError import os from typing import Optional app = FastAPI(title="Blogger Video Downloader API", description="An API for bloggers to download YouTube videos with metadata for content creation") @app.get("/download", summary="Download YouTube video") async def download_video( url: str, quality: Optional[str] = "highest", include_thumbnail: Optional[bool] = False ): """ Download a YouTube video with options suitable for bloggers. Parameters: - url: YouTube video URL - quality: Download quality ('highest', 'lowest', 'audio_only') - include_thumbnail: Whether to also download the thumbnail image Returns video metadata and download path. """ try: yt = YouTube(url) # Get appropriate stream based on quality preference if quality == "highest": stream = yt.streams.get_highest_resolution() elif quality == "lowest": stream = yt.streams.get_lowest_resolution() elif quality == "audio_only": stream = yt.streams.get_audio_only() else: raise HTTPException(status_code=400, detail="Invalid quality option. Use 'highest', 'lowest', or 'audio_only'") if not stream: raise HTTPException(status_code=404, detail="No suitable video stream found") # Create a downloads directory if it doesn't exist os.makedirs("downloads", exist_ok=True) # Download video safe_title = "".join(c for c in yt.title if c.isalnum() or c in " -_").rstrip() download_path = stream.download(output_path="downloads", filename=f"{safe_title}.mp4") response_data = { "message": "Video downloaded successfully!", "title": yt.title, "author": yt.author, "length_seconds": yt.length, "views": yt.views, "publish_date": str(yt.publish_date), "keywords": yt.keywords, "description": yt.description[:200] + "..." if yt.description else None, "download_path": download_path, "quality": stream.resolution if hasattr(stream, 'resolution') else "audio", "filesize_mb": round(stream.filesize / (1024 * 1024), 2) } # Download thumbnail if requested if include_thumbnail: thumbnail_path = os.path.join("downloads", f"{safe_title}_thumbnail.jpg") yt.thumbnail_url.download(thumbnail_path) response_data["thumbnail_path"] = thumbnail_path return response_data except PytubeError as e: raise HTTPException(status_code=400, detail=f"YouTube download error: {str(e)}") except Exception as e: raise HTTPException(status_code=500, detail=f"Unexpected error: {str(e)}") @app.get("/get_video/{filename}", response_class=FileResponse) async def get_video(filename: str): """Retrieve a downloaded video file""" file_path = os.path.join("downloads", filename) if not os.path.exists(file_path): raise HTTPException(status_code=404, detail="File not found") return FileResponse(file_path) @app.get("/get_thumbnail/{filename}", response_class=FileResponse) async def get_thumbnail(filename: str): """Retrieve a downloaded thumbnail file""" file_path = os.path.join("downloads", filename) if not os.path.exists(file_path): raise HTTPException(status_code=404, detail="File not found") return FileResponse(file_path)

Comments

Popular posts from this blog