@@ -2,13 +2,13 @@ # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER # This file is distributed under the same license as the PACKAGE package. # FIRST AUTHOR , YEAR. -# +# #, fuzzy msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2026-08-10 11:02+0300\n" +"POT-Creation-Date: 2026-08-11 18:15+0300\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -766,7 +766,8 @@ msgstr "Промпт слишком длинный" msgid "" "Service is currently unavailable due to high demand. Please try again later" msgstr "" -"Сервис временно недоступен из-за высокой нагрузки. Пожалуйста, попробуйте позже" +"Сервис временно недоступен из-за высокой нагрузки. Пожалуйста, попробуйте " +"позже" #: ml_model/exceptions.py:172 msgid "Service is temporarily unavailable. Please try again later" @@ -1097,7 +1098,7 @@ msgstr "Инструкции Моделей" msgid "no model by this id" msgstr "Не найдено моделей по этому ID" -#: ml_model/services/FileService.py:110 +#: ml_model/services/FileService.py:122 #: tools/public_api/views/providers/openai_compatible.py:208 msgid "Voice not found." msgstr "Голос не найден." @@ -1121,6 +1122,14 @@ msgstr "" msgid "Duration cannot be less than 5 seconds" msgstr "Длительность не может быть меньше 5 секунд" +#: ml_model/services/kling.py:83 +msgid "" +"Image aspect ratio is outside the allowed range. Please use an image between " +"1:2.5 and 2.5:1" +msgstr "" +"Соотношение сторон изображения выходит за пределы допустимого диапазона. " +"Используйте изображение с соотношением сторон от 1:2.5 до 2.5:1" + #: ml_model/services/minio_service.py:37 ml_model/services/minio_service.py:55 #: ml_model/services/minio_service.py:63 ml_model/services/minio_service.py:72 msgid "Unknown bucket destination" @@ -5,13 +5,13 @@ from decimal import Decimal from io import BytesIO from typing import Any -import filetype import requests from django.core.files import File - +from django.utils.translation import gettext as _ from messages.models import Message -from ml_model.exceptions import RequestBlocked, GenerationException, FileNotProvided +from ml_model.exceptions import FileNotProvided, InvalidParameterError +from ml_model.services.FileService import ImageFileProcessingService from ml_model.services.base import SimpleService from ml_model.tasks import replicate_run @@ -47,16 +47,24 @@ class Kling(SimpleService): def make(self, input_message: Message, save: bool = True) -> list[Message]: mode = input_message.info.pop('mode', 'standard') duration = input_message.info.get('duration', 5) - if (balance := PaymentPlanSelector(self.store.user).get_current_balance()) < (cost := self.TOKENS_COST[mode] * duration): + if (balance := PaymentPlanSelector(self.store.user).get_current_balance()) < ( + cost := self.TOKENS_COST[mode] * duration + ): raise InsufficientBalance(balance, cost) if not input_message.file: raise FileNotProvided('Image') - callback_data = dict({'prompt': self.translate_prompt(input_message.content), 'mode': mode, **input_message.info}) - kind = filetype.guess(input_message.file.read(20)) - mime = kind.mime if kind else 'application/octet-stream' - input_message.file.seek(0) - image = f'data:{mime};base64,{base64.b64encode(input_message.file.read()).decode("utf-8")}' - input_message.file.close() + callback_data = dict( + {'prompt': self.translate_prompt(input_message.content), 'mode': mode, **input_message.info} + ) + + processor = ImageFileProcessingService(input_message.file) + self._validate_aspect_ratio(processor) + file_bytes = processor.get_bytes(20) + kind = processor.get_kind(file_bytes) + mime = kind.mime + image_bytes = processor.get_bytes() + processor.image.close() + image = f'data:{mime};base64,{base64.b64encode(image_bytes).decode("utf-8")}' callback_data.update({'start_image': image}) start_time = time.time() video = replicate_run('kwaivgi/kling-v2.1', callback_data) @@ -64,3 +72,13 @@ class Kling(SimpleService): self.handle_invoice(input_message.content_object.model, mode=mode, duration=duration) msgs = self.save_results(input_message.content, process_time, video, save) return msgs + + def _validate_aspect_ratio(self, processor: ImageFileProcessingService) -> None: + width, height = processor.get_dimensions(max_pixels=36_000_000) + + if not (0.40 <= width / height <= 2.50): + raise InvalidParameterError( + _( + 'Image aspect ratio is outside the allowed range. Please use an image between 1:2.5 and 2.5:1' + ) + ) \ No newline at end of file