Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Getting started

Scenario

You have never run gigastt and want a working local transcription in about five minutes: install the binary, download the GigaAM v3 model, transcribe a first audio file — on macOS, Linux, or in Docker. This chapter is the whole path; you should not need any other document to get here.

Prerequisites

  • Disk: ~225 MB model; plan ~250–400 MB with the binary (optional punct/VAD side models extra).
  • RAM: ~46 / ~66 MB resident at --pool-size 1 / 2 (~277 / ~510 MB ps RSS). Method: docs/benchmarks.md.
  • Network (unless you follow the air-gapped recipe): reach github.com for the pre-quantized INT8 bundle (CTC heads use HuggingFace INT8).
  • An audio file to transcribe — WAV (incl. G.711/G.722/GSM), M4A, MP3, OGG/Vorbis, OGG/Opus (.opus), WebM/Opus, or FLAC. The repo ships a 4 s Russian fixture: crates/gigastt/tests/fixtures/golos_00.wav. Any short Russian recording works. Files → this chapter / REST. Live partials → Streaming.
  • Only for cargo install (build from source): Rust 1.94+ and protoc on PATH (brew install protobuf / apt install protobuf-compiler).

Pick one recipe below — macOS, Linux, Windows, Docker, or air-gapped — then read Choosing the recognition head and What the first run costs once.

Recipe: macOS (Homebrew)

Homebrew is the fastest path on Apple Silicon (the tap ships a CoreML-enabled binary). On an Intel Mac use cargo install gigastt instead — see the Linux recipe for the protoc prerequisite.

brew tap ekhodzitsky/gigastt https://github.com/ekhodzitsky/gigastt
brew install gigastt

# Fetch the model (~225 MB pre-quantized INT8 bundle by default —
# see "What the first run costs" below):
gigastt download

# Transcribe your first file:
gigastt transcribe recording.wav

Verify: the last command prints the recognized text on stdout, e.g.

$ gigastt transcribe recording.wav
Привет, как дела?

and ls ~/.gigastt/models/ shows v3_rnnt_encoder_int8.onnx, v3_rnnt_decoder.onnx, v3_rnnt_joint.onnx, and v3_vocab.txt.

Recipe: Linux (prebuilt binary or cargo)

Option A — prebuilt binary (no Rust toolchain, no protoc). Each release publishes tarballs for x86_64-unknown-linux-gnu and aarch64-unknown-linux-gnu:

# Resolve the latest release tag (or set TAG=v2.21.0 by hand):
TAG=$(curl -fsSL https://api.github.com/repos/ekhodzitsky/gigastt/releases/latest \
      | sed -n 's/.*"tag_name": *"\([^"]*\)".*/\1/p')
