Skip to content

megabyde/webinar-transcriber

Repository files navigation

Webinar Transcriber

CI Python 3.12+ Coverage 100% Ruff uv License MIT

Webinar Transcriber preview

Contents

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.

Install

Prerequisites

Install from PyPI

Install the published package as a standalone CLI:

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:

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

uv tool install --reinstall .

To remove the installed tool:

uv tool uninstall webinar-transcriber

Cloud LLM extra

Provider-backed report refinement (--llm, see 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:

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, a C/C++ compiler, and a working CUDA toolkit with nvcc on PATH and CUDA_HOME set.

Install the CLI tool with CUDA support:

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

If the build fails, see CUDA install fails. For a CUDA-enabled development checkout, see Development.

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.

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

OPENAI_API_KEY=... \
    OPENAI_MODEL=<openai-model> \
    webinar-transcriber INPUT --llm
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.

Speaker diarization

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

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.

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.

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:

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.

Reference

Output layout

Successful runs can write:

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. Coding conventions, testing notes, and the Definition of Done live in AGENTS.md.

About

Local-first Python CLI that turns webinar audio and slide videos into transcripts, reports, scenes, diagnostics, and optional LLM-polished notes.

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Contributors