File size: 4,059 Bytes
ba0dc1d
 
 
 
d1c912a
ba0dc1d
 
d0351bc
ba0dc1d
d0351bc
ba0dc1d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
d0351bc
 
ba0dc1d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
import os
import shutil
import tempfile
from pathlib import Path

import gradio as gr
from transformers import pipeline

# Prøv å støtte video via pydub + ffmpeg hvis tilgjengelig (valgfritt)
try:
    from pydub import AudioSegment
    HAS_PYDUB = True
except Exception:
    HAS_PYDUB = False

# --- Konfigurasjon ---
# CPU: bruk en mindre, flerspråklig modell. (large-v3 på CPU vil ofte knekke.)
# Alternativer: "openai/whisper-small", "openai/whisper-medium", "distil-whisper/distil-small.multilingual"
ASR_MODEL_ID = "openai/whisper-small"

def make_transcriber():
    # device=-1 tvinger CPU. return_timestamps=True gir tidskoder i retur.
    return pipeline(
        task="automatic-speech-recognition",
        model=ASR_MODEL_ID,
        device=-1,
        return_timestamps=True
    )

transcriber = make_transcriber()

VIDEO_EXTS = {".mp4", ".avi", ".mov", ".mkv", ".webm"}
AUDIO_EXTS = {".wav", ".mp3", ".m4a", ".flac", ".ogg", ".opus", ".aac"}

def extract_audio_if_needed(input_path: str) -> str:
    """
    Tar inn en filsti (audio eller video).
    Hvis video og pydub+ffmpeg finnes, ekstraheres WAV til temp-katalog og
    vi returnerer ny filsti. Hvis ikke, kastes en forklarende feil.
    Hvis allerede audio, returneres originalstien.
    """
    suffix = Path(input_path).suffix.lower()

    # Allerede audio?
    if suffix in AUDIO_EXTS:
        return input_path

    # Video?
    if suffix in VIDEO_EXTS:
        if not HAS_PYDUB:
            raise RuntimeError(
                "Video oppdaget, men pydub/ffmpeg er ikke tilgjengelig. "
                "Installer pydub og ffmpeg (se requirements.txt og apt.txt), "
                "eller last opp en ren lydfil."
            )
        # Ekstraher WAV
        temp_dir = tempfile.mkdtemp(prefix="asr_")
        out_wav = os.path.join(temp_dir, "extracted_audio.wav")
        audio = AudioSegment.from_file(input_path)
        audio.export(out_wav, format="wav")
        return out_wav

    # Ukjent – la Whisper prøve; hvis det feiler, får brukeren feilmelding
    return input_path

def handle_upload_and_transcribe(file_path: str):
    if not file_path:
        return "Last opp en lyd- eller videofil."

    tmp_to_cleanup = None
    try:
        # Kan generere en temp WAV (for video)
        maybe_audio = extract_audio_if_needed(file_path)
        if maybe_audio != file_path:
            tmp_to_cleanup = os.path.dirname(maybe_audio)

        # Tips: du kan sette språk eksplisitt for raskere/mer stabil dekoding:
        # generate_kwargs={"task": "transcribe", "language": "no"}
        result = transcriber(maybe_audio)

        # Rydd temp
        if tmp_to_cleanup and os.path.exists(tmp_to_cleanup):
            shutil.rmtree(tmp_to_cleanup, ignore_errors=True)

        # Normaliser utdata
        if isinstance(result, dict):
            # transformers>=4.30 gir ofte {"text": "...", "chunks": [...]}
            text = result.get("text")
            if text:
                return text.strip()
            # fallback
            return str(result)
        elif isinstance(result, list) and result:
            return result[0].get("text", str(result))
        return str(result)

    except Exception as e:
        # Rydd opp ved feil
        if tmp_to_cleanup and os.path.exists(tmp_to_cleanup):
            shutil.rmtree(tmp_to_cleanup, ignore_errors=True)
        return f"❌ Feil under prosessering/transkripsjon: {e}"

with gr.Blocks(title="Multilingual Audio/Video Transcription") as demo:
    gr.Markdown(
        "## Multilingual Transcription (CPU)\n"
        "Last opp en lydfil (.wav/.mp3/.m4a/…) eller videofil (.mp4/.mov/…). "
        "På CPU brukes en mindre Whisper-modell for stabil kjøring."
    )
    inp = gr.Audio(type="filepath", label="Fil (audio eller video)")
    out = gr.Textbox(label="Transkripsjon")
    btn = gr.Button("Transkriber")
    btn.click(handle_upload_and_transcribe, inputs=inp, outputs=out)

if __name__ == "__main__":
    # På HF Spaces trenger du vanligvis ikke server_name/server_port her.
    demo.launch()