qopscribe/telegram_bot/handlers/audio_handler.py

125 lines
4.4 KiB
Python
Raw 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
from functools import partial
from aiogram import types, Dispatcher, F
import ffmpeg
import logging
logging.basicConfig(
filename="/shared_storage/bot_log.txt",
level=logging.DEBUG,
format="%(asctime)s - %(levelname)s - %(message)s"
)
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
if not os.path.exists(storage_path):
logging.error(f"❌ storage_path ({storage_path}) не существует!")
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)
if not os.path.exists(temp_destination):
logging.error(f"❌ Файл {temp_destination} не был загружен!")
else:
logging.error(f"✅ Файл {temp_destination} был загружен!")
wav_filename = f"{file_uuid}.wav"
wav_destination = os.path.join(storage_path, wav_filename)
convert_to_wav(temp_destination, wav_destination)
if not os.path.exists(wav_destination):
logging.error(f"❌ WAV-файл {wav_destination} не был создан!")
else:
logging.error(f"✅ WAV-файл успешно создан: {wav_destination}")
os.remove(temp_destination)
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
}
await redis_service.publish_task(task_data)
await message.reply("Your message has been received, converted to WAV, and queued for processing.\nWaiting for transcription...")
text = await redis_service.wait_for_text(
user_id=message.from_user.id,
chat_id=message.chat.id,
message_id=message.message_id
)
if text:
await message.reply(f"Transcription result:\n{text}")
else:
await message.reply("Sorry, transcription result was not received within the timeout.")
def convert_to_wav1(input_file: str, output_file: str):
"""
Конвертирует любой аудио/видеофайл в .wav с частотой 16kHz, 1 канал (моно).
"""
try:
ffmpeg.input(input_file).output(
output_file,
format="wav",
acodec="pcm_s16le",
ac=1,
ar="16000"
).run(overwrite_output=True)
except Exception as e:
print(f"Error converting {input_file} to WAV: {e}")
def convert_to_wav(input_file: str, output_file: str):
"""
Конвертирует любой аудиофайл в WAV с частотой 16kHz, 1 канал (моно).
Логирует ошибки FFmpeg.
"""
try:
logging.error(f"🔄 Конвертация: {input_file} -> {output_file}")
command = [
"ffmpeg", "-y", "-i", input_file,
"-ar", "16000", "-ac", "1", "-c:a", "pcm_s16le",
output_file
]
result = subprocess.run(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if result.returncode != 0:
logging.error(f"❌ Ошибка FFmpeg:\n{result.stderr.decode()}")
else:
logging.error(f"✅ FFmpeg успешно создал файл {output_file}")
except Exception as e:
logging.error(f"❌ Исключение при конвертации {input_file}: {e}")
def register_audio_handlers(dp: Dispatcher, redis_service, storage_path: str):
# Оборачиваем callback для передачи дополнительных аргументов
handler_callback = partial(handle_voice_and_video, redis_service=redis_service, storage_path=storage_path)
# Регистрируем хэндлер с фильтром по content_type
dp.message.register(handler_callback, F.content_type.in_({types.ContentType.VOICE, types.ContentType.VIDEO_NOTE}))