diff --git a/py/routes/api_routes.py b/py/routes/api_routes.py index 76ca11a2..a35bf2b2 100644 --- a/py/routes/api_routes.py +++ b/py/routes/api_routes.py @@ -17,7 +17,8 @@ from ..services.settings_manager import settings import asyncio from .update_routes import UpdateRoutes from ..services.recipe_scanner import RecipeScanner -from ..utils.constants import PREVIEW_EXTENSIONS +from ..utils.constants import PREVIEW_EXTENSIONS, CARD_PREVIEW_WIDTH +from ..utils.exif_utils import ExifUtils logger = logging.getLogger(__name__) @@ -302,18 +303,29 @@ class ApiRoutes: async def _save_preview_file(self, model_path: str, preview_data: bytes, content_type: str) -> str: """Save preview file and return its path""" - # Determine file extension based on content type - if content_type.startswith('video/'): - extension = '.preview.mp4' - else: - extension = '.preview.png' - base_name = os.path.splitext(os.path.basename(model_path))[0] folder = os.path.dirname(model_path) + + # Determine if content is video or image + if content_type.startswith('video/'): + # For videos, keep original format and use .mp4 extension + extension = '.mp4' + optimized_data = preview_data + else: + # For images, optimize and convert to WebP + optimized_data, _ = ExifUtils.optimize_image( + image_data=preview_data, + target_width=CARD_PREVIEW_WIDTH, + format='webp', + quality=85, + preserve_metadata=True + ) + extension = '.webp' # Use .webp without .preview part + preview_path = os.path.join(folder, base_name + extension).replace(os.sep, '/') with open(preview_path, 'wb') as f: - f.write(preview_data) + f.write(optimized_data) return preview_path diff --git a/py/services/model_scanner.py b/py/services/model_scanner.py index d9134b2a..04d0cb2a 100644 --- a/py/services/model_scanner.py +++ b/py/services/model_scanner.py @@ -537,4 +537,19 @@ class ModelScanner: return None except Exception as e: logger.error(f"Error getting model info by name: {e}", exc_info=True) - return None \ No newline at end of file + return None + + async def update_preview_in_cache(self, file_path: str, preview_url: str) -> bool: + """Update preview URL in cache for a specific lora + + Args: + file_path: The file path of the lora to update + preview_url: The new preview URL + + Returns: + bool: True if the update was successful, False if cache doesn't exist or lora wasn't found + """ + if self._cache is None: + return False + + return await self._cache.update_preview_url(file_path, preview_url) \ No newline at end of file diff --git a/static/js/components/LoraCard.js b/static/js/components/LoraCard.js index c4baee23..2e0b9bd0 100644 --- a/static/js/components/LoraCard.js +++ b/static/js/components/LoraCard.js @@ -3,6 +3,7 @@ import { state } from '../state/index.js'; import { showLoraModal } from './loraModal/index.js'; import { bulkManager } from '../managers/BulkManager.js'; import { NSFW_LEVELS } from '../utils/constants.js'; +import { replacePreview } from '../api/loraApi.js' export function createLoraCard(lora) { const card = document.createElement('div');