qopscribe/telegram_bot/handlers/audio_handler.py

125 lines
4.4 KiB
Python
Raw Normal View History

2025-02-23 14:12:10 +01:00
import os
2025-02-23 18:11:12 +01:00
import subprocess
2025-02-23 14:12:10 +01:00
import uuid
from functools import partial
from aiogram import types, Dispatcher, F
2025-02-23 15:24:56 +01:00
import ffmpeg
2025-02-23 14:12:10 +01:00
2025-02-23 18:00:28 +01:00
import logging
logging.basicConfig(
filename="/shared_storage/bot_log.txt",
level=logging.DEBUG,
format="%(asctime)s - %(levelname)s - %(message)s"
)
2025-02-23 14:12:10 +01:00
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
2025-02-23 18:00:28 +01:00
if not os.path.exists(storage_path):
logging.error(f"❌ storage_path ({storage_path}) не существует!")
2025-02-23 14:12:10 +01:00
file = await message.bot.get_file(file_id)
file_path = file.file_path
file_uuid = str(uuid.uuid4())
2025-02-23 15:24:56 +01:00
original_filename = os.path.basename(file_path)
temp_filename = f"{file_uuid}_{original_filename}"
2025-02-23 14:12:10 +01:00
os.makedirs(storage_path, exist_ok=True)
2025-02-23 15:24:56 +01:00
temp_destination = os.path.join(storage_path, temp_filename)
2025-02-23 14:12:10 +01:00
2025-02-23 15:24:56 +01:00
await message.bot.download_file(file_path, temp_destination)
2025-02-23 17:53:26 +01:00
if not os.path.exists(temp_destination):
2025-02-23 18:00:28 +01:00
logging.error(f"❌ Файл {temp_destination} не был загружен!")
2025-02-23 17:53:26 +01:00
else:
2025-02-23 18:00:28 +01:00
logging.error(f"✅ Файл {temp_destination} был загружен!")
2025-02-23 17:53:26 +01:00
2025-02-23 15:24:56 +01:00
wav_filename = f"{file_uuid}.wav"
wav_destination = os.path.join(storage_path, wav_filename)
convert_to_wav(temp_destination, wav_destination)
2025-02-23 17:53:26 +01:00
if not os.path.exists(wav_destination):
2025-02-23 18:00:28 +01:00
logging.error(f"❌ WAV-файл {wav_destination} не был создан!")
2025-02-23 17:53:26 +01:00
else:
2025-02-23 18:00:28 +01:00
logging.error(f"✅ WAV-файл успешно создан: {wav_destination}")
2025-02-23 17:53:26 +01:00
2025-02-23 15:24:56 +01:00
os.remove(temp_destination)
2025-02-23 14:12:10 +01:00
task_data = {
"uuid": file_uuid,
2025-02-23 15:24:56 +01:00
"file_path": wav_destination,
2025-02-23 14:12:10 +01:00
"user_id": message.from_user.id,
2025-02-23 15:24:56 +01:00
"chat_id": message.chat.id,
"message_id": message.message_id
2025-02-23 14:12:10 +01:00
}
2025-02-23 15:24:56 +01:00
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.")
2025-02-23 18:11:12 +01:00
def convert_to_wav1(input_file: str, output_file: str):
2025-02-23 15:24:56 +01:00
"""
Конвертирует любой аудио/видеофайл в .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}")
2025-02-23 14:12:10 +01:00
2025-02-23 18:11:12 +01:00
def convert_to_wav(input_file: str, output_file: str):
"""
Конвертирует любой аудиофайл в WAV с частотой 16kHz, 1 канал (моно).
Логирует ошибки FFmpeg.
"""
try:
2025-02-23 18:11:36 +01:00
logging.error(f"🔄 Конвертация: {input_file} -> {output_file}")
2025-02-23 18:11:12 +01:00
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:
2025-02-23 18:11:36 +01:00
logging.error(f"✅ FFmpeg успешно создал файл {output_file}")
2025-02-23 18:11:12 +01:00
except Exception as e:
logging.error(f"❌ Исключение при конвертации {input_file}: {e}")
2025-02-23 14:12:10 +01:00
def register_audio_handlers(dp: Dispatcher, redis_service, storage_path: str):
2025-02-23 15:24:56 +01:00
# Оборачиваем callback для передачи дополнительных аргументов
2025-02-23 14:12:10 +01:00
handler_callback = partial(handle_voice_and_video, redis_service=redis_service, storage_path=storage_path)
2025-02-23 15:24:56 +01:00
# Регистрируем хэндлер с фильтром по content_type
dp.message.register(handler_callback, F.content_type.in_({types.ContentType.VOICE, types.ContentType.VIDEO_NOTE}))