Initial Animatrix import

This commit is contained in:
Sagnik
2026-04-17 19:11:57 +05:30
commit c7994d17a9
60 changed files with 8516 additions and 0 deletions

View File

@@ -0,0 +1,118 @@
import subprocess
import uuid
from pathlib import Path
from typing import Optional
import aiofiles
from fastapi import UploadFile
from PIL import Image
from app.core.config import settings
class LocalStorageService:
def __init__(self, root: str):
self.root = Path(root)
self.root.mkdir(parents=True, exist_ok=True)
async def save_upload(self, upload: UploadFile, subfolder: str) -> tuple[str, int]:
dest_dir = self.root / subfolder
dest_dir.mkdir(parents=True, exist_ok=True)
ext = Path(upload.filename or "file").suffix
filename = f"{uuid.uuid4()}{ext}"
dest_path = dest_dir / filename
content = await upload.read()
async with aiofiles.open(dest_path, "wb") as handle:
await handle.write(content)
return str(dest_path.relative_to(self.root)).replace("\\", "/"), len(content)
def save_bytes(self, data: bytes, subfolder: str, filename: str) -> str:
dest_dir = self.root / subfolder
dest_dir.mkdir(parents=True, exist_ok=True)
dest_path = dest_dir / filename
with open(dest_path, "wb") as handle:
handle.write(data)
return str(dest_path.relative_to(self.root)).replace("\\", "/")
def absolute_path(self, relative_path: str) -> Path:
return self.root / relative_path
def delete_relative_path(self, relative_path: Optional[str]) -> None:
if not relative_path:
return
abs_path = self.absolute_path(relative_path)
try:
if abs_path.exists():
abs_path.unlink()
except Exception:
pass
def generate_thumbnail(self, image_path: str, thumb_subfolder: str) -> Optional[str]:
try:
abs_path = self.absolute_path(image_path)
with Image.open(abs_path) as img:
img.thumbnail((400, 400))
thumb_dir = self.root / thumb_subfolder
thumb_dir.mkdir(parents=True, exist_ok=True)
thumb_name = f"thumb_{Path(image_path).stem}.jpg"
thumb_path = thumb_dir / thumb_name
img.convert("RGB").save(thumb_path, "JPEG", quality=80)
return str(thumb_path.relative_to(self.root)).replace("\\", "/")
except Exception:
return None
def generate_video_thumbnail(self, video_path: str, thumb_subfolder: str) -> Optional[str]:
abs_path = self.absolute_path(video_path)
thumb_dir = self.root / thumb_subfolder
thumb_dir.mkdir(parents=True, exist_ok=True)
thumb_name = f"thumb_{Path(video_path).stem}.jpg"
thumb_path = thumb_dir / thumb_name
try:
subprocess.run(
[
"ffmpeg",
"-y",
"-i",
str(abs_path),
"-ss",
"00:00:00.500",
"-vframes",
"1",
str(thumb_path),
],
capture_output=True,
timeout=30,
check=False,
)
if thumb_path.exists():
return str(thumb_path.relative_to(self.root)).replace("\\", "/")
except Exception:
return None
return None
def detect_duration_seconds(self, relative_path: str) -> Optional[float]:
abs_path = self.absolute_path(relative_path)
try:
result = subprocess.run(
[
"ffprobe",
"-v",
"error",
"-show_entries",
"format=duration",
"-of",
"default=noprint_wrappers=1:nokey=1",
str(abs_path),
],
capture_output=True,
text=True,
timeout=20,
check=True,
)
return round(float(result.stdout.strip()), 3)
except Exception:
return None
asset_storage = LocalStorageService(settings.ASSET_STORAGE_ROOT)
output_storage = LocalStorageService(settings.OUTPUT_STORAGE_ROOT)