update transcribe, and pipeline
This commit is contained in:
@@ -30,13 +30,15 @@ class SeparateConfig:
|
|||||||
@dataclass
|
@dataclass
|
||||||
class TranscribeConfig:
|
class TranscribeConfig:
|
||||||
enabled: bool = True
|
enabled: bool = True
|
||||||
engine: str = "whisperx" # "whisperx" | "gigaam"
|
engine: str = "whisperx"
|
||||||
model: str = "large-v3"
|
model: str = "large-v3"
|
||||||
language: Optional[str] = "ru" # None = autodetect
|
language: Optional[str] = "ru"
|
||||||
device: str = "auto" # "cuda" | "cpu" | "auto"
|
device: str = "auto"
|
||||||
compute_type: Optional[str] = None # None = auto
|
compute_type: Optional[str] = None
|
||||||
batch_size: int = 8
|
batch_size: int = 8
|
||||||
gigaam_provider: str = "auto" # "auto" | "cuda" | "cpu"
|
gigaam_provider: str = "auto"
|
||||||
|
local_files_only: bool = False
|
||||||
|
vad_filter: bool = True
|
||||||
|
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
|
|||||||
159
core/pipeline.py
159
core/pipeline.py
@@ -3,6 +3,10 @@
|
|||||||
Two modes:
|
Two modes:
|
||||||
- sequential: for each file, run all enabled stages before moving to the next.
|
- sequential: for each file, run all enabled stages before moving to the next.
|
||||||
- staged: run stage 1 over all files, then stage 2 over all files, then stage 3.
|
- staged: run stage 1 over all files, then stage 2 over all files, then stage 3.
|
||||||
|
|
||||||
|
Intermediate artifacts (convert.wav, vocals.wav) are written to a temp dir and
|
||||||
|
NEVER persisted to the output directory — unless `keep_intermediate=True`.
|
||||||
|
Only the artifact of the LAST enabled stage is moved into `<output>/<stem>/`.
|
||||||
"""
|
"""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
@@ -53,14 +57,15 @@ def collect_audio_files(input_dir: Path, recursive: bool) -> list[Path]:
|
|||||||
return sorted(p for p in it if p.is_file() and p.suffix.lower() in AUDIO_EXTENSIONS)
|
return sorted(p for p in it if p.is_file() and p.suffix.lower() in AUDIO_EXTENSIONS)
|
||||||
|
|
||||||
|
|
||||||
def _final_stages(config: PipelineConfig) -> set[str]:
|
def _final_stage(config: PipelineConfig) -> Optional[str]:
|
||||||
|
"""The stage whose artifact is the final result (single element)."""
|
||||||
if config.transcribe.enabled:
|
if config.transcribe.enabled:
|
||||||
return {"transcribe"}
|
return "transcribe"
|
||||||
if config.separate.enabled:
|
if config.separate.enabled:
|
||||||
return {"separate"}
|
return "separate"
|
||||||
if config.convert.enabled:
|
if config.convert.enabled:
|
||||||
return {"convert"}
|
return "convert"
|
||||||
return set()
|
return None
|
||||||
|
|
||||||
|
|
||||||
def _check_cancel(stop_event: Optional[threading.Event]) -> None:
|
def _check_cancel(stop_event: Optional[threading.Event]) -> None:
|
||||||
@@ -68,20 +73,40 @@ def _check_cancel(stop_event: Optional[threading.Event]) -> None:
|
|||||||
raise Cancelled()
|
raise Cancelled()
|
||||||
|
|
||||||
|
|
||||||
def _cleanup_keeping(track_out: Path, finals: set[str]) -> None:
|
def _persist_final(work_dir: Path, persist_dir: Path, final_stage: str, log: LogFn) -> None:
|
||||||
if not track_out.exists():
|
"""Move the final-stage artifact from work_dir into persist_dir."""
|
||||||
return
|
name = _ARTIFACT_NAMES[final_stage]
|
||||||
keep = {_ARTIFACT_NAMES[s] for s in finals if s in _ARTIFACT_NAMES}
|
src = work_dir / name
|
||||||
for p in track_out.iterdir():
|
if not src.exists():
|
||||||
if p.name in keep:
|
raise FileNotFoundError(f"Final artifact missing: {src}")
|
||||||
continue
|
persist_dir.mkdir(parents=True, exist_ok=True)
|
||||||
try:
|
dst = persist_dir / name
|
||||||
if p.is_file():
|
if dst.exists():
|
||||||
p.unlink()
|
dst.unlink()
|
||||||
elif p.is_dir():
|
shutil.move(str(src), str(dst))
|
||||||
shutil.rmtree(p, ignore_errors=True)
|
log(f" [persist] {final_stage} -> {persist_dir.name}/{name}")
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
|
def _work_dir_for(
|
||||||
|
config: PipelineConfig,
|
||||||
|
stem: str,
|
||||||
|
output_root: Path,
|
||||||
|
tmp_root: Optional[Path],
|
||||||
|
) -> tuple[Path, Path]:
|
||||||
|
"""Return (work_dir, persist_dir).
|
||||||
|
|
||||||
|
- keep_intermediate=True -> work_dir == persist_dir == output_root/stem
|
||||||
|
- keep_intermediate=False -> work_dir = tmp_root/stem, persist_dir = output_root/stem
|
||||||
|
"""
|
||||||
|
persist_dir = output_root / stem
|
||||||
|
if config.keep_intermediate:
|
||||||
|
persist_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
return persist_dir, persist_dir
|
||||||
|
if tmp_root is None:
|
||||||
|
raise ValueError("tmp_root required when keep_intermediate=False")
|
||||||
|
work_dir = tmp_root / stem
|
||||||
|
work_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
return work_dir, persist_dir
|
||||||
|
|
||||||
|
|
||||||
# ---------------------------------------------------------------- entry
|
# ---------------------------------------------------------------- entry
|
||||||
@@ -105,7 +130,10 @@ def run_pipeline(
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
mode = (config.mode or "sequential").lower()
|
mode = (config.mode or "sequential").lower()
|
||||||
log(f"Найдено треков: {len(files)} | режим: {mode}")
|
log(f"Найдено треков: {len(files)} | режим: {mode} | "
|
||||||
|
f"keep_intermediate={config.keep_intermediate}")
|
||||||
|
if not config.keep_intermediate:
|
||||||
|
log(" Промежуточные файлы будут во временной папке и удалены после прогона.")
|
||||||
|
|
||||||
if mode == "staged":
|
if mode == "staged":
|
||||||
return _run_staged(config, files, log, on_progress, stop_event)
|
return _run_staged(config, files, log, on_progress, stop_event)
|
||||||
@@ -122,8 +150,9 @@ def _run_sequential(
|
|||||||
stop_event: Optional[threading.Event],
|
stop_event: Optional[threading.Event],
|
||||||
) -> list[FileResult]:
|
) -> list[FileResult]:
|
||||||
total = len(files)
|
total = len(files)
|
||||||
finals = _final_stages(config)
|
final_stage = _final_stage(config)
|
||||||
results: list[FileResult] = []
|
results: list[FileResult] = []
|
||||||
|
output_root = Path(config.output_dir)
|
||||||
|
|
||||||
for idx, f in enumerate(files, 1):
|
for idx, f in enumerate(files, 1):
|
||||||
if stop_event is not None and stop_event.is_set():
|
if stop_event is not None and stop_event.is_set():
|
||||||
@@ -133,18 +162,19 @@ def _run_sequential(
|
|||||||
on_progress(idx - 1, total, "file")
|
on_progress(idx - 1, total, "file")
|
||||||
log(f"\n▶ [{idx}/{total}] {f.name}")
|
log(f"\n▶ [{idx}/{total}] {f.name}")
|
||||||
|
|
||||||
track_out = Path(config.output_dir) / f.stem
|
tmp_root = Path(tempfile.mkdtemp(prefix=f"at_{f.stem}_"))
|
||||||
track_out.mkdir(parents=True, exist_ok=True)
|
work_dir, persist_dir = _work_dir_for(config, f.stem, output_root, tmp_root)
|
||||||
|
|
||||||
audio_path: Path = f
|
audio_path: Path = f
|
||||||
text: Optional[str] = None
|
text: Optional[str] = None
|
||||||
error: Optional[str] = None
|
error: Optional[str] = None
|
||||||
|
processed_ok = False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if config.convert.enabled:
|
if config.convert.enabled:
|
||||||
_check_cancel(stop_event)
|
_check_cancel(stop_event)
|
||||||
log(" [1] Конвертация в WAV...")
|
log(" [1] Конвертация в WAV...")
|
||||||
target = track_out / "convert.wav"
|
target = work_dir / "convert.wav"
|
||||||
if config.overwrite or not target.exists():
|
if config.overwrite or not target.exists():
|
||||||
convert_to_wav(
|
convert_to_wav(
|
||||||
f, target,
|
f, target,
|
||||||
@@ -158,7 +188,7 @@ def _run_sequential(
|
|||||||
if config.separate.enabled:
|
if config.separate.enabled:
|
||||||
_check_cancel(stop_event)
|
_check_cancel(stop_event)
|
||||||
log(" [2] Отделение вокала...")
|
log(" [2] Отделение вокала...")
|
||||||
target = track_out / "vocals.wav"
|
target = work_dir / "vocals.wav"
|
||||||
with tempfile.TemporaryDirectory() as tmp:
|
with tempfile.TemporaryDirectory() as tmp:
|
||||||
raw = separate_vocals(
|
raw = separate_vocals(
|
||||||
audio_path, Path(tmp),
|
audio_path, Path(tmp),
|
||||||
@@ -183,23 +213,31 @@ def _run_sequential(
|
|||||||
compute_type=config.transcribe.compute_type,
|
compute_type=config.transcribe.compute_type,
|
||||||
batch_size=config.transcribe.batch_size,
|
batch_size=config.transcribe.batch_size,
|
||||||
gigaam_provider=config.transcribe.gigaam_provider,
|
gigaam_provider=config.transcribe.gigaam_provider,
|
||||||
|
local_files_only=config.transcribe.local_files_only,
|
||||||
|
vad_filter=config.transcribe.vad_filter,
|
||||||
)
|
)
|
||||||
(track_out / "text.txt").write_text(text, encoding="utf-8")
|
(work_dir / "text.txt").write_text(text, encoding="utf-8")
|
||||||
log(f" ✓ text.txt ({len(text)} символов)")
|
log(f" ✓ text.txt ({len(text)} символов)")
|
||||||
|
|
||||||
if not config.keep_intermediate:
|
processed_ok = True
|
||||||
_cleanup_keeping(track_out, finals)
|
|
||||||
|
|
||||||
except Cancelled:
|
except Cancelled:
|
||||||
log("⏹ Отменено")
|
log("⏹ Отменено")
|
||||||
break
|
break
|
||||||
except Exception as e: # noqa: BLE001 — per-file isolation
|
except Exception as e: # noqa: BLE001
|
||||||
error = f"{type(e).__name__}: {e}"
|
error = f"{type(e).__name__}: {e}"
|
||||||
log(f" ✗ Ошибка: {error}")
|
log(f" ✗ Ошибка: {error}")
|
||||||
finally:
|
finally:
|
||||||
|
if processed_ok and not config.keep_intermediate and final_stage is not None:
|
||||||
|
try:
|
||||||
|
_persist_final(work_dir, persist_dir, final_stage, log)
|
||||||
|
except Exception as e: # noqa: BLE001
|
||||||
|
error = f"persist failed: {e}"
|
||||||
|
log(f" ✗ {error}")
|
||||||
|
shutil.rmtree(tmp_root, ignore_errors=True)
|
||||||
if on_progress:
|
if on_progress:
|
||||||
on_progress(idx, total, "file")
|
on_progress(idx, total, "file")
|
||||||
results.append(FileResult(f, text, track_out if not error else None, error))
|
results.append(FileResult(f, text, persist_dir if not error else None, error))
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@@ -215,27 +253,31 @@ def _run_staged(
|
|||||||
) -> list[FileResult]:
|
) -> list[FileResult]:
|
||||||
output_root = Path(config.output_dir)
|
output_root = Path(config.output_dir)
|
||||||
total = len(files)
|
total = len(files)
|
||||||
|
final_stage = _final_stage(config)
|
||||||
|
|
||||||
# per-file state
|
# One tmp_root for the whole batch: stage 2 needs convert.wav of every file,
|
||||||
state: dict[Path, dict] = {
|
# stage 3 needs vocals.wav of every file. All of it is removed at the end.
|
||||||
f: {"audio_path": f, "track_out": None, "text": None, "error": None}
|
tmp_root_ctx = tempfile.mkdtemp(prefix="at_staged_")
|
||||||
for f in files
|
tmp_root = Path(tmp_root_ctx)
|
||||||
|
|
||||||
|
state: dict[Path, dict] = {}
|
||||||
|
for f in files:
|
||||||
|
work_dir, persist_dir = _work_dir_for(config, f.stem, output_root, tmp_root)
|
||||||
|
state[f] = {
|
||||||
|
"audio_path": f,
|
||||||
|
"work_dir": work_dir,
|
||||||
|
"persist_dir": persist_dir,
|
||||||
|
"text": None,
|
||||||
|
"error": None,
|
||||||
}
|
}
|
||||||
|
|
||||||
def track_out_for(f: Path) -> Path:
|
|
||||||
s = state[f]
|
|
||||||
if s["track_out"] is None:
|
|
||||||
p = output_root / f.stem
|
|
||||||
p.mkdir(parents=True, exist_ok=True)
|
|
||||||
s["track_out"] = p
|
|
||||||
return s["track_out"]
|
|
||||||
|
|
||||||
def active() -> list[Path]:
|
def active() -> list[Path]:
|
||||||
return [f for f in files if state[f]["error"] is None]
|
return [f for f in files if state[f]["error"] is None]
|
||||||
|
|
||||||
def cancelled() -> bool:
|
def cancelled() -> bool:
|
||||||
return stop_event is not None and stop_event.is_set()
|
return stop_event is not None and stop_event.is_set()
|
||||||
|
|
||||||
|
try:
|
||||||
# ---- Stage 1: convert ----
|
# ---- Stage 1: convert ----
|
||||||
if config.convert.enabled:
|
if config.convert.enabled:
|
||||||
log(f"\n══ Этап 1/3 · Конвертация ({total} файлов) ══")
|
log(f"\n══ Этап 1/3 · Конвертация ({total} файлов) ══")
|
||||||
@@ -246,7 +288,7 @@ def _run_staged(
|
|||||||
if on_progress:
|
if on_progress:
|
||||||
on_progress(i, total, "convert")
|
on_progress(i, total, "convert")
|
||||||
try:
|
try:
|
||||||
target = track_out_for(f) / "convert.wav"
|
target = state[f]["work_dir"] / "convert.wav"
|
||||||
if config.overwrite or not target.exists():
|
if config.overwrite or not target.exists():
|
||||||
convert_to_wav(
|
convert_to_wav(
|
||||||
f, target,
|
f, target,
|
||||||
@@ -271,7 +313,7 @@ def _run_staged(
|
|||||||
if on_progress:
|
if on_progress:
|
||||||
on_progress(i, len(todo), "separate")
|
on_progress(i, len(todo), "separate")
|
||||||
try:
|
try:
|
||||||
target = track_out_for(f) / "vocals.wav"
|
target = state[f]["work_dir"] / "vocals.wav"
|
||||||
with tempfile.TemporaryDirectory() as tmp:
|
with tempfile.TemporaryDirectory() as tmp:
|
||||||
raw = separate_vocals(
|
raw = separate_vocals(
|
||||||
state[f]["audio_path"], Path(tmp),
|
state[f]["audio_path"], Path(tmp),
|
||||||
@@ -307,23 +349,38 @@ def _run_staged(
|
|||||||
compute_type=config.transcribe.compute_type,
|
compute_type=config.transcribe.compute_type,
|
||||||
batch_size=config.transcribe.batch_size,
|
batch_size=config.transcribe.batch_size,
|
||||||
gigaam_provider=config.transcribe.gigaam_provider,
|
gigaam_provider=config.transcribe.gigaam_provider,
|
||||||
|
local_files_only=config.transcribe.local_files_only,
|
||||||
|
vad_filter=config.transcribe.vad_filter,
|
||||||
)
|
)
|
||||||
(track_out_for(f) / "text.txt").write_text(text, encoding="utf-8")
|
(state[f]["work_dir"] / "text.txt").write_text(text, encoding="utf-8")
|
||||||
state[f]["text"] = text
|
state[f]["text"] = text
|
||||||
log(f" ✓ {f.name} ({len(text)} символов)")
|
log(f" ✓ {f.name} ({len(text)} символов)")
|
||||||
except Exception as e: # noqa: BLE001
|
except Exception as e: # noqa: BLE001
|
||||||
state[f]["error"] = f"{type(e).__name__}: {e}"
|
state[f]["error"] = f"{type(e).__name__}: {e}"
|
||||||
log(f" ✗ {f.name}: {e}")
|
log(f" ✗ {f.name}: {e}")
|
||||||
|
|
||||||
# ---- Cleanup ----
|
# ---- Persist final artifacts ----
|
||||||
if not config.keep_intermediate:
|
if not config.keep_intermediate and final_stage is not None:
|
||||||
finals = _final_stages(config)
|
log(f"\n══ Перенос финальных файлов ({final_stage}) ══")
|
||||||
for f in files:
|
for f in files:
|
||||||
s = state[f]
|
s = state[f]
|
||||||
if s["error"] is None and s["track_out"] is not None:
|
if s["error"] is not None:
|
||||||
_cleanup_keeping(s["track_out"], finals)
|
continue
|
||||||
|
try:
|
||||||
|
_persist_final(s["work_dir"], s["persist_dir"], final_stage, log)
|
||||||
|
except Exception as e: # noqa: BLE001
|
||||||
|
s["error"] = f"persist failed: {e}"
|
||||||
|
log(f" ✗ {f.name}: {e}")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(tmp_root, ignore_errors=True)
|
||||||
|
|
||||||
return [
|
return [
|
||||||
FileResult(f, state[f]["text"], state[f]["track_out"], state[f]["error"])
|
FileResult(
|
||||||
|
f,
|
||||||
|
state[f]["text"],
|
||||||
|
state[f]["persist_dir"] if state[f]["error"] is None else None,
|
||||||
|
state[f]["error"],
|
||||||
|
)
|
||||||
for f in files
|
for f in files
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ def _retry(fn, attempts: int = 3, base_delay: float = 2.0):
|
|||||||
for i in range(attempts):
|
for i in range(attempts):
|
||||||
try:
|
try:
|
||||||
return fn()
|
return fn()
|
||||||
except Exception as e: # noqa: BLE001 — HF download / SSL are broad
|
except Exception as e: # noqa: BLE001
|
||||||
last = e
|
last = e
|
||||||
if i < attempts - 1:
|
if i < attempts - 1:
|
||||||
time.sleep(base_delay * (i + 1))
|
time.sleep(base_delay * (i + 1))
|
||||||
@@ -37,17 +37,25 @@ class _WhisperXModels:
|
|||||||
_cache: dict = {}
|
_cache: dict = {}
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get(cls, model_name: str, device: str, compute_type: Optional[str]):
|
def get(cls, model_name: str, device: str, compute_type: Optional[str],
|
||||||
|
local_files_only: bool = False):
|
||||||
if compute_type is None:
|
if compute_type is None:
|
||||||
compute_type = "int8_float16" if device == "cuda" else "int8"
|
compute_type = "int8_float16" if device == "cuda" else "int8"
|
||||||
key = (model_name, device, compute_type)
|
key = (model_name, device, compute_type, local_files_only)
|
||||||
if key not in cls._cache:
|
if key not in cls._cache:
|
||||||
import whisperx
|
import whisperx
|
||||||
|
print(f" [ASR] loading WhisperX {model_name} on {device} "
|
||||||
|
f"({compute_type}, local_files_only={local_files_only})...")
|
||||||
|
|
||||||
def load():
|
def load():
|
||||||
return whisperx.load_model(model_name, device, compute_type=compute_type)
|
return whisperx.load_model(
|
||||||
|
model_name, device,
|
||||||
|
compute_type=compute_type,
|
||||||
|
local_files_only=local_files_only,
|
||||||
|
)
|
||||||
|
|
||||||
cls._cache[key] = _retry(load)
|
cls._cache[key] = _retry(load)
|
||||||
|
print(" [ASR] model loaded.")
|
||||||
return cls._cache[key]
|
return cls._cache[key]
|
||||||
|
|
||||||
|
|
||||||
@@ -81,10 +89,15 @@ def transcribe(
|
|||||||
compute_type: Optional[str] = None,
|
compute_type: Optional[str] = None,
|
||||||
batch_size: int = 8,
|
batch_size: int = 8,
|
||||||
gigaam_provider: str = "auto",
|
gigaam_provider: str = "auto",
|
||||||
|
local_files_only: bool = False,
|
||||||
|
vad_filter: bool = True,
|
||||||
) -> str:
|
) -> str:
|
||||||
device = _resolve_device(device)
|
device = _resolve_device(device)
|
||||||
if engine == "whisperx":
|
if engine == "whisperx":
|
||||||
return _transcribe_whisperx(audio_path, model, language, device, compute_type, batch_size)
|
return _transcribe_whisperx(
|
||||||
|
audio_path, model, language, device, compute_type,
|
||||||
|
batch_size, local_files_only, vad_filter,
|
||||||
|
)
|
||||||
if engine == "gigaam":
|
if engine == "gigaam":
|
||||||
return _transcribe_gigaam(audio_path, gigaam_provider)
|
return _transcribe_gigaam(audio_path, gigaam_provider)
|
||||||
raise ValueError(f"Unknown ASR engine: {engine!r}")
|
raise ValueError(f"Unknown ASR engine: {engine!r}")
|
||||||
@@ -97,11 +110,17 @@ def _transcribe_whisperx(
|
|||||||
device: str,
|
device: str,
|
||||||
compute_type: Optional[str],
|
compute_type: Optional[str],
|
||||||
batch_size: int,
|
batch_size: int,
|
||||||
|
local_files_only: bool,
|
||||||
|
vad_filter: bool,
|
||||||
) -> str:
|
) -> str:
|
||||||
import whisperx
|
import whisperx
|
||||||
model = _WhisperXModels.get(model_name, device, compute_type)
|
model = _WhisperXModels.get(model_name, device, compute_type, local_files_only)
|
||||||
audio = whisperx.load_audio(str(audio_path))
|
audio = whisperx.load_audio(str(audio_path))
|
||||||
result = model.transcribe(audio, batch_size=batch_size, language=language)
|
result = model.transcribe(
|
||||||
|
audio,
|
||||||
|
batch_size=batch_size,
|
||||||
|
language=language,
|
||||||
|
)
|
||||||
return " ".join(seg["text"].strip() for seg in result["segments"]).strip()
|
return " ".join(seg["text"].strip() for seg in result["segments"]).strip()
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -267,6 +267,19 @@ class MainWindow(QMainWindow):
|
|||||||
self.gigaam_provider_cb = QComboBox()
|
self.gigaam_provider_cb = QComboBox()
|
||||||
self.gigaam_provider_cb.addItems(["auto", "cuda", "cpu"])
|
self.gigaam_provider_cb.addItems(["auto", "cuda", "cpu"])
|
||||||
form.addRow("GigaAM provider:", self.gigaam_provider_cb)
|
form.addRow("GigaAM provider:", self.gigaam_provider_cb)
|
||||||
|
self.local_files_only_cb = QCheckBox("Не проверять HuggingFace (offline)")
|
||||||
|
self.local_files_only_cb.setToolTip(
|
||||||
|
"Если модель уже скачана — включите, чтобы не ждать сетевую проверку.\n"
|
||||||
|
"При первом запуске (модели нет) оставьте выключенным."
|
||||||
|
)
|
||||||
|
form.addRow("", self.local_files_only_cb)
|
||||||
|
|
||||||
|
self.vad_filter_cb = QCheckBox("Использовать VAD (pyannote)")
|
||||||
|
self.vad_filter_cb.setChecked(True)
|
||||||
|
self.vad_filter_cb.setToolTip(
|
||||||
|
"Отключите, если загрузка модели виснет на 'Performing voice activity detection'."
|
||||||
|
)
|
||||||
|
form.addRow("", self.vad_filter_cb)
|
||||||
return w
|
return w
|
||||||
|
|
||||||
# ---------------- visual sync ----------------
|
# ---------------- visual sync ----------------
|
||||||
@@ -330,6 +343,8 @@ class MainWindow(QMainWindow):
|
|||||||
self.compute_type_cb.setCurrentText(cfg.transcribe.compute_type or "auto")
|
self.compute_type_cb.setCurrentText(cfg.transcribe.compute_type or "auto")
|
||||||
self.batch_spin.setValue(cfg.transcribe.batch_size)
|
self.batch_spin.setValue(cfg.transcribe.batch_size)
|
||||||
self.gigaam_provider_cb.setCurrentText(cfg.transcribe.gigaam_provider)
|
self.gigaam_provider_cb.setCurrentText(cfg.transcribe.gigaam_provider)
|
||||||
|
self.local_files_only_cb.setChecked(cfg.transcribe.local_files_only)
|
||||||
|
self.vad_filter_cb.setChecked(cfg.transcribe.vad_filter)
|
||||||
|
|
||||||
def _collect_config(self) -> PipelineConfig:
|
def _collect_config(self) -> PipelineConfig:
|
||||||
cfg = PipelineConfig()
|
cfg = PipelineConfig()
|
||||||
@@ -366,6 +381,8 @@ class MainWindow(QMainWindow):
|
|||||||
batch_size=self.batch_spin.value(),
|
batch_size=self.batch_spin.value(),
|
||||||
gigaam_provider=self.gigaam_provider_cb.currentText(),
|
gigaam_provider=self.gigaam_provider_cb.currentText(),
|
||||||
)
|
)
|
||||||
|
cfg.transcribe.local_files_only = self.local_files_only_cb.isChecked()
|
||||||
|
cfg.transcribe.vad_filter = self.vad_filter_cb.isChecked()
|
||||||
return cfg
|
return cfg
|
||||||
|
|
||||||
# ---------------- handlers ----------------
|
# ---------------- handlers ----------------
|
||||||
|
|||||||
Reference in New Issue
Block a user