File size: 3,412 Bytes
44a34b5
be2f1d0
13fe256
 
 
44a34b5
310e379
13fe256
d211e5d
13fe256
be2f1d0
13fe256
42a6ff1
13fe256
 
 
42a6ff1
13fe256
 
 
 
 
 
 
 
 
 
 
 
 
 
cfd126b
be2f1d0
42a6ff1
 
13fe256
 
 
be2f1d0
13fe256
 
 
be2f1d0
 
73c7b68
13fe256
 
 
 
eb89ff6
13fe256
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2ca0afe
eb89ff6
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import os
import tempfile
import datetime

import gradio as gr
import torch
import whisperx
from whisperx.diarize import DiarizationPipeline

# Определяем устройство: CUDA если доступна, иначе CPU
device = "cuda" if torch.cuda.is_available() else "cpu"

# Загружаем модель WhisperX с compute_type="int8" для ускорения на CPU
asr_model = whisperx.load_model(
    "small",
    device=device,
    compute_type="int8"  # изменено на int8 для ускорения
)

# Загружаем модель выравнивания для русского
align_model, metadata = whisperx.load_align_model(
    language_code="ru",
    device=device
)

# Инициализируем пайплайн диаризации (Pyannote) с токеном HF
hf_token = os.getenv("HUGGINGFACEHUB_API_TOKEN", None)
diarization_pipeline = DiarizationPipeline(
    use_auth_token=hf_token,
    device=device
)

def transcribe_with_diarization(audio_path):
    # 1) ASR без детекции языка (принудительно ru), с batch_size=16
    result = asr_model.transcribe(audio_path, language="ru", batch_size=16)

    # 2) Выравнивание субтитров по аудио
    aligned = whisperx.align(
        result["segments"],
        align_model,
        metadata,
        audio_path,
        device
    )

    # 3) Диаризация
    diarization = diarization_pipeline(audio_path)

    # 4) Объединяем текстовые сегменты и спикеров
    merged = whisperx.assign_word_speakers(diarization, aligned)["segments"]

    # 5) Формируем текст для вывода
    lines = []
    for seg in merged:
        spk = seg.get("speaker", "Speaker")
        txt = seg.get("text", "").strip()
        lines.append(f"[{spk}] {txt}")
    return "\n".join(lines)

def export_to_txt(text):
    # Сохраняем результат во временный файл и возвращаем путь
    timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = f"transcript_{timestamp}.txt"
    path = os.path.join(tempfile.gettempdir(), filename)
    with open(path, "w", encoding="utf-8") as f:
        f.write(text)
    return path

# Собираем интерфейс Gradio
app = gr.Blocks(title="🎙️ DiarAI: Транскрибация и диаризация (RU)")

with app:
    gr.Markdown("""
    ## Транскрибация и диаризация (русский язык)
    - Фиксированный язык распознавания: **ru** для повышения скорости.
    - Диаризация спикеров через Pyannote.
    """)

    audio_input = gr.Audio(type="filepath", label="Загрузите аудио (только RU)")
    transcribe_btn = gr.Button("▶️ Транскрибировать")
    output_txt = gr.Textbox(label="Результат транскрипции", lines=20)
    save_btn = gr.Button("💾 Экспорт в .txt")
    download_file = gr.File(label="Скачать результат")

    transcribe_btn.click(
        fn=transcribe_with_diarization,
        inputs=audio_input,
        outputs=output_txt
    )
    save_btn.click(
        fn=export_to_txt,
        inputs=output_txt,
        outputs=download_file
    )

if __name__ == "__main__":
    app.launch()