Metadata-Version: 2.4
Name: webinar-transcriber
Version: 1.3.1
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: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
Classifier: Topic :: Multimedia :: Video
Classifier: Topic :: Utilities
Requires-Python: >=3.12
Requires-Dist: av<19.0.0,>=17.1.0
Requires-Dist: click<9.0.0,>=8.4.2
Requires-Dist: numpy<3.0.0,>=2.5.0
Requires-Dist: pillow<13.0.0,>=12.2.0
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.4
Requires-Dist: sherpa-onnx-core==1.13.3
Requires-Dist: sherpa-onnx==1.13.3
Provides-Extra: llm
Requires-Dist: instructor[anthropic]<2.0.0,>=1.15.3; 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)](https://github.com/megabyde/webinar-transcriber/blob/main/LICENSE)

<picture>
  <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/megabyde/webinar-transcriber/main/docs/assets/social-preview-dark.png">
  <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/megabyde/webinar-transcriber/main/docs/assets/social-preview.png">
  <img alt="Webinar Transcriber preview" src="https://raw.githubusercontent.com/megabyde/webinar-transcriber/main/docs/assets/social-preview.png">
</picture>

## 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
[Pipeline](https://github.com/megabyde/webinar-transcriber/blob/main/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
```

`pipx install webinar-transcriber` works the same way. `pip install webinar-transcriber` installs
into the current environment instead of as an isolated tool.

### 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.3.0
```

Replace `v1.3.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, install the local source tree as a uv tool. This registers
`webinar-transcriber` from the checkout; no virtual environment activation is needed. Re-run the
command after pulling changes when the installed command should track the checkout.

```bash
uv tool install --reinstall .
```

To remove the installed tool:

```bash
uv tool uninstall webinar-transcriber
```

### Cloud LLM extra

Provider-backed report refinement (`--llm`, see [Cloud LLM](#cloud-llm)) needs the OpenAI and
Anthropic SDKs, which the base install omits. Append the `llm` extra to the package spec in
whichever install command above you used. `--reinstall` applies the extra whether or not the package
is already installed:

```bash
uv tool install --reinstall "webinar-transcriber[llm]"   # from PyPI
uv tool install --reinstall ".[llm]"                     # from a checkout
```

For a GitHub release, append the extra in the direct-reference form:
`"webinar-transcriber[llm] @ git+https://github.com/megabyde/webinar-transcriber.git@v1.3.0"`.

### 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.

Install the CLI tool with CUDA support:

```bash
GGML_CUDA=1 uv tool install --reinstall . \
    --reinstall-package pywhispercpp \
    --no-binary-package pywhispercpp
```

If the build fails, see
[CUDA install fails](https://github.com/megabyde/webinar-transcriber/blob/main/docs/troubleshooting.md#cuda-install-fails).
For a CUDA-enabled development checkout, see
[Development](https://github.com/megabyde/webinar-transcriber/blob/main/docs/development.md).

## 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.

The CLI accepts any container PyAV can decode when it contains an audio stream, including `.mp4`,
`.mkv`, `.mov`, `.webm`, `.mp3`, `.wav`, and `.m4a`. A video stream is optional; when present, it
adds scene detection and representative frames.

> [!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.

This step needs provider SDKs that the base install omits. Install them with the `llm` extra (see
[Cloud LLM extra](#cloud-llm-extra) under Install).

> [!IMPORTANT]
> `--llm` sends report text, section timing metadata, and transcript excerpts to the configured
> provider. It does not send the local source path. 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](https://github.com/megabyde/webinar-transcriber/blob/main/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](https://github.com/megabyde/webinar-transcriber/blob/main/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 transcription run, not during installation). 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
[Troubleshooting](https://github.com/megabyde/webinar-transcriber/blob/main/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
[Development](https://github.com/megabyde/webinar-transcriber/blob/main/docs/development.md). Coding
conventions, testing notes, and the Definition of Done live in
[AGENTS.md](https://github.com/megabyde/webinar-transcriber/blob/main/AGENTS.md).
