From c97b3e3ec3cec882ddf383a798fc3de4080f2f97d5067efa5c28f0840e5ec6e2 Mon Sep 17 00:00:00 2001 From: AidarKC Date: Wed, 3 Jun 2026 14:49:03 +0400 Subject: [PATCH] =?UTF-8?q?=D0=A1=D0=BD=D0=B8=D0=BC=D0=BE=D0=BA=20=D1=81?= =?UTF-8?q?=D0=BE=D1=81=D1=82=D0=BE=D1=8F=D0=BD=D0=B8=D1=8F=20=D0=B4=D0=BE?= =?UTF-8?q?=20=D0=BF=D0=B5=D1=80=D0=B5=D0=BD=D0=BE=D1=81=D0=B0=20=D1=81?= =?UTF-8?q?=D0=B5=D1=80=D0=B2=D0=B5=D1=80=D0=BD=D0=BE=D0=B3=D0=BE=20UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...03_0040_диагностика_больших_voice_audio.md | 14 +++++++ SHiNE-agent-bot-coder/README.md | 1 + SHiNE-agent-bot-coder/py_bot_service.py | 39 ++++++++++++------- VERSION.properties | 4 +- doc/instructions/ui-deploy-targets.md | 19 --------- doc/mvp-web-push-notes/README.md | 18 --------- 6 files changed, 41 insertions(+), 54 deletions(-) create mode 100644 Dev_Docs/Pending_Features/2026-06-03_0040_диагностика_больших_voice_audio.md delete mode 100644 doc/instructions/ui-deploy-targets.md delete mode 100644 doc/mvp-web-push-notes/README.md diff --git a/Dev_Docs/Pending_Features/2026-06-03_0040_диагностика_больших_voice_audio.md b/Dev_Docs/Pending_Features/2026-06-03_0040_диагностика_больших_voice_audio.md new file mode 100644 index 0000000..8cea128 --- /dev/null +++ b/Dev_Docs/Pending_Features/2026-06-03_0040_диагностика_больших_voice_audio.md @@ -0,0 +1,14 @@ +# Диагностика больших voice/audio в Telegram-боте + +- краткое описание фичи: + - Бот при большом voice/audio больше не отказывается заранее по метаданным Telegram. Теперь он сначала сообщает, что пробует скачать файл, затем отдельно сообщает об успешном скачивании и только после этого переходит к подготовке аудио и распознаванию через OpenAI. +- что именно проверять: + - Отправить в бота большой `voice` или `audio`, который раньше попадал под ранний отказ. + - Проверить, что сначала приходит сообщение о попытке скачать большой файл. + - Проверить два сценария: + - скачивание удалось: бот пишет об успешной загрузке и продолжает распознавание; + - скачивание не удалось: бот пишет именно о неудачном скачивании из Telegram, без ложной привязки к ошибке OpenAI. +- ожидаемый результат: + - Пользователь видит понятную поэтапную диагностику: попытка скачивания, результат скачивания и только потом следующий этап обработки. +- статус: + - pending diff --git a/SHiNE-agent-bot-coder/README.md b/SHiNE-agent-bot-coder/README.md index 62a8204..6f32f8d 100644 --- a/SHiNE-agent-bot-coder/README.md +++ b/SHiNE-agent-bot-coder/README.md @@ -57,6 +57,7 @@ python3 SHiNE-agent-bot-coder/py_bot_service.py --selftest-codex "Ответь ## Длинные voice/audio - Если аудио короткое, бот отправляет его в OpenAI как раньше. - Если аудио большое или длинное, бот локально пережимает его через `ffmpeg`, при необходимости режет на куски и распознаёт последовательно. +- Если Telegram заранее сообщает большой размер файла, бот больше не отказывается сразу: сначала явно пишет, что пробует скачать файл, затем отдельно сообщает, удалось ли скачивание, и только после успешной загрузки переходит к подготовке аудио и OpenAI. - Для очень больших файлов упираемся не только в OpenAI, но и в лимит обычного облачного Telegram Bot API на скачивание файла ботом. Для таких случаев нужно использовать локальный `telegram-bot-api` сервер и указать его через `TELEGRAM_API_BASE_URL`. ## Запуск как systemd-сервис diff --git a/SHiNE-agent-bot-coder/py_bot_service.py b/SHiNE-agent-bot-coder/py_bot_service.py index a8798ed..e2bfb95 100644 --- a/SHiNE-agent-bot-coder/py_bot_service.py +++ b/SHiNE-agent-bot-coder/py_bot_service.py @@ -18,7 +18,7 @@ import time import traceback import uuid from pathlib import Path -from typing import Any +from typing import Any, Callable from urllib import error, request DEFAULT_ALLOWED_PLAYERS = ",".join([ @@ -1509,7 +1509,10 @@ class ShinePyBotService: try: if job.get("type") == "voice": self._safe_send(chat_id, f"#{job_num}: распознаю голосовое...", reply_to=message_id) - recognized = self._transcribe_voice_job(job) + recognized = self._transcribe_voice_job( + job, + status_cb=lambda note: self._safe_send(chat_id, f"#{job_num}: {note}", reply_to=message_id), + ) job["text"] = recognized self._append_history(history_path, "voice_transcription", {"jobId": job_id, "jobNum": job_num, "text": recognized}) preview = recognized.strip() @@ -2206,7 +2209,12 @@ class ShinePyBotService: raise VoiceReplyError("OpenAI вернул пустой аудиофайл.") return audio - def _transcribe_voice_job(self, job: dict[str, Any]) -> str: + def _transcribe_voice_job( + self, + job: dict[str, Any], + *, + status_cb: Callable[[str], Any] | None = None, + ) -> str: if not self.cfg.openai_api_key: raise VoiceTranscriptionError( "не настроен ключ OpenAI для распознавания.", @@ -2225,17 +2233,11 @@ class ShinePyBotService: media_type = (job.get("telegram_media_type") or "voice").strip() duration_seconds = int(job.get("telegram_duration_seconds") or 0) telegram_file_size = int(job.get("telegram_file_size") or 0) - if self._telegram_cloud_download_is_likely_too_big(telegram_file_size): - limit_mb = self._bytes_to_mb(20 * 1024 * 1024) - actual_mb = self._bytes_to_mb(telegram_file_size) - raise VoiceTranscriptionError( - ( - f"Telegram не даст этому боту скачать такой файл через обычный Bot API " - f"(примерно {actual_mb} MB при лимите около {limit_mb} MB). " - f"Для очень длинных аудио нужен локальный `telegram-bot-api` сервер или другой способ доставки файла." - ), - stage="telegram_get_file_too_big", - retryable=False, + file_looks_big_for_cloud = self._telegram_cloud_download_is_likely_too_big(telegram_file_size) + if file_looks_big_for_cloud and status_cb is not None: + status_cb( + "файл большой, всё равно пробую скачать его из Telegram. " + f"Предварительный размер около {self._bytes_to_mb(telegram_file_size)} MB." ) started_at = time.time() print(f"[py-bot] transcribe start job={job_id} num={job_num} media={media_type}", flush=True) @@ -2244,6 +2246,11 @@ class ShinePyBotService: f"[py-bot] transcribe downloaded job={job_id} filename={filename} size={len(file_bytes)} bytes", flush=True, ) + if file_looks_big_for_cloud and status_cb is not None: + status_cb( + "скачивание из Telegram прошло успешно. " + f"Фактический размер около {self._bytes_to_mb(len(file_bytes))} MB, дальше готовлю аудио и отправляю в OpenAI." + ) prepared_parts = self._prepare_audio_parts_for_transcription( file_bytes, filename, @@ -2290,7 +2297,9 @@ class ShinePyBotService: detail = str(e) if "file is too big" in detail.lower(): raise VoiceTranscriptionError( - "Telegram считает файл слишком большим для скачивания через текущий Bot API. Для такого аудио нужен локальный `telegram-bot-api` сервер или другой способ передать файл боту.", + "Файл большой: я попробовал скачать его через текущий Telegram Bot API, " + "но Telegram не дал это сделать. Для такого аудио нужен локальный `telegram-bot-api` " + "сервер или другой способ передать файл боту.", stage="telegram_get_file_too_big", retryable=False, detail=detail, diff --git a/VERSION.properties b/VERSION.properties index 02e7c92..ccc54f1 100644 --- a/VERSION.properties +++ b/VERSION.properties @@ -1,2 +1,2 @@ -client.version=1.2.115 -server.version=1.2.107 +client.version=1.2.116 +server.version=1.2.108 diff --git a/doc/instructions/ui-deploy-targets.md b/doc/instructions/ui-deploy-targets.md deleted file mode 100644 index 300ece3..0000000 --- a/doc/instructions/ui-deploy-targets.md +++ /dev/null @@ -1,19 +0,0 @@ -# UI deploy - -Актуальный UI-деплой выполняется одной командой: - -```bash -./gradlew deployUI -``` - -По умолчанию: - -- хост: `player@93.170.12.154` -- домен: `https://shineup.me` -- путь: `/home/player/SHiNE/SHiNE-UI` - -Переопределение при необходимости: - -```bash -REMOTE_HOST=player@93.170.12.154 REMOTE_BASE_DIR=/home/player/SHiNE bash deploy_shine-PWA.sh -``` diff --git a/doc/mvp-web-push-notes/README.md b/doc/mvp-web-push-notes/README.md deleted file mode 100644 index d6c1680..0000000 --- a/doc/mvp-web-push-notes/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# MVP notes: Web Push - -## Временное поведение (сделано для тестового стенда) - -- Клиент отправляет push-подписку на сервер при каждом запуске после авторизации, даже если подписка не изменилась. -- Причина: на тестовом сервере/после переустановки БД запись о токене может пропасть, а клиент этого не узнает. - -## Что доработать для production - -- Вернуть режим "отправлять только при изменении подписки" как основной. -- Добавить безопасный механизм ресинхронизации: -- Вариант 1: периодическая принудительная отправка (например, 1 раз в N дней). -- Вариант 2: endpoint на сервере "есть ли подписка", и отправка только при отсутствии/рассинхроне. -- В логах разделить обычную отправку и принудительную, чтобы видеть лишний трафик. -- Добавить e2e-тесты сценариев: -- Переустановка сервера (потеря токена в БД). -- Смена браузерной подписки. -- Повторный запуск клиента без изменений.