File size: 3,929 Bytes
82e11f0
 
 
 
4df8719
 
 
82e11f0
 
4df8719
82e11f0
 
 
 
 
 
 
 
 
 
 
 
 
 
4df8719
82e11f0
 
4df8719
 
 
 
 
 
 
 
 
 
 
 
3a2ffbd
82e11f0
 
 
 
 
553733d
198f058
553733d
 
82e11f0
553733d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
82e11f0
 
 
 
4df8719
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
import spaces

# isort: split

from collections.abc import Iterator
from itertools import batched

import gradio as gr
import torch
from silero_vad import load_silero_vad

from src.environment import load_hf_token
from src.shared.transcription import transcribe
from src.space.runtime import SpaceConfig, load_space_components, read_recording


def create_app() -> gr.Blocks:
    # ---------------------------------------------------------
    # Place model weights on CUDA during startup for ZeroGPU sharing.
    # ---------------------------------------------------------
    config = SpaceConfig()
    components = load_space_components(load_hf_token())
    device = torch.device("cuda")
    components.model.to(device)
    vad_model = load_silero_vad(onnx=True)

    @spaces.GPU(duration=30)
    def generate(audio: list[bytes]) -> list[str]:
        results = transcribe(components.model, components.feature_extractor, components.tokenizer, config, device, audio)
        return [result.text for result in results]

    def transcribe_recording(audio_path: str | None) -> Iterator[str]:
        segments = read_recording(audio_path, vad_model)
        if not segments:
            yield "音声内に発話が見つかりませんでした。"
            return
        texts: list[str] = []
        for batch in batched(segments, 4):
            texts.extend(generate(list(batch)))
            yield "".join(texts).replace("\r", "").replace("\n", "")

    # ---------------------------------------------------------
    # Provide one audio input and one transcription action.
    # ---------------------------------------------------------
    with gr.Blocks(title="LambdaAudio v6", delete_cache=(3600, 3600)) as app:
        gr.Markdown("# LambdaAudio v6\n日本語の音声をアップロードするか、マイクで録音してください。\n\n[モデルの詳細](https://huggingface.co/KeisukeMiyamoto/lambda-audio-v6)")
        audio = gr.Audio(sources=["microphone", "upload"], type="filepath", format="wav", label="音声", editable=False, elem_id="recording-input")
        button = gr.Button("文字起こし", variant="primary", elem_id="transcribe-button")
        submit = gr.Button(visible="hidden", elem_id="transcribe-submit")
        output = gr.Textbox(label="文字起こし結果", lines=5, interactive=False, buttons=["copy"])
        submit.click(transcribe_recording, inputs=audio, outputs=output, api_name="transcribe", concurrency_limit=1)

        # ---------------------------------------------------------
        # Stop the browser recorder before submitting its uploaded audio.
        # The stop_recording event fires after Gradio finishes uploading.
        # ---------------------------------------------------------
        button.click(
            fn=None,
            queue=False,
            js="""() => {
                const audio = document.getElementById('recording-input');
                if (audio.dataset.submitAfterRecording) return;
                const stop = [...audio.querySelectorAll('.stop-button, .stop-button-paused')]
                    .find(button => button.checkVisibility());
                if (stop) {
                    audio.dataset.submitAfterRecording = 'true';
                    stop.click();
                    return;
                }
                document.getElementById('transcribe-submit').click();
            }""",
        )
        audio.stop_recording(
            fn=None,
            queue=False,
            js="""() => {
                const audio = document.getElementById('recording-input');
                if (!audio.dataset.submitAfterRecording) return;
                delete audio.dataset.submitAfterRecording;
                document.getElementById('transcribe-submit').click();
            }""",
        )
    return app.queue(max_size=10)


if __name__ == "__main__":
    create_app().launch(max_file_size="200mb")