diff --git a/backend/app/routers/photos.py b/backend/app/routers/photos.py index 8320370..3d78d6b 100644 --- a/backend/app/routers/photos.py +++ b/backend/app/routers/photos.py @@ -10,9 +10,11 @@ from pydantic import BaseModel from sqlalchemy import select, and_, or_, func, tuple_ from sqlalchemy.ext.asyncio import AsyncSession from sqlalchemy.orm import selectinload +import asyncio import base64 import json import os +import subprocess import logging logger = logging.getLogger(__name__) @@ -842,17 +844,52 @@ async def get_original( ext = Path(photo.filepath).suffix.lower() media_type = _INLINE_MEDIA_TYPES.get(ext, 'application/octet-stream') - file_size = os.path.getsize(photo.filepath) + return _serve_file_with_range( + photo.filepath, + request, + media_type, + download_filename=( + photo.filename if media_type == 'application/octet-stream' else None + ), + ) + +# Cached H.264/MP4 transcodes for /playback. iPhone shoots HEVC Main 10 by +# default and Chrome/Firefox can't decode 10-bit HEVC reliably, so anything +# that isn't already h264 in a web-safe container gets transcoded once and +# served from this directory thereafter. +_VIDEO_CACHE_DIR = Path('/data/video-cache') +_VIDEO_CACHE_DIR.mkdir(parents=True, exist_ok=True) + +# Video codecs that play in