Metadata-Version: 2.5
Name: polza-stt
Version: 0.3.0
Summary: Параллельная транскрибация длинного аудио через Polza.ai с TUI, выбором модели и подсчётом стоимости
Project-URL: Homepage, https://github.com/DaSh-More/polza-stt
Project-URL: Issues, https://github.com/DaSh-More/polza-stt/issues
Author-email: Danila Shevkunov <mail@dshevkunov.dev>
License-Expression: MIT
License-File: LICENSE
Keywords: cli,ffmpeg,polza,speech-to-text,stt,transcription,tui,whisper
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: End Users/Desktop
Classifier: Natural Language :: Russian
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Classifier: Topic :: Utilities
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27
Requires-Dist: platformdirs>=4.0
Requires-Dist: readchar>=4.0
Requires-Dist: rich>=13.7
Description-Content-Type: text/markdown

# polza-stt

Транскрибация длинного аудио через [Polza.ai](https://polza.ai) — с терминальным интерфейсом, выбором модели по цене и подсчётом того, сколько это стоило.

Файл режется ffmpeg на куски по 5 минут, все куски уходят в API **одновременно** (asyncio + httpx, без потоков), результат склеивается в один текстовый файл, временные нарезки удаляются.

> Неофициальный клиент. Проект не связан с Polza.ai, нужен свой API-ключ.

## Возможности

- **Параллельно** — все куски в сети одновременно, длинная лекция обрабатывается за время одного куска.
- **Выбор файла стрелками** — список аудио в каталоге с размерами и длительностью, плюс системный диалог (tkinter, с запасными zenity/kdialog) и ручной ввод пути.
- **Выбор модели с ценами** — таблица STT-моделей из API: рублей за минуту и сколько выйдет **именно этот файл**.
- **Деньги на виду** — оценка до запуска, факт после: сумма из `usage` API, а если провайдер её не вернул — тариф × фактически отправленная длительность.
- **Живой прогресс** — статус каждого куска, счётчик слов, повторы при сбоях, общий прогресс-бар.
- **Ошибка куска не рушит прогон** — остальной текст сохраняется, упавшие перечисляются, код возврата 2.

## Установка

Нужен **ffmpeg** в PATH (`apt install ffmpeg`, `brew install ffmpeg`, `winget install Gyan.FFmpeg`).

```bash
uv tool install polza-stt      # или: pipx install polza-stt
```

Разовый запуск без установки:

```bash
uvx polza-stt
```

## Настройка

При первом запуске утилита спросит только API-ключ и сохранит его **в одно постоянное место**, не зависящее от текущего каталога:

| ОС | Путь |
| --- | --- |
| Linux | `~/.config/polza-stt/config.env` (или `$XDG_CONFIG_HOME`) |
| macOS | `~/Library/Application Support/polza-stt/config.env` |
| Windows | `%APPDATA%\polza-stt\config.env` |

Права на файл — `600`. Посмотреть путь: `polza-stt --config-path`. Переопределить глобально: переменная `POLZA_STT_CONFIG`, разово — флаг `--config путь`. Если в текущем каталоге лежит готовый `./.env`, при первом запуске он автоматически переедет в постоянное хранилище.

Формат простой:

```ini
BASE_URL=https://polza.ai/api/v2
TOKEN=ваш_ключ
MODEL=ai-sage/gigaam-v3
```

`BASE_URL` подставляется сам (`https://polza.ai/api/v2`) — менять его нужно, только если Polza сменит адрес или вы работаете через свой прокси; тогда просто поправьте строку в файле.

`MODEL` заполнять не нужно: строка появляется сама и обновляется на ту модель, которой вы транскрибировали в последний раз. В меню выбора эта модель помечена `•` и стоит под курсором, так что повторный запуск — это просто два Enter.

Те же значения можно передать переменными окружения `BASE_URL` / `TOKEN` / `MODEL` (или `POLZA_BASE_URL` и т.д.). Перенастроить: `polza-stt --reconfigure`.

## Использование

```bash
polza-stt                                  # выбрать файл и модель в интерфейсе
polza-stt lecture.mp3                       # файл задан, модель выбрать в UI
polza-stt lecture.mp3 -y                    # без вопросов, модель из конфига
polza-stt lecture.mp3 -y --model openai/whisper-large-v3-turbo -o out.txt
```

Клавиши в меню: `↑`/`↓` (и `j`/`k`) — выбор, `Enter` — подтвердить, цифры — быстрый прыжок, `q`/`Esc` — выход.

### Аргументы

| Аргумент | Значение |
| --- | --- |
| `audio` | путь к файлу; без него — выбор в интерфейсе |
| `-o, --output` | куда писать текст (по умолчанию `<audio>.txt`) |
| `--chunk` | длина куска в секундах (по умолчанию 300) |
| `--jobs` | ограничение одновременных запросов (0 — авто, не более 16) |
| `--language` | ISO-639-1 (`ru`, `en`, …) или `auto` — определить самому (по умолчанию) |
| `--model` | ID модели, пропускает выбор |
| `--config` | путь к конфигу (синоним `--env`) |
| `--config-path` | показать путь к конфигу и выйти |
| `--dir` | каталог для выбора файла |
| `--reconfigure` | перезаписать конфиг |
| `-y, --yes` | без подтверждения и без выбора модели |

Коды возврата: `0` — успех, `1` — ошибка запуска (нет ffmpeg, нет файла, нет конфига), `2` — часть кусков не транскрибировалась.

## Как считается стоимость

Цены берутся из `GET {base_url}/models` — поле `stt_per_minute` у моделей с `type: stt`, в рублях. Оценка до запуска = длительность × тариф. После прогона, если API вернул `usage.cost_rub`, показывается его сумма («по данным API»), иначе считается по тарифу и фактической длительности отправленных кусков. Если `/models` недоступен, берётся небольшой встроенный список моделей.

## Технические детали

- Куски перекодируются в mono MP3 16 кГц / 64 кбит/с — пятиминутный фрагмент весит ~2.5 МБ и после base64 укладывается в лимит тела запроса (~15 МБ).
- Порядок текста сохраняется по индексу куска независимо от порядка ответов.
- Три попытки на кусок с паузами 2 и 4 секунды.
- Временный каталог удаляется в `finally` — промежуточные тексты на диск не пишутся вообще.
- Одновременно в полёте держится не более 16 запросов: каждый несёт ~3 МБ base64, и без потолка десятичасовой файл (120 кусков) занял бы под гигабайт памяти. Сами тексты крошечные — 10 часов речи это ~0.5 МБ. Потолок меняется флагом `--jobs`.
- Нарезки на диске: ~29 МБ на час аудио (моно MP3 64 кбит/с), для 10 часов ~290 МБ во временном каталоге на время работы.

## Лицензия

MIT
