Metadata-Version: 2.4
Name: webinar-transcriber
Version: 1.3.0
Summary: Local-first CLI for transcribing webinar videos and audio recordings.
Project-URL: Homepage, https://github.com/megabyde/webinar-transcriber#readme
Project-URL: Repository, https://github.com/megabyde/webinar-transcriber
Project-URL: Issues, https://github.com/megabyde/webinar-transcriber/issues
Project-URL: Releases, https://github.com/megabyde/webinar-transcriber/releases
Author: Yury Bayda
License: MIT License
        
        Copyright (c) 2026 Yury Bayda
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
License-File: LICENSE-3RDPARTY.md
Keywords: audio,speech-to-text,transcription,video,webinar,whisper.cpp
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: MacOS
Classifier: Operating System :: Microsoft :: Windows
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Classifier: Topic :: Multimedia :: Video
Classifier: Topic :: Utilities
Requires-Python: >=3.12
Requires-Dist: av<18.0.0,>=17.1.0
Requires-Dist: click<9.0.0,>=8.4.1
Requires-Dist: numpy<3.0.0,>=2.4.6
Requires-Dist: pillow<13.0.0,>=12.1.1
Requires-Dist: python-docx<2.0.0,>=1.2.0
Requires-Dist: pywhispercpp<2.0.0,>=1.5.0
Requires-Dist: rich<15.0.0,>=14.3.3
Requires-Dist: sherpa-onnx-core<1.14.0,>=1.13.3
Requires-Dist: sherpa-onnx<1.14.0,>=1.13.3
Provides-Extra: llm
Requires-Dist: instructor[anthropic]<2.0.0,>=1.15.1; extra == 'llm'
Requires-Dist: pydantic<3.0.0,>=2.13.4; extra == 'llm'
Requires-Dist: tenacity<10.0.0,>=9.1.4; extra == 'llm'
Description-Content-Type: text/markdown

# Webinar Transcriber