VER=${TAG#v}

curl -fLO "https://github.com/ekhodzitsky/gigastt/releases/download/${TAG}/gigastt-${VER}-x86_64-unknown-linux-gnu.tar.gz"
curl -fLO "https://github.com/ekhodzitsky/gigastt/releases/download/${TAG}/gigastt-${VER}-x86_64-unknown-linux-gnu.tar.gz.sha256"
sha256sum -c "gigastt-${VER}-x86_64-unknown-linux-gnu.tar.gz.sha256"

tar xf "gigastt-${VER}-x86_64-unknown-linux-gnu.tar.gz"
sudo install -m 0755 gigastt /usr/local/bin/gigastt

(On ARM64 replace x86_64-unknown-linux-gnu with aarch64-unknown-linux-gnu. Homebrew on Linux x86_64 — brew install gigastt after the tap from the macOS recipe — works too.)

Option B — cargo (any platform, needs Rust 1.94+ and protoc):

sudo apt install protobuf-compiler   # Debian/Ubuntu; skip if protoc exists
cargo install gigastt

Then fetch the model — the lean way, a ~225 MB pre-quantized INT8 bundle from the pinned GitHub Release (no ~844 MB FP32 download, no ~2-minute on-device quantization; also handy when HuggingFace is unreachable but GitHub is not):

gigastt download
gigastt transcribe recording.wav

Verify: gigastt transcribe recording.wav prints the recognized text on stdout, and ls ~/.gigastt/models/ shows the v3_rnnt_* model files.

Recipe: Windows (prebuilt binary)

Every release publishes x86_64-pc-windows-msvc tarballs (CPU). PowerShell 5.1+ / Windows 10+ includes tar and curl:

$rel = Invoke-RestMethod https://api.github.com/repos/ekhodzitsky/gigastt/releases/latest
$TAG = $rel.tag_name          # e.g. v2.21.0
$VER = $TAG.TrimStart('v')
$asset = "gigastt-$VER-x86_64-pc-windows-msvc.tar.gz"
$base = "https://github.com/ekhodzitsky/gigastt/releases/download/$TAG"

Invoke-WebRequest "$base/$asset" -OutFile $asset
Invoke-WebRequest "$base/$asset.sha256" -OutFile "$asset.sha256"
# Optional integrity check (hash file is "HASH  filename"):
$expected = (Get-Content "$asset.sha256").Split()[0]
$actual = (Get-FileHash $asset -Algorithm SHA256).Hash.ToLower()
if ($actual -ne $expected.ToLower()) { throw "SHA-256 mismatch" }

tar xf $asset
# Put gigastt.exe on PATH, or call it by full path:
.\gigastt.exe download
.\gigastt.exe transcribe recording.wav

Model directory on Windows defaults under the user profile (%USERPROFILE%\.gigastt\models\). First serve still binds loopback only (127.0.0.1:9876) until you pass --bind-all.

Verify: .\gigastt.exe transcribe recording.wav prints text; health after .\gigastt.exe serve answers at http://127.0.0.1:9876/health.

Recipe: Docker

Prebuilt multi-arch images (amd64 + arm64) are published to GHCR for every release; -cuda tags carry the CUDA variant:

docker pull ghcr.io/ekhodzitsky/gigastt:latest   # pin :<version> in production

docker run -d --name gigastt \
  -p 127.0.0.1:9876:9876 \
  -v gigastt-models:/home/gigastt/.gigastt/models \
  ghcr.io/ekhodzitsky/gigastt:latest

The named volume keeps the model across container restarts; without it the container re-downloads ~225 MB on every recreation. On first start the container downloads the model — the port binds immediately, but inference is only up when /ready turns green:

# Wait until the model is loaded (503 while initializing):
until curl -sf http://127.0.0.1:9876/ready > /dev/null; do sleep 5; done

curl http://127.0.0.1:9876/health

Then transcribe a file from the host (the file path is on the host — curl reads it, not the container):

curl -F file=@recording.wav http://127.0.0.1:9876/v1/transcribe

Verify: /health returns

{"status":"ok","model":"gigaam-v3-rnnt","variant":"rnnt","version":"2.21.0","punctuation":true,"itn":true}

(the version field reflects the image you pulled), and the POST returns a JSON transcript:

{"text":"Привет, как дела?","words":[{"word":"привет","start":0.0,"end":0.4,"confidence":0.99}],"duration":1.2}

Recipe: air-gapped (offline bundle)

For hosts with no internet access, every release publishes a self-contained offline bundle per Linux target — binary + pre-quantized INT8 rnnt model + punctuation model + systemd unit + installer — plus two Debian packages with the same content. Download them on a connected machine, carry them over, install.

Tarball flow (any distro):

# On a connected machine (see the Linux recipe for resolving TAG/VER):
curl -fLO "https://github.com/ekhodzitsky/gigastt/releases/download/${TAG}/gigastt-${VER}-offline-x86_64-unknown-linux-gnu.tar.gz"
curl -fLO "https://github.com/ekhodzitsky/gigastt/releases/download/${TAG}/gigastt-${VER}-offline-x86_64-unknown-linux-gnu.tar.gz.sha256"
sha256sum -c "gigastt-${VER}-offline-x86_64-unknown-linux-gnu.tar.gz.sha256"

# On the target machine:
mkdir gigastt-offline && tar xf "gigastt-${VER}-offline-x86_64-unknown-linux-gnu.tar.gz" -C gigastt-offline && cd gigastt-offline
sudo ./install.sh                      # verifies SHA256SUMS, installs binary + model + unit
sudo systemctl enable --now gigastt

Debian flow: install gigastt_<ver>_amd64.deb (binary + unit) together with gigastt-model-int8_<ver>_all.deb (the same model set), then sudo systemctl enable --now gigastt.

The bundle deliberately omits optional pieces — speaker diarization and the e2e_rnnt / ml_ctc heads. The installed unit runs with GIGASTT_OFFLINE=1, so a missing optional model is a fast, instructive error naming the exact path to fill (fetch it on a connected machine with gigastt download and copy the file over), never a network timeout. The full contents list and signature verification are in packaging/offline/README-OFFLINE.md.

Verify: curl http://127.0.0.1:9876/health returns {"status":"ok",...} with "model":"gigaam-v3-rnnt", and gigastt transcribe sample.wav --model-dir /usr/share/gigastt/models prints text (the flag is only needed when running uninstalled — the systemd unit already points at the installed model).

Choosing the recognition head

gigastt ships four recognition heads; --model-variant picks one at download / serve / transcribe time. When you omit the flag, an existing model directory is used as-is (auto-detect), and a fresh install defaults to rnnt.

HeadLanguagesOutput stylePick it when
rnnt (default)RussianBare lowercase from the acoustic model; casing + punctuation restored by an auto-downloaded RuPunct pass, digits by ITNDefault: lowest WER on Russian speech
e2e_rnntRussianPunctuation / casing / ITN baked into the acoustic modelYou want one self-contained model with no post-processing passes
ml_ctcru/en/kk/ky/uzBare lowercase, no restoration passesMixed Russian/English (or kk/ky/uz) speech; faster than rnnt (RTF ~0.032 vs ~0.043; ready RSS ≈ rnnt)
ml_ctc_largeru/en/kk/ky/uzBare lowercase, no restoration passesMultilingual speech where accuracy matters more than footprint (600M encoder)

The ml_ctc* heads download pre-quantized INT8 directly, so there is no quantization step for them. Switching heads after install:

gigastt download --model-variant e2e_rnnt   # fetch another head
gigastt serve --model-variant e2e_rnnt      # and serve it explicitly

WER/RTF numbers per head are in docs/benchmarks.md; the deeper model/backend tour is in Models and backends.

What the first run costs

The very first gigastt download (or first gigastt serve, which auto-downloads a missing model) fetches a ~225 MB pre-quantized INT8 bundle from the pinned GitHub Release: SHA-256-verified, staged to .partial, atomically renamed. No FP32 download, no on-device quantization, no protoc.

Note it pulls from github.com, not huggingface.co — useful when one of the two is blocked.

Runtime is INT8 only — there is no FP32 download or FP32 engine path.

If you skip a manual download, the first serve does it for you. The port binds immediately; /health answers 200 with "model":"loading" and /ready returns 503 {"status":"not_ready","reason":"initializing"} until the model is usable, so clients should gate on /ready, never on the process being alive.

Verifying the result

End-to-end checklist that works after any of the recipes above:

# 1. Model files are in place:
ls ~/.gigastt/models/
#   v3_rnnt_encoder_int8.onnx  v3_rnnt_decoder.onnx  v3_rnnt_joint.onnx  v3_vocab.txt  ...

# 2. Offline transcription works (no server needed):
gigastt transcribe crates/gigastt/tests/fixtures/golos_00.wav
#   → prints the recognized text on stdout

# 3. The server comes up and reports the loaded head:
gigastt serve &                      # Ctrl-C to stop; default http://127.0.0.1:9876
curl http://127.0.0.1:9876/ready     # 200 once the model is loaded
curl http://127.0.0.1:9876/health
#   {"status":"ok","model":"gigaam-v3-rnnt","variant":"rnnt","version":"...","punctuation":true,"itn":true}

# 4. REST transcription works:
curl -F file=@crates/gigastt/tests/fixtures/golos_00.wav http://127.0.0.1:9876/v1/transcribe
#   → {"text":"...","words":[...],"duration":N}

Common pitfalls

  • protoc not found during cargo install or a source build — install the Protocol Buffers compiler (brew install protobuf / apt install protobuf-compiler), or skip the toolchain entirely with the prebuilt binary / Homebrew.
  • First serve sits there for a while — that is the one-time model download, not a hang: /health returns {"model":"loading"} meanwhile. Pre-seed with gigastt download and gate clients on /ready.
  • Address already in use on port 9876 — find the holder with lsof -nP -tiTCP:9876 -sTCP:LISTEN; confirm it is gigastt (ps -p <pid> -o command=), then kill <pid> (SIGTERM drains cleanly), or start on another port with --port.
  • Model download fails or hangs (proxy, firewall, HuggingFace unreachable) — retry gigastt download; the resume-safe staging file makes it idempotent, and exit codes distinguish causes (65 = checksum, 69 = network, 74 = disk). If huggingface.co is blocked but github.com is not, use gigastt download; in a fully closed contour use the air-gapped bundle. Check ~/.gigastt/models/ permissions on disk errors.
  • OOM or heavy swap on startup — use --pool-size 1 on small machines. RAM figures: docs/benchmarks.md.

The full symptom → cause → fix table lives in docs/troubleshooting.md.