from fastapi import FastAPI, HTTPException, Query, Depends from fastapi.middleware.cors import CORSMiddleware from typing import List import os from sqlalchemy.orm import Session from models import Base, Video from schemas import VideoCreate, VideoInDB from database import engine, get_db from video_scanner import scan_video_directory from fastapi.responses import FileResponse import json # Create database tables Base.metadata.create_all(bind=engine) app = FastAPI(title="Video Organization API", version="0.1.0") # Add CORS middleware app.add_middleware( CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) # In-memory storage for video paths (in a real app, this would be in a database) video_paths = [] @app.get("/") def read_root(): return {"message": "Welcome to Video Organization API"} @app.post("/video-paths/") def add_video_path(path: str = Query(...)): """ Add a video path to the library """ if not os.path.exists(path): raise HTTPException(status_code=404, detail="Path does not exist") if path not in video_paths: video_paths.append(path) return {"message": f"Path {path} added successfully", "paths": video_paths} else: return {"message": f"Path {path} already exists", "paths": video_paths} @app.get("/video-paths/") def get_video_paths(): """ Get all video paths in the library """ return {"paths": video_paths} @app.delete("/video-paths/") def delete_video_path(path: str = Query(...)): """ Delete a video path from the library """ if path in video_paths: video_paths.remove(path) return {"message": f"Path {path} removed successfully", "paths": video_paths} else: raise HTTPException(status_code=404, detail="Path not found") @app.post("/scan-videos/") def scan_videos(db: Session = Depends(get_db)): """ Scan all video paths and save the videos found to the database """ all_videos = [] for path in video_paths: try: videos = scan_video_directory(path) all_videos.extend(videos) except FileNotFoundError as e: raise HTTPException(status_code=404, detail=str(e)) added_count = 0 for video_data in all_videos: existing_video = db.query(Video).filter(Video.path == video_data['path']).first() if not existing_video: video = Video(**video_data) db.add(video) added_count += 1 db.commit() return {"message": f"Scan complete. Added {added_count} new videos.", "count": added_count} @app.get("/videos/", response_model=List[VideoInDB]) def get_videos(db: Session = Depends(get_db), search: str = Query(None)): """ Get all videos in the library, optionally filtered by search query """ query = db.query(Video) if search: query = query.filter( (Video.title.ilike(f"%{search}%")) | (Video.path.ilike(f"%{search}%")) ) videos = query.all() return videos @app.delete("/videos/{video_id}") def delete_video(video_id: int, db: Session = Depends(get_db)): """ Delete a video from the library by its ID """ video = db.query(Video).filter(Video.id == video_id).first() if not video: raise HTTPException(status_code=404, detail="Video not found") db.delete(video) db.commit() return {"message": f"Video with ID {video_id} deleted successfully"} @app.get("/videos/{video_id}/stream") def stream_video(video_id: int, db: Session = Depends(get_db)): """ Stream a video file by its ID """ print(f"Attempting to stream video with ID: {video_id}") # Log video = db.query(Video).filter(Video.id == video_id).first() if not video: print(f"Video with ID {video_id} not found in database.") # Log raise HTTPException(status_code=404, detail="Video not found") if not os.path.exists(video.path): print(f"Video file not found on server: {video.path}") # Log raise HTTPException(status_code=404, detail="Video file not found on server") print(f"Streaming video from path: {video.path}") # Log return FileResponse(video.path, media_type="video/mp4") if __name__ == "__main__": import uvicorn uvicorn.run(app, host="0.0.0.0", port=8000)