qopscribe/telegram_bot/handlers/audio_handler.py

90 lines
3.4 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import os
import subprocess
import uuid
import logging
from functools import partial
from aiogram import types, Dispatcher, F
async def handle_voice_and_video(message: types.Message, redis_service, storage_path: str):
file_id = None
if message.content_type == types.ContentType.VOICE:
file_id = message.voice.file_id
elif message.content_type == types.ContentType.VIDEO_NOTE:
file_id = message.video_note.file_id
if not file_id:
return
file = await message.bot.get_file(file_id)
file_path = file.file_path
file_uuid = str(uuid.uuid4())
original_filename = os.path.basename(file_path)
temp_filename = f"{file_uuid}_{original_filename}"
os.makedirs(storage_path, exist_ok=True)
temp_destination = os.path.join(storage_path, temp_filename)
await message.bot.download_file(file_path, temp_destination)
wav_filename = f"{file_uuid}.wav"
wav_destination = os.path.join(storage_path, wav_filename)
convert_to_wav(temp_destination, wav_destination)
os.remove(temp_destination)
processing_msg = await message.reply("Обрабатываю аудио, пожалуйста, подождите...")
task_data = {
"uuid": file_uuid,
"file_path": wav_destination,
"user_id": message.from_user.id,
"chat_id": message.chat.id,
"message_id": message.message_id
}
logging.info(f"Отправляю задачу в Redis: {task_data}")
await redis_service.publish_task(task_data)
logging.info(f"Ожидаю результат для сообщения {message.message_id}")
text = await redis_service.wait_for_text(
user_id=message.from_user.id,
chat_id=message.chat.id,
message_id=message.message_id
)
os.remove(wav_destination)
await processing_msg.delete()
if text:
logging.info(f"Получен результат для сообщения {message.message_id}, длина текста: {len(text)}")
await send_long_message(message, text)
else:
logging.warning(f"Не получен результат для сообщения {message.message_id}")
await message.reply("К сожалению, не удалось получить результат обработки в отведенное время.")
async def send_long_message(message: types.Message, text: str):
"""Отправляет длинный текст, разбивая его на части по 4096 символов"""
chunk_size = 4096
for i in range(0, len(text), chunk_size):
await message.reply(text[i : i + chunk_size])
def convert_to_wav(input_file: str, output_file: str):
"""
Конвертирует любой аудиофайл в WAV с частотой 16kHz, 1 канал (моно).
Логирует ошибки FFmpeg.
"""
command = [
"ffmpeg", "-y", "-i", input_file,
"-ar", "16000", "-ac", "1", "-c:a", "pcm_s16le",
output_file
]
subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
def register_audio_handlers(dp: Dispatcher, redis_service, storage_path: str):
handler_callback = partial(handle_voice_and_video, redis_service=redis_service, storage_path=storage_path)
dp.message.register(handler_callback, F.content_type.in_({types.ContentType.VOICE, types.ContentType.VIDEO_NOTE}))