Metadata-Version: 2.4
Name: omni-transcriber
Version: 0.1.0
Summary: Transcribe anything: YouTube/Instagram/any URL, local media files, or whole folders - locally via Whisper.
License-Expression: MIT
License-File: LICENSE
Requires-Dist: typer>=0.15
Requires-Dist: rich>=13.7
Requires-Dist: faster-whisper>=1.2.0
Requires-Dist: ctranslate2>=4.6.3
Requires-Dist: yt-dlp[default]>=2026.1
Requires-Dist: onnxruntime<1.24 ; python_full_version < '3.11'
Requires-Dist: static-ffmpeg>=3.0
Requires-Dist: nvidia-cublas-cu12>=12.8 ; sys_platform != 'darwin' and extra == 'gpu'
Requires-Dist: nvidia-cudnn-cu12>=9.8,<10 ; sys_platform != 'darwin' and extra == 'gpu'
Requires-Python: >=3.10
Provides-Extra: gpu
Description-Content-Type: text/markdown

# omni-transcriber

Transcribe **anything** from the command line: a YouTube link, an Instagram
reel, any yt-dlp-supported URL, a local video or audio file, or a whole folder
of media. Transcription runs locally via [faster-whisper][fw] — no API key, no
audio leaves your machine.

```console
$ transcriber https://youtu.be/jNQXAC9IVRw
Alright, so here we are, one of the elephants...

$ transcriber lecture.mp4 -f srt -o lecture.srt
$ transcriber ~/podcasts -r -m turbo -o transcripts/
```

## Install

Needs Python 3.10 or newer. [uv][uv] is the smoothest route, but pipx and pip
work too.

```console
$ uv tool install omni-transcriber      # or: pipx install omni-transcriber
$ uvx omni-transcriber --help           # or run it without installing
```

**With NVIDIA GPU acceleration:**

```console
$ uv tool install "omni-transcriber[gpu]"
```

| Install | Download size | Notes |
| --- | --- | --- |
| default (CPU) | ~450 MB | Works everywhere. Fine for short clips. |
| `[gpu]` extra | ~2.7 GB | Adds the CUDA cuBLAS/cuDNN wheels. NVIDIA only. |

The `[gpu]` extra is never required. On a machine with an NVIDIA card but no
`[gpu]` install, `--device cuda` prints a warning and falls back to the CPU
rather than failing.

### Optional companions

- **A JavaScript runtime** — YouTube increasingly needs one. [Deno][deno] is
  yt-dlp's preferred runtime; Node.js also works. `transcriber` enables whichever
  it finds on your `PATH` automatically. Without one, some videos lose formats
  or fail outright.
- **ffmpeg** — *not* used for transcription (the bundled PyAV decoder reads audio
  straight out of any container). yt-dlp needs it only for a few stream types;
  if it is missing when that happens, a static build is fetched automatically.

## Usage

```
transcriber INPUTS...            files, folders, and/or URLs — mix freely
```

`ots` is installed as a shorter alias for the same command — `ots lecture.mp4`
does exactly what `transcriber lecture.mp4` does. (If you also use
[OpenTimestamps][ots], which ships its own `ots`, one will shadow the other on
your `PATH`; `transcriber` always works.)

| Flag | Meaning |
| --- | --- |
| `-f, --format` | `txt` (default), `srt`, `vtt`, `json`, `md` |
| `-t, --timestamps` | Timestamps in `txt`/`md` (`srt`/`vtt` always have them) |
| `-m, --model` | Whisper model — see the table below (default `small`) |
| `-o, --output` | A file for one input, or a directory (`-o out/`) for many |
| `-l, --language` | Force a language (`en`, `fr`, ...); default is auto-detect |
| `-r, --recursive` | Recurse into subfolders |
| `--device` | `auto` (default), `cpu`, `cuda` |
| `--compute-type` | `auto` (default), `int8`, `float16`, `int8_float16` |
| `--batch-size N` | Decoding batch size; default 8 on CUDA, sequential on CPU |
| `--no-vad` | Disable voice-activity filtering (keeps silence) |
| `--playlist` / `--limit N` | Expand a playlist link; cap how many entries |
| `--cookies-from-browser` / `--cookies` | Authenticate for private/login-walled media |
| `--keep-audio` | Keep the downloaded audio next to the transcript |
| `--overwrite` | Re-transcribe items that already have a transcript |
| `-v, --verbose` | yt-dlp and engine detail on stderr |

### Where output goes

- **One input, no `-o`** → the transcript goes to **stdout**, so it pipes:
  `transcriber talk.mp4 | wc -w`. Progress bars and warnings all go to stderr.
- **`-o FILE`** → that exact file.
- **Several inputs, a folder, a playlist, or `-o DIR/`** → one
  `<title>.<format>` file per item.

Existing transcripts are **skipped** with a notice rather than overwritten, so
re-running an interrupted batch resumes it for free. Pass `--overwrite` to redo
them. A batch keeps going when one item fails and prints a summary at the end;
the exit code is 1 if anything failed.

## Models

Whisper models are downloaded once, on first use, to the HuggingFace cache
(`~/.cache/huggingface`).

| Model | Download | Good for |
| --- | --- | --- |
| `tiny` | 75 MB | Quick drafts, testing |
| `base` | 145 MB | Clear speech, low resources |
| `small` | 484 MB | **Default** — the accuracy/speed sweet spot on CPU |
| `medium` | 1.5 GB | Better accuracy, noticeably slower on CPU |
| `large-v3` | 3.1 GB | Best accuracy. GPU strongly recommended |
| `turbo` | 1.6 GB | Near-`large-v3` accuracy, much faster. **Best GPU pick** |
| `distil-large-v3` | 1.5 GB | Distilled, English-only, very fast |

Add `.en` to `tiny`/`base`/`small`/`medium` for slightly better English-only
accuracy. Any HuggingFace CTranslate2 repo id or local model directory also
works.

**Speed:** on an RTX 5070 Ti, `small` transcribes 468 s of audio in 3.7 s;
the same job on CPU takes 122 s.

## Authentication for private media

Instagram reels, members-only videos, and anything else behind a login need
your browser's cookies:

```console
$ transcriber <reel-url> --cookies-from-browser firefox -f md -t
$ transcriber <reel-url> --cookies cookies.txt
```

> **Windows note:** Chrome's app-bound cookie encryption usually defeats
> `--cookies-from-browser chrome`. Use Firefox, or export a `cookies.txt` with a
> browser extension and pass `--cookies`.

## Exit codes

| Code | Meaning |
| --- | --- |
| 0 | Everything transcribed (or was already done) |
| 1 | At least one item failed — the message says why |
| 2 | Bad command-line usage |
| 130 | Interrupted with Ctrl-C |

## Development

From a checkout:

```console
$ uv sync                       # dev environment
$ uv run pytest                 # fast tests: no network, no models
$ uv run pytest -m slow         # real tiny-model smoke test (~75 MB, once)
$ uv run ruff check . && uv run ruff format .
```

CI runs the suite on Linux, macOS, and Windows across Python 3.10 and 3.12.
Python 3.10 through 3.14 are verified locally on Linux.

## License

MIT — see [LICENSE](LICENSE).

[fw]: https://github.com/SYSTRAN/faster-whisper
[uv]: https://docs.astral.sh/uv/
[deno]: https://deno.com/
[ots]: https://opentimestamps.org/
