feat(utils): реализованы проверки окружения (шаг 2)
- Зачем:
- необходимы утилиты для проверки ffmpeg, определения устройства и
валидации входного файла перед запуском транскрипции.
- Что:
- check_ffmpeg() завершает процесс с понятным сообщением, если ffmpeg не в PATH.
- detect_device() возвращает "cuda" при наличии nvidia-smi, иначе "cpu".
- get_gpu_name() получает имя GPU через nvidia-smi или возвращает None.
- validate_input_file() проверяет существование, тип и размер файла;
неизвестное расширение — warning, не ошибка.
- build_output_path() формирует путь <stem>-transcript.md рядом с исходником.
- Проверка:
- uv run pytest tests/test_utils.py -v — 9 passed.
- uv run python -c "from local_transcriber.utils import check_ffmpeg, detect_device; check_ffmpeg(); print(detect_device())"
This commit is contained in:
@@ -1,21 +1,68 @@
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import warnings
|
||||
from pathlib import Path
|
||||
|
||||
SUPPORTED_EXTENSIONS = {
|
||||
".mp3", ".wav", ".flac", ".ogg", ".m4a", ".wma", ".aac",
|
||||
".mp4", ".mkv", ".avi", ".mov", ".webm", ".ts",
|
||||
}
|
||||
|
||||
|
||||
def check_ffmpeg() -> None:
|
||||
raise NotImplementedError
|
||||
try:
|
||||
subprocess.run(["ffmpeg", "-version"], capture_output=True, check=False)
|
||||
except FileNotFoundError:
|
||||
sys.exit(
|
||||
"ffmpeg не найден в PATH. Установите ffmpeg:\n"
|
||||
" Linux: apt install ffmpeg\n"
|
||||
" Windows: winget install ffmpeg\n"
|
||||
" macOS: brew install ffmpeg"
|
||||
)
|
||||
|
||||
|
||||
def detect_device(requested: str = "auto") -> str:
|
||||
raise NotImplementedError
|
||||
if requested != "auto":
|
||||
return requested
|
||||
if shutil.which("nvidia-smi") is not None:
|
||||
return "cuda"
|
||||
return "cpu"
|
||||
|
||||
|
||||
def get_gpu_name() -> str | None:
|
||||
raise NotImplementedError
|
||||
try:
|
||||
result = subprocess.run(
|
||||
["nvidia-smi", "--query-gpu=name", "--format=csv,noheader"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
name = result.stdout.strip().splitlines()[0].strip()
|
||||
return name if name else None
|
||||
except FileNotFoundError:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def validate_input_file(path: Path) -> Path:
|
||||
raise NotImplementedError
|
||||
if not path.exists():
|
||||
raise FileNotFoundError(f"Файл не найден: {path}")
|
||||
if not path.is_file():
|
||||
raise ValueError(f"Путь не является файлом: {path}")
|
||||
if path.stat().st_size == 0:
|
||||
raise ValueError(f"Файл пустой: {path}")
|
||||
if path.suffix.lower() not in SUPPORTED_EXTENSIONS:
|
||||
warnings.warn(
|
||||
f"Расширение '{path.suffix}' не входит в список поддерживаемых. "
|
||||
"Попытка продолжить.",
|
||||
stacklevel=2,
|
||||
)
|
||||
return path.resolve()
|
||||
|
||||
|
||||
def build_output_path(input_path: Path, output: Path | None = None) -> Path:
|
||||
raise NotImplementedError
|
||||
if output is not None:
|
||||
return output
|
||||
return input_path.with_stem(input_path.stem + "-transcript").with_suffix(".md")
|
||||
|
||||
Reference in New Issue
Block a user