- неявный compute_type при fallback переразрешается по умолчанию CPU (float16 CUDA не переносится на CTranslate2 CPU); - prepare() помечает module готовым только после проверки пословного контракта; - движок сообщает сам adapter (атрибут engine) вместо параллельной таблицы; - сбой runtime_info() не роняет запуск; - каскад конфига оставляет model/compute_type пустыми для module, CLI не дублирует CLI > TOML; - удалены недостижимые из CLI сообщения о mid-stream fallback; - в --verbose потоки помечены как запрошенные, adapters сообщают применённые; OpenVINO прямо говорит, что --threads не применяется; - тесты: умолчания по устройствам, TOML compute_type, не-strict сценарий обычной ошибки; CONTRIBUTING.md и AGENTS.md без устаревших имён. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
5.3 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Project
Local audio/video transcription CLI — no cloud, no API keys. Outputs markdown with timestamps.
Language conventions: code identifiers in English; docstrings, comments, UI strings, and commit messages in Russian. Style is ruff-compatible. Commits follow Conventional Commits.
Commands
uv sync # install dependencies
uv run transcribe meeting.mp4 # run CLI
uv run pytest # run all tests
uv run pytest tests/test_cli.py # run one test file
uv run pytest -k test_name # run single test by name
uv run pytest -v # verbose output
Package manager is uv (not pip). Build backend is hatchling.
Architecture
CLI (cli.py)
→ config.py cascade: CLI arg → .transcriber.toml (model/compute_type stay None for the module to resolve)
→ utils.py detect_device(), validate files, expand globs (Windows workaround)
→ context_menu.py Windows SendTo: Transcribe.cmd install/uninstall (--install-menu / --uninstall-menu)
→ transcriber.py Transcriber(ExecutionRequest): resolves auto + device defaults,
get_backend(device) → ensure_model_available → create_model once per run,
transcribe(file) per file; fallback and ExecutionInfo stay inside
→ formatter.py segments → markdown with timestamps, paragraph grouping (>2s pause or >60s)
Backend system (src/local_transcriber/backends/)
Three backends implement the Backend Protocol (structural typing, no inheritance required):
| Backend | Module | Devices | Library |
|---|---|---|---|
| FasterWhisper | faster_whisper.py |
cpu, cuda |
faster_whisper (CTranslate2) |
| OpenVINO | openvino.py |
openvino, openvino-gpu, openvino-cpu |
openvino_genai |
| OnnxAsr | onnx_asr.py |
onnx |
onnx_asr (onnxruntime) |
get_backend(device) in backends/__init__.py maps device string to backend with lazy imports.
Key design decisions
- Execution module (
Transcriber): one owner per run for model handle, adapter, actual device and allowed GPU→CPU fallback (load time and mid-stream). Callers getTranscribeResult+ExecutionInfo(requested vs actual device, engine, model, compute type, threads,runtime_info()from the adapter for--verbose). Fallback is reachable only withstrict_device=False(Python API): CLI explicit device is strict,autois ONNX CPU. - CUDA bootstrap (
_cuda_bootstrap.py): preloadslibcublas.so.12viactypes.CDLL(RTLD_GLOBAL)before importing ctranslate2, because pip'snvidia-cublas-cu12installs to a non-standard path andLD_LIBRARY_PATHcan't be changed at runtime (glibc caches it). - Batch mode: 3-phase pipeline (prescan → create
Transcriber→ transcribe all). No state is carried between files by the CLI. - Device-aware defaults:
compute_typeandmodelvary by device (float16 for CUDA, int8 for OpenVINO, float32 for CPU). Defined inconfig.pyDEVICE_DEFAULTS, applied byTranscriberwhen the request leaves themNone. - ONNX thread budget:
--threadssetsintra_op_num_threadsfor both ASR and VAD sessions viaSessionOptions; 0 keeps onnxruntime defaults. - OpenVINO uses pre-quantized models —
compute_typeselects which HF repo to download, not a runtime parameter.
Testing
All tests mock backends — no real model downloads or transcription. Key test patterns:
- CLI tests:
typer.testing.CliRunnerwith the realTranscriberand a fake adapter patched atlocal_transcriber.transcriber.get_backend;load_config,validate_input_file,write_transcriptmocked _cli_run()— context manager assembling that standard set, yields(backend, write_transcript)_make_result()/_make_backend()— factories for test data- Module tests (
test_transcriber.py):Transcriberthrough its interface with_make_run_backend(); adapter tests patch the libraries (onnx_asr.load_model,faster_whisper.WhisperModel)
Common tasks
- New CLI option: add
typer.Optionincli.py:main()→ add key toHARDCODED_DEFAULTSinconfig.py→ write test - New audio/video format: add extension to
SUPPORTED_EXTENSIONSinutils.py - New backend: implement
Backendprotocol → add device mapping inbackends/__init__.py→ add device-aware defaults inconfig.py - Change output format: edit
format_transcript()informatter.py
Project docs
docs/PRD.md— product requirements and scopedocs/backlog.md— future experiments and ideasdocs/gpu.md— GPU benchmarks, platform compatibility detailsdocs/adr/— architecture decision records (CUDA bootstrap, batch mode, pluggable backends, compute-type defaults, ONNX-ASR evaluation)
Agent skills
Issue tracker
Задачи ведутся в Gitea через tea; GitHub используется только как зеркало, внешние PR не входят в triage. См. docs/agents/issue-tracker.md.
Triage labels
Используются стандартные пять triage-меток. См. docs/agents/triage-labels.md.
Domain docs
Репозиторий использует single-context layout. См. docs/agents/domain.md.