whisper / app.py
artyomboyko's picture
Update app.py
09bd3ae verified
# -*- 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)