Spaces:
Running
Running
| # -*- coding: utf-8 -*- | |
| import torch | |
| import gradio as gr | |
| import yt_dlp as youtube_dl | |
| from transformers import pipeline | |
| from transformers.pipelines.audio_utils import ffmpeg_read | |
| from huggingface_hub import login | |
| import tempfile | |
| import uuid | |
| import os | |
| import time | |
| import yt_dlp | |
| # --- Конфигурация --- | |
| HF_TOKEN = os.getenv("HF_ACCESS_TOKEN") | |
| MODEL_NAME = "artyomboyko/whisper-small-ru-v4" | |
| BATCH_SIZE = 8 | |
| # FILE_LIMIT_MB = 1000 | |
| # --- Инициализация --- | |
| try: | |
| if HF_TOKEN: | |
| login(token=HF_TOKEN) | |
| print("Успешный вход в Hugging Face Hub.") | |
| else: | |
| print("HF_ACCESS_TOKEN не найден. Запуск в оффлайн-режиме или с публичными моделями.") | |
| except Exception as e: | |
| print(f"Не удалось войти в Hugging Face Hub: {e}") | |
| # Определение устройства для вычислений (GPU или CPU) | |
| device = 0 if torch.cuda.is_available() else "cpu" | |
| if device == 0: | |
| print("GPU доступен, вычисления будут производиться на GPU.") | |
| else: | |
| print("GPU не доступен, вычисления будут производиться на CPU.") | |
| # Загрузка модели распознавания речи | |
| try: | |
| pipe = pipeline( | |
| task="automatic-speech-recognition", | |
| model=MODEL_NAME, | |
| chunk_length_s=30, | |
| device=device, | |
| ) | |
| print(f"Модель {MODEL_NAME} успешно загружена.") | |
| except Exception as e: | |
| print(f"Ошибка при загрузке модели {MODEL_NAME}: {e}") | |
| exit() | |
| # --- Функции --- | |
| def transcribe(filepath, task): | |
| """ | |
| Транскрибирует аудиофайл с помощью загруженной модели Whisper. | |
| Args: | |
| filepath (str): Путь к аудиофайлу. | |
| task (str): Задача для модели ("transcribe" или "translate"). | |
| Returns: | |
| str: Распознанный текст. | |
| """ | |
| if filepath is None: | |
| # Используем gr.Warning вместо gr.Error для неблокирующего уведомления | |
| gr.Warning("Аудиофайл не предоставлен! Пожалуйста, загрузите или запишите аудио перед отправкой запроса.") | |
| return "Ошибка: Аудиофайл не предоставлен." # Возвращаем строку ошибки | |
| print(f"Начало транскрибации файла: {filepath}, Задача: {task}") | |
| try: | |
| result = pipe(filepath, batch_size=BATCH_SIZE, generate_kwargs={"task": task}, return_timestamps=True) | |
| text = result["text"] | |
| print("Транскрибация завершена успешно.") | |
| return text | |
| except Exception as e: | |
| print(f"Ошибка во время транскрибации: {e}") | |
| # Используем gr.Error для вывода серьезной ошибки | |
| raise gr.Error(f"Произошла ошибка при обработке аудио: {e}") | |
| def download_audio(video_url: str, download_folder: str) -> str: | |
| if not video_url: | |
| gr.Warning("URL YouTube видео не предоставлен.") | |
| return None | |
| unique_filename = f"{uuid.uuid4()}.mp3" | |
| audio_filepath = os.path.join(download_folder, unique_filename) | |
| ydl_opts = { | |
| 'format': 'bestaudio/best', | |
| 'outtmpl': audio_filepath, | |
| 'postprocessors': [{ | |
| 'key': 'FFmpegExtractAudio', | |
| 'preferredcodec': 'mp3', | |
| 'preferredquality': '192', | |
| }], | |
| 'quiet': True, | |
| } | |
| try: | |
| os.makedirs(download_folder, exist_ok=True) | |
| with yt_dlp.YoutubeDL(ydl_opts) as ydl: | |
| ydl.download([video_url]) | |
| except Exception as e: | |
| print(f"Не удалось скачать аудио с YouTube: {e}") | |
| gr.Error(f"Не удалось скачать аудио с YouTube: {e}", duration=5) | |
| audio_filepath = None | |
| return audio_filepath | |
| def transcribe_youtube(youtube_url, task): | |
| """ | |
| Скачивает аудио с YouTube и транскрибирует его. | |
| Args: | |
| youtube_url (str): URL YouTube видео. | |
| task (str): Задача для модели ("transcribe" или "translate"). | |
| Returns: | |
| str: Распознанный текст или сообщение об ошибке. | |
| """ | |
| audio_filepath = download_audio(youtube_url, "./downloded_audio") | |
| if audio_filepath: | |
| try: | |
| transcription = transcribe(audio_filepath, task) | |
| # Удаляем временный файл и директорию после транскрибации | |
| os.remove(audio_filepath) | |
| os.rmdir(os.path.dirname(audio_filepath)) | |
| return transcription | |
| except Exception as e: | |
| # Удаляем временный файл и директорию даже если транскрибация не удалась | |
| if os.path.exists(audio_filepath): | |
| os.remove(audio_filepath) | |
| os.rmdir(os.path.dirname(audio_filepath)) | |
| raise e # Перебрасываем ошибку для обработки Gradio | |
| else: | |
| return "Не удалось скачать аудио." | |
| # --- Создание интерфейса Gradio --- | |
| with gr.Blocks(theme=gr.themes.Default(primary_hue="blue", secondary_hue="neutral")) as demo: | |
| gr.Markdown( | |
| f""" | |
| # Whisper: Транскрибация аудио | |
| Транскрибируйте длинные аудиозаписи (с микрофона или из файла) одним нажатием кнопки! | |
| Демо использует модель OpenAI Whisper [{MODEL_NAME}](https://huggingface.co/{MODEL_NAME}) | |
| через библиотеку 🤗 Transformers для распознавания речи. | |
| """ | |
| ) | |
| # Создание вкладок | |
| with gr.Tabs(): | |
| # Вкладка 1: Транскрибация с микрофона | |
| with gr.TabItem("Микрофон"): | |
| with gr.Row(): | |
| mic_input = gr.Audio(sources=["microphone"], type="filepath", label="Запись с микрофона") | |
| task_mic = gr.Radio(["transcribe", "translate"], label="Задача", value="transcribe") | |
| output_mic = gr.Textbox(label="Результат", lines=7) # Увеличили количество строк для текста | |
| mic_button = gr.Button("Транскрибировать с микрофона") | |
| # Вкладка 2: Транскрибация из файла | |
| with gr.TabItem("Аудиофайл"): | |
| with gr.Row(): | |
| file_input = gr.Audio(sources=["upload"], type="filepath", label="Загрузить аудиофайл") | |
| task_file = gr.Radio(["transcribe", "translate"], label="Задача", value="transcribe") | |
| output_file = gr.Textbox(label="Результат", lines=7) | |
| file_button = gr.Button("Транскрибировать файл") | |
| # Вкладка 3: Транскрибация с YouTube URL | |
| with gr.TabItem("YouTube URL"): | |
| with gr.Row(): | |
| url_input = gr.Textbox(label="Введите URL YouTube видео") | |
| task_youtube = gr.Radio(["transcribe", "translate"], label="Задача", value="transcribe") | |
| output_youtube = gr.Textbox(label="Результат", lines=7) | |
| youtube_button = gr.Button("Транскрибировать с YouTube") | |
| # --- Привязка функций к кнопкам --- | |
| # Связываем кнопку "Транскрибировать с микрофона" с функцией transcrib | |
| mic_button.click( | |
| fn=transcribe, | |
| inputs=[mic_input, task_mic], | |
| outputs=output_mic | |
| ) | |
| # Связываем кнопку "Транскрибировать файл" с функцией transcribe | |
| file_button.click( | |
| fn=transcribe, | |
| inputs=[file_input, task_file], | |
| outputs=output_file | |
| ) | |
| # Связываем кнопку "Транскрибировать с YouTube" с функцией transcribe_youtube | |
| youtube_button.click( | |
| fn=transcribe_youtube, | |
| inputs=[url_input, task_youtube], | |
| outputs=output_youtube | |
| ) | |
| # --- Запуск приложения --- | |
| print("Запуск интерфейса Gradio...") | |
| demo.queue().launch(debug=True, share=False) |