This page covers the full build matrix. For a quick sanity build, see the Quick install section in the README. If you only want a working binary and a first transcription, start at getting-started.md instead — it picks the release asset for you and stops there.
The GitHub releases carry several Linux x86-64 tarballs.
| tarball | GPU acceleration | falls back to CPU? |
|---|---|---|
crispasr-linux-x86_64.tar.gz |
none (CPU only) | n/a — it is the CPU build |
crispasr-linux-x86_64-cpu-legacy.tar.gz |
none (generic x86-64/SSE2 CPU) | n/a |
crispasr-linux-x86_64-avx512.tar.gz |
none (AVX-512 CPU) | n/a |
crispasr-linux-x86_64-cuda.tar.gz |
NVIDIA GPU (CUDA 12) | yes — runs on CPU if CUDA libs are absent |
crispasr-linux-x86_64-cuda13.tar.gz |
NVIDIA GPU (CUDA 13) | yes — runs on CPU if CUDA libs are absent |
crispasr-linux-x86_64-hip.tar.gz |
AMD GPU (ROCm) | no |
crispasr-linux-x86_64-vulkan.tar.gz |
Vulkan GPU | no |
Since v0.8.30 the CUDA tarballs use dynamic backend loading
(GGML_BACKEND_DL): the CUDA backend is a separate shared library
(ggml-cuda.so) that the main binary loads via dlopen at runtime. If the
NVIDIA driver (libcuda.so.1) or CUDA runtime (libcudart.so.12 / .13) are absent,
the CUDA backend simply does not load and the CPU backend is used instead —
the “auto-select the best backend, fall back to CPU” behavior works as
advertised. No wrapper script is needed.
Since #405 the CUDA tarballs also ship the CPU backend as a set of
ISA-variant modules (libggml-cpu-x64.so … libggml-cpu-icelake.so); at
startup ggml scores each against the host CPU and loads the best supported
one. A pre-AVX2 host (e.g. a Sandy/Ivy Bridge Xeon next to a Tesla P40) gets
the x64/sse42/sandybridge module instead of no CPU backend at all —
v0.8.30’s single AVX2 libggml-cpu.so was refused there, which aborted every
model load with GGML_ASSERT(backend) / GGML_ASSERT(device). If no CPU
module can load, crispasr now exits with a clear “no CPU ggml backend” error
pointing at the -cpu-legacy artifact instead of aborting.
For GPU acceleration, the NVIDIA driver and CUDA toolkit must be installed on
the host (or injected into the container via --gpus / runtime: nvidia).
Installing via
mise(or another GitHub-release installer)? Those tools pick ONE asset per OS/arch — for Linux that is the plaincrispasr-linux-x86_64.tar.gz, which is an AVX2 CPU build (2013+ Intel / 2015+ AMD; it fails fast with an explanatory error on older CPUs since #380/#405 instead of dying on an illegal instruction). The CUDA / Vulkan / HIP / legacy-CPU flavors are separate assets the installer does not know about — download the tarball you need from the releases page directly, or configure your installer’s asset selection if it supports one.
The HIP and Vulkan tarballs still require their respective runtimes at link time (no CPU fallback). Use the plain CPU tarball if you need a GPU-less fallback for those.
Verify what a given tarball actually requires before deploying it:
readelf -d crispasr | grep NEEDED
Can the GPU build degrade gracefully instead? Yes, if you build it yourself:
-DGGML_BACKEND_DL=ON -DBUILD_SHARED_LIBS=ONmakes each backend adlopen-ed module, so a missing CUDA driver leaves the CUDA backend unregistered instead of killing the process. This works and is verified on Metal and CPU — see the #355 section for the measured transcripts and the two throughput caveats. The two CUDA tarballs above are already built this way; the HIP and Vulkan tarballs are still statically linked, because flipping those release legs needs an A/B on real AMD and Vulkan hardware first.
crispasr-windows-x86_64-cpu.zip targets an AVX2 + FMA baseline (Intel
Haswell 2013+ / AMD Excavator 2015+). On an older CPU — e.g. Sandy/Ivy Bridge,
which have AVX but not AVX2 — the first compute instruction raises an
illegal-instruction fault that the Windows console swallows: the program
prints its banner and exits with no output and no error (issue #380). Since
that report the CLI checks at startup and prints an explicit error instead
(CRISPASR_IGNORE_CPU_ISA=1 overrides).
Hitting that “banner, then nothing” symptom on a machine that does have AVX2? It is still a crash, and the exit code says which kind — see troubleshooting.md.
For pre-AVX2 CPUs use crispasr-windows-x86_64-cpu-legacy.zip — a generic
x86-64/SSE2-floor build (CRISPASR_PORTABLE_CPU=ON) that runs on anything
from Westmere up, just slower per core. Check with wmic cpu get name and
look the model up, or run the AVX2 build once: the new error message tells
you which features are missing.
The Windows CUDA packages bundle three NVIDIA runtime DLLs — cudart64_*.dll,
cublas64_*.dll and cublasLt64_*.dll — so they work on a host that never
added the CUDA bin directory to PATH. They also dominate the download, and
they change far less often than we cut releases. Re-fetching them for every
version is wasted bandwidth, which is painful if github.com is slow for you.
So each release ships both forms:
| asset | contains |
|---|---|
crispasr-windows-x86_64-cuda.zip |
CLI (CUDA 12), self-contained |
crispasr-windows-x86_64-cuda-non-cuda.zip |
CLI (CUDA 12), without the three DLLs |
crispasr-windows-x86_64-cuda13.zip |
CLI (CUDA 13, sm_75+, #400), self-contained |
crispasr-windows-x86_64-cuda13-non-cuda.zip |
CLI (CUDA 13), without the three DLLs |
libcrispasr-windows-x86_64-cuda.tar.gz |
shared libs + headers (CUDA 12), self-contained |
libcrispasr-windows-x86_64-cuda-non-cuda.tar.gz |
shared libs + headers (CUDA 12), without the three DLLs |
cudart64_*.dll, cublas64_*.dll, cublasLt64_*.dll |
the three DLLs of each CUDA major, on their own |
crispasr-windows-x86_64-cuda*-runtime-sha256.txt |
SHA-256 of each trio (one manifest per major) |
To upgrade without re-downloading the runtime: take the -non-cuda archive,
unpack it, and copy the three DLLs you already have next to crispasr.exe
(for the libs package, into bin\). The DLL file names carry the CUDA major
(cudart64_12.dll vs cudart64_13.dll), so a CUDA 12 trio cannot be
mistakenly installed into a CUDA 13 package or vice versa.
The executable reports the toolkit it was built and linked against and the required runtime ABI major on both diagnostic surfaces:
.\crispasr.exe --version | Select-String 'cuda'
.\crispasr.exe --diagnostics 2>&1 | Select-String 'cuda toolkit|cuda runtime ABI'
A CUDA 12 package prints cuda toolkit : 12.8... and cuda runtime ABI: 12;
the CUDA 13 package prints 13.0... and ABI 13. This identifies the binary,
not a separately installed toolkit. The self-contained zip loads its matching
major-version DLLs from beside crispasr.exe.
The Windows CUDA 12 build delay-loads the NVIDIA driver DLL used by ggml’s VMM allocator. It therefore reaches these diagnostic commands and can fall back to CPU on a driverless host, while retaining VMM when an NVIDIA GPU is available.
Each trio is published once per release and shared by that major’s
packages — sound only because every CUDA-bundling job of the same major pins
the same toolkit (12.8.0 for the CUDA 12 packages, 13.0.0 for CUDA 13).
tools/check-cuda-split-packaging.py enforces that, along with the rule that
any job bundling them must also ship a split archive and attach it to the
release. Check the SHA-256 manifest before reusing DLLs from an older download;
a CUDA version bump changes the filenames, which is your signal to re-fetch.
The Windows CUDA 13 recipe is proven in CI by
.github/workflows/win-cuda13-verify.yml: it rebuilds the exact release
package on a GPU-less windows-2022 runner, asserts the *64_13.dll wiring
(dumpbin /dependents on ggml-cuda.dll), and runs the packaged
crispasr.exe end-to-end on samples/jfk.wav — which also proves the zip’s
CPU fallback on a machine with no NVIDIA driver.
cohere backend target compiles as
C++20 via target_compile_features(cohere PUBLIC cxx_std_20))curl or wget on $PATH if you want to use -m auto auto-downloadOptional:
libavformat / libavcodec / libavutil / libswresample for
Opus / M4A / WebM ingestion (-DCRISPASR_FFMPEG=ON).libopenblas / MKL / Accelerate — speeds up the CPU-side mel-filterbank
SGEMM used by Conformer-based encoders (parakeet, canary, cohere, granite,
fastconformer-ctc). CrispASR’s own targets pick BLAS up automatically when it
is present at build time; no CrispASR flag is needed. (ggml’s separate BLAS
backend, -DGGML_BLAS=ON, still defaults OFF outside Apple.)-DGGML_CUDA=ON,
-DGGML_METAL=ON, -DGGML_VULKAN=ON, -DGGML_MUSA=ON,
-DGGML_SYCL=ON). On CUDA, set
GGML_CUDA_ENABLE_UNIFIED_MEMORY=1 at runtime to allow swapping
to system RAM when VRAM is exhausted.sherpa-onnx binaries on $PATH if you want
--diarize-method sherpa with ONNX models.No Python, PyTorch, or pip is required at runtime.
git clone --recursive https://github.com/CrispStrobe/CrispASR
cd CrispASR
# if you already cloned without --recursive:
# git submodule update --init --recursive
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
The bundled
ggml/submodule is required. A non-recursive clone leaves it empty; CMake now stops early with a message telling you to rungit submodule update --init --recursive.
The default build produces every CLI target. Binaries land in
build/bin/:
| Binary | Purpose |
|---|---|
crispasr |
Main CLI (transcribe / TTS / server) |
crispasr-quantize |
Re-quantize any GGUF model — see quantize.md |
crispasr-diff |
Per-stage cosine-similarity diff vs Python reference |
To build only the library (faster CI builds), pass
--target crispasr-lib:
cmake --build build -j$(nproc) --target crispasr-lib
The repo ships a CMakePresets.json with sensible defaults
(Release + tests off + ccache friction off):
cmake --preset default # Release
cmake --preset debug # Debug
cmake --preset linux # Release + OpenMP
cmake --build build -j$(nproc)
scripts/dev-build.sh wraps the configure + build with platform-aware
defaults (Ninja, ccache, OpenMP, mold linker on Linux):
scripts/dev-build.sh # default target
scripts/dev-build.sh --target crispasr-quantize # build a different target
scripts/dev-build.sh --reconfigure -DGGML_VULKAN=ON # extra cmake args
Two batch scripts handle the Windows build without requiring a
pre-opened Developer Command Prompt. They use vswhere.exe to locate
Visual Studio 2022 automatically, call vcvars64.bat, then drive
CMake + Ninja.
build-windows.bat — CPU buildbuild-windows.bat
Produces build\bin\crispasr.exe. Extra CMake flags can be appended:
build-windows.bat -DCRISPASR_CURL=ON :: enable libcurl fallback
build-windows.bat -DGGML_CUDA=ON :: NVIDIA GPU (CUDA must be installed)
build-windows.bat -DGGML_CUDA=ON -DCMAKE_CUDA_ARCHITECTURES=60 :: Tesla P100
Tesla P100 is a Pascal GPU with compute capability 6.0 (sm_60). Use a
CUDA 12.x toolkit when building for it; CUDA 13 no longer generates code
for Pascal GPUs.
What it does:
vswhere.exe under %ProgramFiles(x86)%\Microsoft Visual Studio\Installer\.vcvars64.bat to initialize the 64-bit MSVC environment.cmake -G Ninja -B build -DCMAKE_BUILD_TYPE=Release [extra flags].crispasr-cli target → build\bin\crispasr.exe.build-vulkan.bat — Vulkan GPU buildbuild-vulkan.bat
Produces build-vulkan\bin\crispasr.exe with the Vulkan compute backend
enabled. In addition to the VS detection above, it:
%VULKAN_SDK%. If unset, scans C:\VulkanSDK\ for the
newest installed version and sets VULKAN_SDK accordingly.-DGGML_VULKAN=ON -DGGML_CUDA=OFF so CUDA is not accidentally
pulled in if the CUDA toolkit is also installed.build-vulkan\ directory so it
coexists with a CPU build.:: Typical usage — VULKAN_SDK is picked up automatically
build-vulkan.bat
:: Override Vulkan SDK location explicitly
set VULKAN_SDK=C:\VulkanSDK\1.4.304.1
build-vulkan.bat
:: Run on Vulkan, pinned to GPU 1 (NVIDIA on a hybrid laptop)
build-vulkan\bin\crispasr.exe --gpu-backend vulkan -dev 1 -m model.gguf -f audio.wav
Important:
build-windows.bat -DGGML_CUDA=ON produces a CUDA build, not a
Vulkan build.--gpu-backend vulkan only works if the binary was actually built
with Vulkan support.0 may be the integrated GPU. Use
-dev N to pin the discrete GPU if needed.Both scripts exit with a non-zero code and a [ERROR] message if any
step fails (VS not found, CMake configure error, build error).
libcrispasr from a language binding (Rust / Go / …)These scripts build the CLI, but adding -DBUILD_SHARED_LIBS=ON also
produces libcrispasr (build\src\crispasr.lib + the DLL). Three ways to link
it from a binding:
build-windows.bat -DBUILD_SHARED_LIBS=ON [-DGGML_CUDA=ON],
then point the binding’s CRISPASR_SYS_LIB_DIR at the build\ dir (its
build.rs now finds the single-config build\src\crispasr.lib); put the
directory holding crispasr.dll on PATH.libcrispasr-windows-x86_64[-cuda].tar.gz from
Releases, extract, set
CRISPASR_SYS_LIB_DIR to the bundle root + put its bin\ on PATH.build.rs runs cmake for you (needs VS 2022
cuda/vulkan features).Exact per-OS environment is in the Rust
crispasr-sys README.
CrispASR builds against ggml’s GPU backends. Pick the one matching your hardware at configure time:
cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_CUDA=ON # NVIDIA
cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_METAL=ON # Apple Silicon
cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_VULKAN=ON # cross-vendor
cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_MUSA=ON # Moore Threads
cmake -B build -DCMAKE_BUILD_TYPE=Release -DGGML_SYCL=ON # Intel oneAPI
You can compile multiple backends into one binary; ggml will pick the
highest-priority compiled backend at runtime, in ggml’s registration order
(CUDA > Metal > SYCL > Vulkan > CPU — MUSA registers through the CUDA
slot, so it shares CUDA’s position). Force a specific backend
with --gpu-backend <name>, and pin a device with -dev N:
crispasr --gpu-backend vulkan -dev 1 -m model.gguf -f audio.wav
crispasr --gpu-backend cpu -m model.gguf -f audio.wav # benchmarking
.opus (Ogg/Opus, including WebM/Matroska Opus) and raw ADTS .aac
(AAC-LC) decode natively through the in-tree clean-room
glint decoder — no ffmpeg and no
libopus needed — via the library crispasr_audio_load API used by the
bindings. glint is RFC-conformant for Opus (all 12 RFC 6716/8251 vectors), so
this works on every platform including WASM, out of the box. A build with
-DCRISPASR_OPUS=OFF (no libopus linked at all) still decodes .opus and
WebM/Opus.
libopus + opusfile remains available as an optional Opus fallback, selected with
CRISPASR_OPUS_DECODER=libopus. It’s on by default (CRISPASR_OPUS) when the
system opusfile is found via pkg-config (e.g. apt install libopusfile-dev,
brew install opusfile), but is no longer required for any input format. On
platforms without system libs (Windows / iOS / Android / WASM), build it
statically:
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCRISPASR_OPUS_FETCH=ON
Container AAC (.m4a / .alac / .caf) decodes natively on Apple
(macOS/iOS) via AudioToolbox, or via libfdk-aac (dlopen) on Linux/Windows —
also no ffmpeg. See cli.md for the full format matrix.
.amr (AMR-NB 8 kHz) and AMR-WB 16 kHz decode via
opencore-amr (Apache-2.0) — the
standard codecs for mobile voice recordings and voicemail. On by default
(CRISPASR_AMR) when the system libraries are found via pkg-config
(apt install libopencore-amrnb-dev libopencore-amrwb-dev,
brew install opencore-amr). Without them, AMR is simply skipped and the build
succeeds — the CMake status line tells you which path was taken.
To build the decoder statically instead (no system packages — Windows, Android / Termux, iOS, WASM):
cmake -B build -DCMAKE_BUILD_TYPE=Release -DCRISPASR_AMR_FETCH=ON
registerbuild errors on clang ≥ 16 (fixed in v0.8.24). opencore-amr is 2000s-era code that declares localsregister, a storage class C++17 removed. On a toolchain whose default is C++17 — clang 16 and newer, including Termux’s — every one of those is a hard error:error: ISO C++17 does not allow 'register' storage class specifier [-Wregister](issue #314). Older defaults only warn, which is why this surfaced as a sudden break rather than a long-standing one; it is toolchain-dependent, not architecture-dependent.v0.8.24 scopes
-Wno-register(and clang’s-Wno-deprecated-register) to the two vendored codec targets, so no flag of your own is needed. On an older CrispASR the workaround isexport CXXFLAGS="$CXXFLAGS -Wno-register"— effective, but it silences the same mistake in your code too, so prefer upgrading.
For formats with no permissive native decoder (container .m4a without
libfdk-aac, WMA, exotic containers, …), build with the optional ffmpeg fallback:
# Install ffmpeg dev libs first:
# apt install libavformat-dev libavcodec-dev libavutil-dev libswresample-dev
cmake -B build-ffmpeg -DCMAKE_BUILD_TYPE=Release -DCRISPASR_FFMPEG=ON
cmake --build build-ffmpeg -j$(nproc) --target crispasr-lib
Upstream bug warning.
.m4a/.mp4/.webmcontainers currently crash CrispASR’s ffmpeg integration. For those formats, pre-convert to WAV (or, on Apple,.m4a/AAC work natively without ffmpeg):ffmpeg -i input.m4a -ar 16000 -ac 1 -c:a pcm_s16le -y /tmp/audio.wav
The pre-built binaries on some HuggingFace model cards (e.g.
bin/cohere-quantize) were built against glibc 2.38 and fail on
Ubuntu 22.04 (glibc 2.35) with:
./bin/cohere-quantize: /lib/x86_64-linux-gnu/libc.so.6:
version 'GLIBC_2.38' not found
The fix is to build from source — CrispASR has no glibc minimum version of its own, so it builds cleanly against whatever glibc your distro ships.
git clone --recursive https://github.com/CrispStrobe/CrispASR
cd CrispASR
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build -j$(nproc)
ls build/bin/crispasr-quantize
CrispASR builds natively under Termux on aarch64
Android devices. Use a static build to avoid linker conflicts with
system-installed libggml.so from the whisper-cli package (#137):
pkg install build-essential cmake git
git clone https://github.com/CrispStrobe/CrispASR
cd CrispASR
cmake -B build -DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=OFF \
-DCRISPASR_BUILD_TESTS=OFF
cmake --build build -j$(nproc)
Why static? Termux’s whisper-cli package installs an older
libggml.so into $PREFIX/lib. The dynamic linker finds it before the
locally built version, causing cannot locate symbol errors at runtime.
Static linking (-DBUILD_SHARED_LIBS=OFF) embeds all ggml code directly
into the binary, eliminating the conflict entirely.
Strip debug symbols to reduce binary size:
strip build/bin/crispasr*
Termux clang is new enough to default to C++17, which matters if you enable
the statically-built AMR decoder (-DCRISPASR_AMR_FETCH=ON): the vendored
opencore-amr sources use the register storage class that C++17 removed. Fixed
in v0.8.24 — see AMR-NB / AMR-WB support
if you are building an older tag (#314).
To cross-compile from a Linux or macOS host for Android deployment
(e.g. embedding libcrispasr.so in an Android app), use the provided
build-android.sh script. This requires the
Android NDK installed on the host:
export ANDROID_NDK_HOME=/path/to/android-ndk
./build-android.sh # all ABIs (arm64-v8a, armeabi-v7a, x86_64)
./build-android.sh --abi arm64-v8a # single ABI
./build-android.sh --vulkan # with Vulkan GPU support
Output lands in build-android/<ABI>/src/libcrispasr.so.
This is not the same as building inside Termux. The NDK cross-compiler produces binaries linked against Android’s bionic libc, suitable for embedding in Android apps via JNI. Termux uses its own linker and packages — use the native Termux build above instead.
GGML_BACKEND_DL (#355)-DGGML_BACKEND_DL=ON -DBUILD_SHARED_LIBS=ON now configures, links and runs.
It is opt-in: the default build is unchanged. The two Linux CUDA release tarballs
now ship with it enabled; the rest are still statically linked (see “flipping the
release leg” below).
Three things blocked it, all now resolved:
ggml-cuda / ggml-metal
explicitly (125 sites), and under DL those are MODULE targets that cannot
be linked. They now route through crispasr_link_ggml_* interface targets
that are empty in a DL build and the real backend otherwise. ✅ggml_backend_cpu_init, ggml_backend_is_cpu, ggml_backend_cpu_set_n_threads,
ggml_backend_cpu_buffer_type, ggml_backend_cpu_reg, ggml_backend_is_metal
and ggml_backend_cpu_set_threadpool are not linkable. All 426 call sites go
through src/core/ggml_cpu_backend.h, whose non-DL branch is the identical
direct call. ✅ggml_graph_compute,
ggml_graph_compute_with_ctx, ggml_graph_plan, ggml_threadpool_new /
_free and ggml_get_type_traits_cpu, across ~23 sites. These now go
through the same header, which under DL routes them to a thread_local CPU
backend obtained from the registry (thread_local because a ggml backend is
not safe for concurrent use and several of these sites run on worker
threads). ✅tests/test-cpu-backend-shim.cpp is the equivalence gate: the same 7 cases
compile unchanged in both modes and assert arithmetic, not just return codes.
Both report 27 assertions in 7 test cases.
Measured on an M1 with parakeet-tdt-0.6b-v3-q4_k + Silero VAD over a 300 s
FLEURS clip, all four runs producing 608 words:
| build | device | transcript |
|---|---|---|
| default | Metal | X |
DL, libggml-metal.so present |
Metal | X — byte-identical |
default, -ng |
CPU | Y |
DL, libggml-metal.so removed |
CPU | Y — byte-identical |
X and Y differ in two tokens. That is the ordinary CPU-vs-Metal reduction-order
divergence — it is present in the default build too, which is exactly what the
-ng row is there to show. DL itself changes nothing.
Removing the module is the #355 scenario in miniature: the process does not die,
it logs load_backend: loaded CPU backend and transcribes.
Two limitations keep this opt-in rather than default. ggml’s CPU registry
does not expose the threadpool setter through get_proc_address (only
set_n_threads — see ggml_backend_cpu_get_proc_address), so a DL build cannot
install the shared worker pool and falls back to ggml’s own per-call threading.
For the same reason ggml_graph_plan has no DL equivalent, so the hot paths
that size a work buffer once and reuse it across frames re-plan per call
instead. Neither is a correctness issue and neither has been measured; both are
throughput risks on the per-frame VAD and wav2vec2 paths.
tests/test_ggml_audio_ops_* are not built under DL. They call
ggml_backend_metal_init() by symbol on purpose — naming one exact backend with
no scheduler fallback is the point of those tests — and routing them through the
registry would pick “best available” instead.
The -cuda and -cuda13 release legs now build with
-DBUILD_SHARED_LIBS=ON -DGGML_BACKEND_DL=ON. Flipping -hip and -vulkan too
still needs an A/B on real AMD and Vulkan hardware; only Metal and CPU are
verified above.