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) |