feat(backend): add SaluteSpeech to task dispatch (ENGINE_MAP + elif branch)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Daniil
2026-04-04 00:08:27 +03:00
parent 2c9c11fa17
commit c40aeab8be
2 changed files with 29 additions and 11 deletions
+2 -2
View File
@@ -83,7 +83,7 @@ class TranscriptionGenerateRequest(Schema):
file_key: str = Field(..., description="Storage key of the input file") file_key: str = Field(..., description="Storage key of the input file")
project_id: UUID | None = Field(default=None, description="Associated project ID") project_id: UUID | None = Field(default=None, description="Associated project ID")
engine: Literal["whisper", "google"] = Field( engine: Literal["whisper", "google", "salutespeech"] = Field(
default="whisper", description="Transcription engine to use" default="whisper", description="Transcription engine to use"
) )
language: str | None = Field(default=None, description="Language code (e.g., 'en')") language: str | None = Field(default=None, description="Language code (e.g., 'en')")
@@ -164,5 +164,5 @@ class TaskWebhookEvent(Schema):
) )
) )
if not has_update: if not has_update:
raise ValueError("Webhook event must include at least one update field.") raise ValueError("Событие вебхука должно содержать хотя бы одно обновляемое поле.")
return self return self
+27 -9
View File
@@ -88,14 +88,15 @@ ERROR_UNKNOWN_ENGINE = "Неизвестный движок транскрипц
ENGINE_MAP: dict[str, str] = { ENGINE_MAP: dict[str, str] = {
"whisper": "LOCAL_WHISPER", "whisper": "LOCAL_WHISPER",
"google": "GOOGLE_SPEECH_CLOUD", "google": "GOOGLE_SPEECH_CLOUD",
"salutespeech": "SALUTE_SPEECH",
} }
MESSAGE_STARTING = "Starting" MESSAGE_STARTING = "Запуск"
MESSAGE_COMPLETED = "Completed" MESSAGE_COMPLETED = "Завершено"
MESSAGE_PROBING_MEDIA = "Probing media" MESSAGE_PROBING_MEDIA = "Анализ медиафайла"
MESSAGE_PROCESSING = "Processing" MESSAGE_PROCESSING = "Обработка"
MESSAGE_CONVERTING = "Converting" MESSAGE_CONVERTING = "Конвертация"
MESSAGE_RENDERING_CAPTIONS = "Rendering captions" MESSAGE_RENDERING_CAPTIONS = "Рендеринг субтитров"
MESSAGE_CANCELLED = "Отменено пользователем" MESSAGE_CANCELLED = "Отменено пользователем"
MESSAGE_EXTRACTING_FRAMES = "Извлечение кадров" MESSAGE_EXTRACTING_FRAMES = "Извлечение кадров"
MESSAGE_UPLOADING_FRAMES = "Загрузка кадров" MESSAGE_UPLOADING_FRAMES = "Загрузка кадров"
@@ -560,7 +561,7 @@ def media_convert_actor(
try: try:
if output_format.lower() != "mp4": if output_format.lower() != "mp4":
raise ValueError(f"Unsupported format: {output_format}") raise ValueError(f"Неподдерживаемый формат: {output_format}")
storage = _get_storage_service() storage = _get_storage_service()
_send_webhook_event( _send_webhook_event(
@@ -612,6 +613,7 @@ def transcription_generate_actor(
"""Generate transcription from audio/video file.""" """Generate transcription from audio/video file."""
from cpv3.modules.transcription.service import ( from cpv3.modules.transcription.service import (
transcribe_with_google_speech, transcribe_with_google_speech,
transcribe_with_salute_speech,
transcribe_with_whisper, transcribe_with_whisper,
) )
@@ -698,6 +700,22 @@ def transcription_generate_actor(
storage, file_key=file_key, language_codes=language_codes storage, file_key=file_key, language_codes=language_codes
) )
) )
elif engine == "salutespeech":
audio_stream = next(
(s for s in probe.streams if s.codec_type == "audio"), None
)
sr = int(audio_stream.sample_rate) if audio_stream and audio_stream.sample_rate else 16000
document = _run_async(
transcribe_with_salute_speech(
storage,
file_key=file_key,
language=language,
model=model,
sample_rate=sr,
job_id=job_uuid,
on_progress=_on_whisper_progress,
)
)
else: else:
raise ValueError(ERROR_UNKNOWN_ENGINE.format(engine=engine)) raise ValueError(ERROR_UNKNOWN_ENGINE.format(engine=engine))
@@ -1159,7 +1177,7 @@ class TaskService:
"""Apply a webhook event to the job and store a job event record.""" """Apply a webhook event to the job and store a job event record."""
job = await self._job_repo.get_by_id(job_id) job = await self._job_repo.get_by_id(job_id)
if job is None: if job is None:
raise ValueError(f"Job {job_id} not found") raise ValueError(f"Задача {job_id} не найдена")
if job.status in (JOB_STATUS_DONE, JOB_STATUS_FAILED, JOB_STATUS_CANCELLED): if job.status in (JOB_STATUS_DONE, JOB_STATUS_FAILED, JOB_STATUS_CANCELLED):
logger.info("Ignoring webhook for terminal job %s (status=%s)", job_id, job.status) logger.info("Ignoring webhook for terminal job %s (status=%s)", job_id, job.status)
@@ -1644,7 +1662,7 @@ class TaskService:
transcription_repo = TranscriptionRepository(self._session) transcription_repo = TranscriptionRepository(self._session)
transcription = await transcription_repo.get_by_id(request.transcription_id) transcription = await transcription_repo.get_by_id(request.transcription_id)
if transcription is None: if transcription is None:
raise ValueError(f"Transcription {request.transcription_id} not found") raise ValueError(f"Транскрипция {request.transcription_id} не найдена")
user_folder = get_user_folder(requester) user_folder = get_user_folder(requester)
resolved_folder = ( resolved_folder = (