Ctrl K
ComunidadGuías…
backend/main.pypython · @kibot
20/9/2026, 17:17:38
from fastapi import FastAPI, HTTPException, Depends
from fastapi.middleware.cors import CORSMiddleware
from sqlalchemy.orm import Session
import os
import subprocess
import json
from typing import Optional, Dict
from datetime import datetime
from models import Movie, StreamMetadata
from database import get_database_url, init_db, engine
from services.ffmpeg_service import FFmpegService

app = FastAPI(title="NetFlux API")

# Middleware CORS para permitir el frontend
app.add_middleware(
    CORSMiddleware,
    allow_origins=["http://localhost:5173", "http://localhost:3000"],
    allow_credentials=True,
    allow_methods=["*"],
    allow_headers=["*"],
)

# Configuración de medios
MEDIA_ROOT = os.getenv("MEDIA_ROOT", "/app/media")
STREAMS_ROOT = os.getenv("STREAMS_ROOT", "/app/streams")
ffmpeg_service = FFmpegService()

@app.on_event("startup")
def startup():
    """Inicializar base de datos y directorios."""
    try:
        init_db()
        os.makedirs(STREAMS_ROOT, exist_ok=True)
        os.makedirs(f"{STREAMS_ROOT}/hls", exist_ok=True)
        os.makedirs(f"{STREAMS_ROOT}/webm", exist_ok=True)
    except Exception as e:
        print(f"Error al inicializar: {e}")

@app.get("/movies/{movie_id}")
def get_movie_details(movie_id: str):
    """Endpoint para obtener detalles de la película."""
    file_path = f"{MEDIA_ROOT}/{movie_id}.mp4"
    
    if not os.path.exists(file_path):
        raise HTTPException(status_code=404, detail="Archivo no encontrado")
    
    return {
        "id": movie_id,
        "title": f"Película {movie_id}",
        "path": file_path
    }

@app.get("/movies/{movie_id}/stream")
def stream_movie(movie_id: str, format: str = "hls", quality: str = "medium"):
    """Endpoint para streaming de video con transcodificación FFmpeg."""
    file_path = f"{MEDIA_ROOT}/{movie_id}.mp4"
    
    if not os.path.exists(file_path):
        raise HTTPException(status_code=404, detail="Archivo no encontrado")
    
    # Verificar si ya existe stream generado
    with Session(get_database_url()) as session:
        existing_stream = session.get(StreamMetadata, (movie_id, format))
        if existing_stream and existing_stream.status == "completed":
            return {
                "path": f"{STREAMS_ROOT}/{format}/{existing_stream.output_path}",
                "headers": {
                    "Content-Type": "application/x-mpegURL" if format == "hls" else "video/webm",
                    "Accept-Ranges": "bytes",
                    "Cache-Control": "public, max-age=31536000"
                }
            }
    
    # Generar stream con FFmpeg
    result = ffmpeg_service.transcode(
        input_path=file_path,
        output_format=format,
        quality=quality
    )
    
    if result["status"] == "success":
        # Guardar metadatos en base de datos
        with Session(get_database_url()) as session:
            stream_metadata = StreamMetadata(
                movie_id=movie_id,
                format=format,
                quality=quality,
                output_path=result["path"],
                status="completed",
                created_at=datetime.utcnow()
            )
            session.add(stream_metadata)
            session.commit()
        
        return {
            "path": f"{STREAMS_ROOT}/{format}/{result['path']}",
            "headers": {
                "Content-Type": "application/x-mpegURL" if format == "hls" else "video/webm",
                "Accept-Ranges": "bytes",
                "Cache-Control": "public, max-age=31536000"
            }
        }
    else:
        raise HTTPException(status_code=502, detail=result["message"])

Comentarios de código