[![CI](https://github.com/megabyde/webinar-transcriber/actions/workflows/ci.yml/badge.svg)](https://github.com/megabyde/webinar-transcriber/actions/workflows/ci.yml)
[![Python 3.12+](https://img.shields.io/badge/python-3.12%2B-3776AB?logo=python&logoColor=white)](https://www.python.org/downloads/)
[![Coverage 100%](https://img.shields.io/badge/coverage-100%25-brightgreen)](https://github.com/megabyde/webinar-transcriber/actions/workflows/ci.yml)
[![Ruff](https://img.shields.io/badge/lint-ruff-D7FF64?logo=ruff&logoColor=1D2B34)](https://docs.astral.sh/ruff/)
[![uv](https://img.shields.io/badge/package-uv-5C5CFF?logo=uv&logoColor=white)](https://docs.astral.sh/uv/)
[![License MIT](https://img.shields.io/badge/license-MIT-2F855A)](LICENSE)

![Webinar Transcriber preview](docs/assets/social-preview.png#gh-light-mode-only)
![Webinar Transcriber preview](docs/assets/social-preview-dark.png#gh-dark-mode-only)

## Contents

- [Overview](#overview)
- [Install](#install)
- [Usage](#usage)
- [Advanced Usage](#advanced-usage)
- [Troubleshooting](#troubleshooting)
- [Reference](#reference)
- [Development](#development)

## Overview

`webinar-transcriber` turns webinar recordings into transcripts, structured notes, diagnostics, and
machine-readable report artifacts. It accepts audio-only files and slide-based video. Video runs add
scene detection and representative frames; audio-only runs keep the same transcript and report
contract without visual context.

`webinar-transcriber` is local-first: speech detection, transcription, window reconciliation, and
report sectioning all run on your machine with local models and heuristics. Optional LLM refinement
runs only after that deterministic report exists; it polishes section text and refines titles,
summaries, action items, and section TL;DRs, but never replaces the base pipeline.

For per-stage detail and the artifact each stage produces, see [docs/pipeline.md](docs/pipeline.md).

## Install

### Prerequisites

- [Python 3.12+](https://www.python.org/downloads/) and
  [uv](https://docs.astral.sh/uv/getting-started/installation/)

### Install from PyPI

Install the published package as a standalone CLI:

```bash
uv tool install webinar-transcriber
```

Or with `pipx`, or into the current environment with `pip` (add the `llm` extra for cloud LLM
refinement):

```bash
pipx install webinar-transcriber
pip install "webinar-transcriber[llm]"
```

### Install from a GitHub release

Pin a tagged release directly from GitHub when you want a fixed version and do not need a checkout:

```bash
uv tool install --reinstall git+https://github.com/megabyde/webinar-transcriber.git@v1.2.0
```

Replace `v1.2.0` with the release tag you want. Wheel and source distribution files are also
attached to the [GitHub Releases](https://github.com/megabyde/webinar-transcriber/releases) page.

### Install the CLI from this checkout

From the repository root, run the target that matches the runtime you need:

| Command             | Installs                                                |
| ------------------- | ------------------------------------------------------- |
| `make install`      | Standard local CLI install.                             |
| `make install-llm`  | CLI plus optional OpenAI/Anthropic LLM dependencies.    |
| `make install-cuda` | CLI with `pywhispercpp` rebuilt from source for NVIDIA. |
| `make uninstall`    | Removes the installed `webinar-transcriber` uv tool.    |

`make install` registers `webinar-transcriber` as a uv tool from the local source tree. No virtual
environment activation is needed. Re-run the install target after pulling changes when the installed
command should track the checkout.

> [!TIP]
> Without `make`, install the local checkout with uv directly:
>
> ```bash
> uv tool install --reinstall .
> ```

Run `make help` to list every project target.

The default `large-v3-turbo` Whisper model downloads on the first transcription run, not during
installation.

### NVIDIA CUDA

> [!CAUTION]
> CUDA installs rebuild `pywhispercpp` locally and depend on the host CUDA toolkit. Use the standard
> install unless you specifically need NVIDIA acceleration.

CUDA is the only supported path that builds `pywhispercpp` from source. It requires
[CMake](https://cmake.org/download/), a C/C++ compiler, and a working
[CUDA toolkit](https://developer.nvidia.com/cuda-downloads) with `nvcc` on `PATH` and `CUDA_HOME`
set.

- `make install-cuda` installs the CLI tool with CUDA support.
- `make sync-cuda` prepares the checkout development environment with CUDA support.

If the build fails, see [CUDA install fails](docs/troubleshooting.md#cuda-install-fails).

## Usage

### Quick start

By default, each input gets a fresh run directory under `runs/`. Multiple inputs are processed
sequentially. `--output-dir` is allowed only with one input.

Any container PyAV can decode is accepted, including common formats such as `.mp4`, `.mkv`, `.mov`,
`.webm`, `.mp3`, `.wav`, and `.m4a`.

> [!TIP]
> Use a fresh `--output-dir` for reproducible comparisons. Existing output directories are refused,
> not overwritten.

```bash
webinar-transcriber INPUT
webinar-transcriber INPUT1 INPUT2 INPUT3
webinar-transcriber INPUT --keep-audio
webinar-transcriber INPUT --output-dir runs/custom-demo
```

### Cloud LLM

`--llm` enables provider-backed report refinement after deterministic sectioning. The LLM step can
polish section transcript text with light cleanup and paragraphing, and refine summary bullets,
action items, section titles, and section TL;DRs. Supported providers are `openai` and `anthropic`;
OpenAI is the default.

The base install does not include provider SDKs. Install the LLM extra first:

```bash
make install-llm
```

> [!IMPORTANT]
> `--llm` sends report text and transcript excerpts to the configured provider. Do not use it for
> recordings that must stay entirely local.

Configure the provider with environment variables:

- `LLM_PROVIDER`: `openai` (default) or `anthropic`.
- `OPENAI_API_KEY` / `OPENAI_MODEL`: API key and model identifier for the OpenAI provider.
- `ANTHROPIC_API_KEY` / `ANTHROPIC_MODEL`: API key and model identifier for the Anthropic provider.

The CLI does not pin a default model name for either provider; pass any model the provider supports.

```bash
OPENAI_API_KEY=... \
    OPENAI_MODEL=<openai-model> \
    webinar-transcriber INPUT --llm
```

```bash
LLM_PROVIDER=anthropic \
    ANTHROPIC_API_KEY=... \
    ANTHROPIC_MODEL=<anthropic-model> \
    webinar-transcriber INPUT --llm
```

For missing environment variables, missing extras, or unsupported provider names, see
[Troubleshooting](docs/troubleshooting.md).

### Speaker diarization

Pass `--diarize` to label transcript segments with anonymous local speaker IDs:

```bash
webinar-transcriber INPUT --diarize
webinar-transcriber INPUT --diarize --diarize-speakers 4
```

> [!WARNING]
> Pass `--diarize-speakers` only when the exact speaker count is known. A wrong count can force poor
> speaker labels. Omit the option to let Sherpa estimate the count.

Diarization runs locally through `sherpa-onnx` and does not use an API key. The first diarized run
downloads the segmentation and speaker-embedding models into
`~/.cache/webinar-transcriber/diarization`. Set `WEBINAR_DIARIZATION_CACHE_DIR` to override that
cache directory.

When diarization is enabled, reports label each speaker turn with stable anonymous labels ordered by
first appearance in the timeline: `S1`, `S2`, and so on (one label per turn, even when a turn spans
several paragraphs). JSON artifacts include a `speaker` field on transcript segments and a separate
`diarization.json` file with raw speaker turns. If labels look wrong, see
[Poor diarization labels](docs/troubleshooting.md#poor-diarization-labels).

## Advanced Usage

### ASR model

`webinar-transcriber` uses `pywhispercpp` to resolve whisper.cpp models. By default it uses
`large-v3-turbo` (downloaded on the first run, as noted in [Install](#install)). You can pass
another model identifier or a local GGML model path with `--asr-model`.

```bash
webinar-transcriber INPUT --asr-model large-v3-turbo
webinar-transcriber INPUT --asr-model large-v3
webinar-transcriber INPUT --asr-model models/whisper-cpp/ggml-large-v3-turbo.bin
```

To manage the model file yourself, download it directly:

```bash
mkdir -p models/whisper-cpp
curl -L \
    -o models/whisper-cpp/ggml-large-v3-turbo.bin \
    https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-large-v3-turbo.bin
```

Use `--asr-model large-v3` when transcription accuracy matters more than local runtime.

### ASR controls

The default ASR path uses the selected `whisper.cpp` model, automatic language detection, and an
automatically selected thread count.

- `--language CODE`: force a Whisper language code such as `en` or `ru`.
- `--threads N`: set the CPU worker count passed to `whisper.cpp`.

GPU-enabled builds can offload supported model work to the GPU, but `whisper.cpp` still uses CPU
threads for scheduling, language detection, and non-offloaded work. The same `--threads` value is
also used by local VAD, local diarization, and concurrent LLM section polishing. By default, the CLI
uses the host CPU count capped at 8. Lower it when the machine needs CPU capacity for other work.

## Troubleshooting

Common errors and their fixes, indexed by the message the CLI prints, live in
[docs/troubleshooting.md](docs/troubleshooting.md).

## Reference

### Output layout

Successful runs can write:

```text
runs/<timestamp>_<basename>/
├─ metadata.json             # probed media type, duration, streams
├─ transcript.json           # reconciled transcript with timestamps and optional speakers
├─ report.md
├─ report.docx
├─ report.json               # final report in markdown, docx, and json
├─ diagnostics.json          # stage timings, counts, warnings, ASR and optional LLM info
├─ asr/
│  ├─ speech_regions.json    # VAD ranges
│  └─ decoded_windows.json   # per-window decode output
├─ diarization.json          # anonymous speaker turns; --diarize only
├─ scenes.json               # scene boundaries; video only
├─ frames/                   # representative frames; video only
└─ transcription-audio.mp3   # normalized audio copy; --keep-audio only
```

Failed runs still write `diagnostics.json` with the failed stage and any partial intermediate
artifacts already produced, as long as the run directory exists.

## Development

Checkout setup, running from source, the make target reference, and the quality gate live in
[docs/development.md](docs/development.md). Coding conventions, testing notes, and the Definition of
Done live in [AGENTS.md](AGENTS.md).
