54 lines
1.5 KiB
Python
54 lines
1.5 KiB
Python
import subprocess
|
|
from pathlib import Path
|
|
from PIL import Image
|
|
from app.config import THUMBNAIL_DIR
|
|
|
|
THUMB_SIZE = (400, 400)
|
|
|
|
|
|
def thumbnail_path(media_id: int) -> Path:
|
|
return THUMBNAIL_DIR / f"{media_id}.jpg"
|
|
|
|
|
|
def generate_image_thumbnail(src: Path, dest: Path) -> None:
|
|
with Image.open(src) as img:
|
|
img.thumbnail(THUMB_SIZE)
|
|
img = img.convert("RGB")
|
|
img.save(dest, "JPEG", quality=85)
|
|
|
|
|
|
def generate_video_thumbnail(src: Path, dest: Path) -> None:
|
|
# Extract frame at 10% of duration
|
|
subprocess.run(
|
|
[
|
|
"ffprobe", "-v", "error", "-show_entries", "format=duration",
|
|
"-of", "default=noprint_wrappers=1:nokey=1", str(src),
|
|
],
|
|
capture_output=True, text=True, check=False,
|
|
)
|
|
subprocess.run(
|
|
[
|
|
"ffmpeg", "-y", "-ss", "00:00:05", "-i", str(src),
|
|
"-vframes", "1", "-vf", f"scale={THUMB_SIZE[0]}:-1",
|
|
str(dest),
|
|
],
|
|
capture_output=True, check=False,
|
|
)
|
|
|
|
|
|
def get_or_create_thumbnail(media_id: int, abs_path: str, media_type: str) -> Path | None:
|
|
dest = thumbnail_path(media_id)
|
|
if dest.exists():
|
|
return dest
|
|
src = Path(abs_path)
|
|
if not src.exists():
|
|
return None
|
|
try:
|
|
if media_type == "image":
|
|
generate_image_thumbnail(src, dest)
|
|
else:
|
|
generate_video_thumbnail(src, dest)
|
|
return dest if dest.exists() else None
|
|
except Exception:
|
|
return None
|