@sergise

Как сделать чтоб бот отправлял сообщения, во время обработки видео?

У меня есть такой код:
Нажатие на кнопку:
@dp.callback_query_handler(lambda call: "uniq-video" in call.data)
async def handle_uniq_video_callback(call):
    await bot.answer_callback_query(callback_query_id=call.id)

    # Запрос пользователя на отправку видео
    await bot.send_message(call.message.chat.id, "Пожалуйста, отправьте видео для уникализации")
    await AddRequisites.waiting_for_video.set()

Получение видеофайла:
@dp.message_handler(content_types=types.ContentTypes.VIDEO, state=AddRequisites.waiting_for_video)
async def save_and_process_video(message: types.Message, state: FSMContext):
    video_file_id = message.video.file_id
    video_file = await bot.get_file(video_file_id)
    video_path = video_file.file_path
    new_video_path = f"saved_videos/{message.chat.id}.mp4"  # Путь для сохранения видео

    progress_message = await bot.send_message(message.chat.id, "Загрузка и сохранение видео...")
    await bot.download_file(video_path, new_video_path)

    queue[message.from_user.id] = len(queue) + 1
    await send_queue_position(message.from_user.id, progress_message.message_id)

    async with semaphore:
        unique_video_path = await apply_unique_filters(new_video_path, message.chat.id, progress_message.message_id)
    
        with open(unique_video_path, 'rb') as unique_video, open("path_to_unique_video.mp4", 'rb') as video_with_logo:
        caption = "↪️ Уникализировано с помощью — @sqwoztraff_bot"
        await bot.send_video(message.chat.id, unique_video, caption=caption)
        await bot.send_video(message.chat.id, video_with_logo, caption=caption)
    await bot.delete_message(message.chat.id, progress_message.message_id)
    del queue[message.from_user.id]
    await state.finish()

Обновление сообщения с очередью:
async def send_queue_position(user_id, message_id):
    position = queue.get(user_id)
    if position is not None:
        total_users = len(queue)
        await bot.edit_message_text(f"Ваша позиция в очереди {position} из {total_users}", user_id, message_id)  # Send initial progress message

async def process_queue(user_id, message_id):
    while True:
        for user_id in list(queue.keys()):
            await send_queue_position(user_id)
        await asyncio.sleep(60)

Сама обработка видео:
async def apply_unique_filters(video_path, chat_id, message_id):
    cap = cv2.VideoCapture(video_path)

    total_frames = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
    processed_frames = 0

    await bot.edit_message_text("Обработка видео: 0% (0 из " + str(total_frames) + " кадров)", chat_id=chat_id, message_id=message_id) 

    exposure_increase = 0  
    contrast_decrease = 0  

    unique_video_path = "path_to_unique_video.mp4"

    input_clip = VideoFileClip(video_path)
    audio_clip = input_clip.audio
    modified_frames = []
    while cap.isOpened():
        ret, frame = cap.read()
        if not ret:
            break

        corrected_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)

        corrected_frame[:, :, 0] = np.clip(corrected_frame[:, :, 0] * 1.1, 0, 255) 
        corrected_frame[:, :, 1] = np.clip(corrected_frame[:, :, 1] * 1.1, 0, 255) 
        corrected_frame[:, :, 2] = np.clip(corrected_frame[:, :, 2] * 0.9, 0, 255) 

        corrected_frame = cv2.convertScaleAbs(corrected_frame, alpha=0.8, beta=10) 

        gray_noise = np.random.normal(0, 5, corrected_frame.shape[:2])  
        noise = np.stack((gray_noise, gray_noise, gray_noise), axis=-1)

        noisy_frame = np.uint8(np.clip(corrected_frame + noise, 0, 255)) 

        modified_frames.append(noisy_frame)


        processed_frames += 1
        progress_percent = int(processed_frames / total_frames * 100)
        
        if progress_percent % 5 == 0:
            await bot.edit_message_text(f"[1/3] Обработка видео: {progress_percent}% ({processed_frames} из {total_frames} кадров)", chat_id=chat_id, message_id=message_id)

    modified_clip = ImageSequenceClip(modified_frames, fps=30)
    final_clip = modified_clip.set_audio(audio_clip)
    for i, frame in enumerate(final_clip.iter_frames()):
        progress_percent = int((i + 1) / len(modified_frames) * 100)
        if progress_percent % 15 == 0 or i == len(modified_frames) - 1:
            await bot.edit_message_text(f"[2/3] Сохранение видео: {progress_percent}% ({i + 1} из {len(modified_frames)} кадров)", chat_id=chat_id, message_id=message_id)
    progress_sec = int(len(modified_frames) / 12)
    progress_sec2 = int(len(modified_frames) / 9)
    await bot.edit_message_text(f"[3/3] Идет рендеринг ~{progress_sec}-{progress_sec2} сек", chat_id=chat_id, message_id=message_id)
    final_clip.write_videofile(unique_video_path, threads=4, codec="libx264", audio_codec="aac", logger=None)

    cap.release()

    video = VideoFileClip(unique_video_path)


    image_path = "logo.png"
    image = ImageClip(image_path).set_duration(video.duration).resize(height=100)  

    result = CompositeVideoClip([video, image.set_position(('center', 'bottom'))]) 
    result2 = result.subclip(0, result.duration - 4 / video.fps)
    result2.write_videofile("path_to_unique_video_text.mp4", threads=4, logger=None)

    cap.release()

    await bot.edit_message_text("Обработка видео завершена. Отправка результата...", chat_id=chat_id, message_id=message_id)

    return "path_to_unique_video_text.mp4"


На данный момент, когда бот обрабатывает видео, он не отправляет никому ответы, уже два дня пытаюсь решить проблему...
aiogram, moviepy
  • Вопрос задан
  • 11525 просмотров
Решения вопроса 1
fenrir1121
@fenrir1121
Начни с документации
Асинхронность применима только для IO-bound задач.
Обработка видео это CPU-bound задача, пока она происходит она блокирует цикл событий. Необходимо ее выносить в отдельный процесс с использованием multiprocessing
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы
25 нояб. 2024, в 02:45
2000 руб./за проект
24 нояб. 2024, в 23:46
20000 руб./за проект