Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 50 additions & 30 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ cmake_minimum_required(VERSION 3.26)
# nemo_speech_tts_version) stay in sync without a hardcoded literal.
file(STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/VERSION" _nemo_speech_version_lines)
foreach(_line ${_nemo_speech_version_lines})
if(_line MATCHES "^NEMO_SPEECH_VERSION:[ \t]*([0-9]+\\.[0-9]+\\.[0-9]+)")
set(NEMO_SPEECH_VERSION "${CMAKE_MATCH_1}")
if(_line MATCHES
"^NEMO_SPEECH_VERSION:[ \t]*([0-9]+\\.[0-9]+\\.[0-9]+)([-+][0-9A-Za-z.-]+)?[ \t]*$")
set(NEMO_SPEECH_VERSION "${CMAKE_MATCH_1}${CMAKE_MATCH_2}")
set(NEMO_SPEECH_PROJECT_VERSION "${CMAKE_MATCH_1}")
endif()
endforeach()
if(NOT NEMO_SPEECH_VERSION)
if(NOT NEMO_SPEECH_VERSION OR NOT NEMO_SPEECH_PROJECT_VERSION)
message(FATAL_ERROR "could not parse NEMO_SPEECH_VERSION from ${CMAKE_CURRENT_SOURCE_DIR}/VERSION")
endif()

project(nemo_speech VERSION ${NEMO_SPEECH_VERSION} LANGUAGES C CXX)
project(nemo_speech VERSION ${NEMO_SPEECH_PROJECT_VERSION} LANGUAGES C CXX)
add_compile_definitions(NEMO_SPEECH_VERSION_STR="${NEMO_SPEECH_VERSION}")

include(GNUInstallDirs)
Expand All @@ -35,6 +37,14 @@ install(DIRECTORY docs/
DESTINATION "${CMAKE_INSTALL_DATADIR}/doc/nemo-speech/docs")
install(DIRECTORY config/
DESTINATION "${CMAKE_INSTALL_DATADIR}/nemo-speech/config")
file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/share/nemo-speech")
configure_file(
models/index.json
"${CMAKE_BINARY_DIR}/share/nemo-speech/model-index.json"
COPYONLY)
install(FILES models/index.json
DESTINATION "${CMAKE_INSTALL_DATADIR}/nemo-speech"
RENAME model-index.json)

# Windows: stop <windows.h> - pulled in transitively by the CUDA headers when
# GGML_CUDA=ON - from defining the min()/max() macros, which otherwise clobber
Expand Down Expand Up @@ -93,6 +103,7 @@ option(NEMO_SPEECH_BUILD_DIAR "Build standalone and ASR-integrated diarizat
option(NEMO_SPEECH_BUILD_TTS "Build text-to-speech" ON)
option(NEMO_SPEECH_BUILD_NMT "Build text translation (links llama.cpp)" ${NEMO_SPEECH_WITH_NMT})
option(NEMO_SPEECH_BUILD_CLI "Build the unified nemo-speech CLI" ON)
option(NEMO_SPEECH_BUILD_MIC_CAPTURE "Build microphone capture in the CLI and examples" ON)
option(NEMO_SPEECH_BUILD_HTTP "Build the HTTP server and local playground" OFF)
option(NEMO_SPEECH_HTTP_TLS "Enable TLS support in the HTTP server (requires OpenSSL)" OFF)
option(NEMO_SPEECH_BUILD_GRPC "Build Riva-compatible gRPC adapters" ${NEMO_SPEECH_WITH_GRPC})
Expand Down Expand Up @@ -153,15 +164,13 @@ if(NEMO_SPEECH_BUILD_DIAR AND NOT NEMO_SPEECH_BUILD_ASR)
"without the transcribe CLI/API surface")
endif()

# Drop-in cuBLAS shim (native GEMM, no cuBLASLt). When ON, builds
# libcublas.so.13 from kernels/cublas_shim.cu. The shipping container image
# substitutes it for real cuBLAS to drop ~564 MB; put it on LD_LIBRARY_PATH
# ahead of the system cuBLAS to reproduce that GEMM path natively.
# Drop-in cuBLAS shim (native GEMM, no cuBLASLt). Release builds can substitute
# it for real cuBLAS to reduce their runtime closure.
# Disabled by default for source builds, which link the CUDA toolkit's cuBLAS.
# Container builds enable the shim explicitly to reduce the runtime image size.
# Portable builds enable the shim explicitly.
# It is only built when GGML_CUDA is also ON (see the target below), and is a
# no-op for Metal, Vulkan, and CPU builds.
option(NEMO_SPEECH_CUBLAS_SHIM "Build the in-tree drop-in cuBLAS shim (libcublas.so.13, native GEMM, no cuBLASLt)" OFF)
option(NEMO_SPEECH_CUBLAS_SHIM "Build the in-tree drop-in cuBLAS shim (native GEMM, no cuBLASLt)" OFF)

# Whether the linked ggml has the project ASR patches applied (ggml-patches/:
# the fused rel-pos attention op and the F16 depthwise-conv kernel). The ASR
Expand Down Expand Up @@ -279,18 +288,16 @@ if(GGML_METAL)
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
endif()

# In-tree cuBLAS shim: a drop-in libcublas.so.13 backed by native GEMM kernels
# (no cuBLASLt). ggml-cuda links real cuBLAS at build time, but the shim shares
# its SONAME, so binaries resolve it instead when it is first on LD_LIBRARY_PATH.
# The container images ship it in place of real cuBLAS (~564 MB saved); this
# target reproduces that for native builds.
# The cuBLAS shim is a Linux-only container size optimization. It relies on ELF
# SONAME versioning (SOVERSION 13 -> libcublas.so.13) plus a GNU-ld
# --version-script, neither of which exists with MSVC/link.exe. On Windows,
# ggml-cuda links the real cuBLAS DLL from the CUDA toolkit, so the shim is
# neither needed nor buildable - skip it.
if(GGML_CUDA AND NEMO_SPEECH_CUBLAS_SHIM AND NOT WIN32)
# In-tree cuBLAS shim backed by native GEMM kernels (no cuBLASLt). ggml-cuda
# links real cuBLAS at build time. At runtime the loader resolves its cuBLAS
# dependency to this target's matching major-version library name.
if(GGML_CUDA AND NEMO_SPEECH_CUBLAS_SHIM)
enable_language(CUDA)
if(CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 13.0)
set(NEMO_SPEECH_CUBLAS_SOVERSION 12)
else()
set(NEMO_SPEECH_CUBLAS_SOVERSION 13)
endif()
add_library(nemo_speech_cublas_shim SHARED kernels/cublas_shim.cu)
if(CMAKE_CUDA_ARCHITECTURES)
set(NEMO_SPEECH_CUBLAS_SHIM_ARCHITECTURES "${CMAKE_CUDA_ARCHITECTURES}")
Expand All @@ -300,16 +307,25 @@ if(GGML_CUDA AND NEMO_SPEECH_CUBLAS_SHIM AND NOT WIN32)
set(NEMO_SPEECH_CUBLAS_SHIM_ARCHITECTURES "80-virtual")
endif()
set_target_properties(nemo_speech_cublas_shim PROPERTIES
OUTPUT_NAME cublas
SOVERSION 13
CUDA_ARCHITECTURES "${NEMO_SPEECH_CUBLAS_SHIM_ARCHITECTURES}"
CUDA_RUNTIME_LIBRARY Static
CUDA_SEPARABLE_COMPILATION ON)
target_link_options(nemo_speech_cublas_shim PRIVATE
"LINKER:--version-script=${CMAKE_CURRENT_SOURCE_DIR}/kernels/ver_cublas.map")
elseif(GGML_CUDA AND NEMO_SPEECH_CUBLAS_SHIM AND WIN32)
message(STATUS
"NEMO_SPEECH_CUBLAS_SHIM: skipped on Windows; linking the CUDA "
"toolkit's real cuBLAS instead.")
if(WIN32)
# The toolkit import library records this exact DLL name. App-local
# deployment therefore substitutes the shim without changing ggml.
set_target_properties(nemo_speech_cublas_shim PROPERTIES
OUTPUT_NAME "cublas64_${NEMO_SPEECH_CUBLAS_SOVERSION}")
else()
set_target_properties(nemo_speech_cublas_shim PROPERTIES
OUTPUT_NAME cublas
SOVERSION "${NEMO_SPEECH_CUBLAS_SOVERSION}")
configure_file(
kernels/ver_cublas.map
"${CMAKE_CURRENT_BINARY_DIR}/ver_cublas.map"
@ONLY)
target_link_options(nemo_speech_cublas_shim PRIVATE
"LINKER:--version-script=${CMAKE_CURRENT_BINARY_DIR}/ver_cublas.map")
endif()
endif()

if(NEMO_SPEECH_WITH_FLASHLIGHT)
Expand Down Expand Up @@ -448,6 +464,10 @@ if(DEFINED VCPKG_INSTALLED_DIR AND DEFINED VCPKG_TARGET_TRIPLET)
endif()
install(FILES ggml/LICENSE
DESTINATION "${NEMO_SPEECH_THIRD_PARTY_LICENSE_DIR}/ggml")
if(NEMO_SPEECH_BUILD_ASR AND NEMO_SPEECH_BUILD_CLI AND NEMO_SPEECH_BUILD_MIC_CAPTURE)
install(FILES third_party/miniaudio/LICENSE
DESTINATION "${NEMO_SPEECH_THIRD_PARTY_LICENSE_DIR}/miniaudio")
endif()
if(TARGET nemo_speech_cublas_shim)
install(TARGETS nemo_speech_cublas_shim
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
Expand Down Expand Up @@ -500,7 +520,7 @@ configure_package_config_file(
write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/NeMoSpeechConfigVersion.cmake
VERSION ${PROJECT_VERSION}
COMPATIBILITY SameMajorVersion)
COMPATIBILITY SameMinorVersion)
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/NeMoSpeechConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/NeMoSpeechConfigVersion.cmake
Expand Down
20 changes: 12 additions & 8 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,49 +206,53 @@
{
"name": "cpu-server",
"inherits": "cpu-asr",
"displayName": "CPU ASR and TTS HTTP server and playground",
"displayName": "CPU speech CLI, HTTP server, and playground",
"cacheVariables": {
"NEMO_SPEECH_BUILD_TTS": "ON",
"NEMO_SPEECH_BUILD_NMT": "ON",
"NEMO_SPEECH_BUILD_HTTP": "ON",
"NEMO_SPEECH_BUILD_GRPC": "OFF",
"NEMO_SPEECH_WITH_GRPC": "OFF",
"NEMO_SPEECH_WITH_NMT": "OFF"
"NEMO_SPEECH_WITH_NMT": "ON"
}
},
{
"name": "cuda-server",
"inherits": "cuda-asr",
"displayName": "CUDA ASR and TTS HTTP server and playground",
"displayName": "CUDA speech CLI, HTTP server, and playground",
"cacheVariables": {
"NEMO_SPEECH_BUILD_TTS": "ON",
"NEMO_SPEECH_BUILD_NMT": "ON",
"NEMO_SPEECH_BUILD_HTTP": "ON",
"NEMO_SPEECH_BUILD_GRPC": "OFF",
"NEMO_SPEECH_WITH_GRPC": "OFF",
"NEMO_SPEECH_WITH_NMT": "OFF"
"NEMO_SPEECH_WITH_NMT": "ON"
}
},
{
"name": "metal-server",
"inherits": "metal-asr",
"displayName": "Metal ASR and TTS HTTP server and playground",
"displayName": "Metal speech CLI, HTTP server, and playground",
"cacheVariables": {
"NEMO_SPEECH_BUILD_TTS": "ON",
"NEMO_SPEECH_BUILD_NMT": "ON",
"NEMO_SPEECH_BUILD_HTTP": "ON",
"NEMO_SPEECH_BUILD_GRPC": "OFF",
"NEMO_SPEECH_WITH_GRPC": "OFF",
"NEMO_SPEECH_WITH_NMT": "OFF"
"NEMO_SPEECH_WITH_NMT": "ON"
}
},
{
"name": "vulkan-server",
"inherits": "vulkan-asr",
"displayName": "Vulkan ASR and TTS HTTP server and playground",
"displayName": "Vulkan speech CLI, HTTP server, and playground",
"cacheVariables": {
"NEMO_SPEECH_BUILD_TTS": "ON",
"NEMO_SPEECH_BUILD_NMT": "ON",
"NEMO_SPEECH_BUILD_HTTP": "ON",
"NEMO_SPEECH_BUILD_GRPC": "OFF",
"NEMO_SPEECH_WITH_GRPC": "OFF",
"NEMO_SPEECH_WITH_NMT": "OFF"
"NEMO_SPEECH_WITH_NMT": "ON"
}
},
{
Expand Down
23 changes: 23 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,29 @@

We welcome external contributions to NeMo-Speech.cpp.

## Development checks

Follow the [source-build guide](docs/build.md) for prerequisites and submodules.
For a model-independent CPU ASR test build:

```bash
git submodule update --init ggml llama.cpp
scripts/configure.sh cpu-asr -DNEMO_SPEECH_BUILD_TESTS=ON
cmake --build --preset cpu-asr
ctest --test-dir build/cpu-asr --output-on-failure
```

Install [pre-commit](https://pre-commit.com/) and run the same formatting,
license-header, and static file checks used by CI:

```bash
pre-commit run --all-files
```

Use the closest matching CUDA, Metal, Vulkan, server, or component preset when
the change affects code outside the CPU ASR path. Include the commands and
results relevant to the change in the pull request.

## Contribution license and provenance

Unless a file states otherwise, contributions are submitted under the
Expand Down
97 changes: 67 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,22 @@
# NeMo-Speech.cpp

A lightweight native C++ runtime for NVIDIA Nemotron Speech models built on ggml. Runs speech models in realtime and in batch mode across platforms/backends.
A lightweight native C++ runtime for running the NVIDIA Nemotron Speech model family locally, with broad hardware support. It supports multilingual speech recognition, speaker diarization, translation, and speech synthesis in real-time and batch modes.

NeMo-Speech.cpp is NVIDIA's official local speech inference solution, with day-0 support for our latest speech models. It builds on models from [NVIDIA NeMo Speech](https://github.com/NVIDIA-NeMo/Speech), with native inference powered by [ggml](https://github.com/ggml-org/ggml).

## Models and applications

| Application | Supported models |
|---|---|
| Speech recognition | [Nemotron 3.5 ASR Streaming 0.6B](https://huggingface.co/nvidia/nemotron-3.5-asr-streaming-0.6b), [Nemotron Speech Streaming 0.6B](https://huggingface.co/nvidia/nemotron-speech-streaming-en-0.6b), [Parakeet TDT 0.6B v3](https://huggingface.co/nvidia/parakeet-tdt-0.6b-v3), and [Parakeet CTC 1.1B](https://huggingface.co/nvidia/parakeet-ctc-1.1b) |
| Speaker diarization | [Streaming Sortformer 4-speaker v2](https://huggingface.co/nvidia/diar_streaming_sortformer_4spk-v2), standalone or combined with ASR |
| Text and speech translation | [Riva Translate 4B Instruct v2](https://huggingface.co/nvidia/Riva-Translate-4B-Instruct-v2), with composed ASR-to-NMT-to-TTS speech translation |
| Speech synthesis | [MagpieTTS Multilingual 357M](https://huggingface.co/nvidia/magpie_tts_multilingual_357m) with [NeMo NanoCodec](https://huggingface.co/nvidia/nemo-nano-codec-22khz-1.89kbps-21.5fps) |
| Speech processing | [Silero VAD](https://github.com/snakers4/silero-vad), punctuation and capitalization, endpointing, text normalization, and subtitles |

## Contents

- [Models and applications](#models-and-applications)
- [Installation](#installation)
- [Quick start](#quick-start)
- [Command line](#command-line)
Expand All @@ -16,38 +29,57 @@ A lightweight native C++ runtime for NVIDIA Nemotron Speech models built on ggml

## Installation

From a source checkout, install the CLI, HTTP API, and browser playground for
the detected platform and backend:
Install the `nemo-speech` CLI for the detected platform and backend:

On Linux or macOS, run:

```bash
scripts/install.sh --source
curl -fsSL https://github.com/NVIDIA/NeMo-Speech.cpp/raw/main/scripts/install.sh | sh
export PATH="$HOME/.local/bin:$PATH" # current shell; future shells are updated
```

The source build requires Git, CMake 3.26 or newer, Ninja, a C++17 compiler,
and the toolkit for the selected GPU backend. See
[Installation](docs/install.md) for platform-specific prerequisites, options,
and the native release-archive flow.
On Windows, run from PowerShell:

```powershell
irm https://github.com/NVIDIA/NeMo-Speech.cpp/raw/main/scripts/install.ps1 | iex
```

Open a new PowerShell window after installation so the updated user `PATH`
takes effect.

The installer prefers a verified native release and falls back to a source
build when an artifact is unavailable. A source build requires Git, CMake 3.26
or newer, Ninja, a C++17 compiler, SentencePiece development files, and the
toolchain required by the selected backend, if any. See
[Installation](docs/install.md) for platform-specific prerequisites and
options.

## Quick start

Download the ready-to-run Q8 GGUF from the model's Hugging Face repository,
then transcribe the bundled sample:
Transcribe a local WAV file. On first use, the CLI downloads the pinned default
Nemotron 3.5 GGUF from Hugging Face and verifies its size and SHA-256:

```bash
hf download nvidia/nemotron-speech-streaming-en-0.6b \
nemotron-speech-streaming-en-0.6b.q8_0.gguf \
--local-dir models
nemo-speech transcribe /path/to/audio.wav
```

nemo-speech transcribe test_files/asr/wav/test/jfk.wav \
--model models/nemotron-speech-streaming-en-0.6b.q8_0.gguf
Source checkouts can use `test_files/asr/wav/test/jfk.wav` as a smoke-test
input.

The same command can transcribe the default microphone on builds that include
live capture:

```bash
nemo-speech transcribe --live
```

Install the `hf` command with `pip install -U huggingface_hub` if needed. The
CLI selects an available backend and handles common mono or stereo PCM WAV
sample rates automatically. Substitute your own WAV file after verifying the
bundled sample. See [ASR models](docs/asr/models.md) for the other published
GGUFs and [model conversion](docs/model-conversion.md) for custom checkpoints.
Run `nemo-speech model list` to see defaults, short names, and which command
uses each model. For example, `nemo-speech pull nemotron-en` downloads the
English-only model ahead of time, and `--model nemotron-en` selects it. Local
GGUF paths continue to work without downloading anything. The CLI selects an
available backend and handles common mono or stereo PCM WAV sample rates
automatically. See the [CLI model guide](docs/cli.md#models-and-cache) and
[model conversion](docs/model-conversion.md) for custom checkpoints.

## Command line

Expand All @@ -62,13 +94,13 @@ Start the same runtime as a local HTTP service and open the playground:

```bash
nemo-speech serve \
--asr-model models/nemotron-speech-streaming-en-0.6b.q8_0.gguf \
--asr-model nemotron-3.5 \
--open
```

The server binds to <http://127.0.0.1:8080> by default and also provides a
documented OpenAI-compatible audio API subset and realtime WebSocket
transcription. A separately built `riva_server` binary provides the
The server binds to <http://127.0.0.1:8080> by default. Its transcription and
speech routes expose documented OpenAI-compatible subsets, alongside realtime
WebSocket transcription. A separately built `riva_server` binary provides the
Riva-compatible gRPC interface. See the [server guide](docs/server.md) when you
are ready to integrate either interface.

Expand All @@ -88,11 +120,12 @@ gRPC usage.

## Build from source

Requires CMake 3.26 or newer, Ninja, C and C++17 compilers, and a supported
CUDA toolkit. For a CUDA ASR and TTS server with the playground:
Requires CMake 3.26 or newer, Ninja, C and C++17 compilers, SentencePiece
development files, and the toolchain required by the selected backend, if any.
For a CUDA ASR and TTS server with the playground:

```bash
git submodule update --init ggml third_party/cpp-httplib
git submodule update --init ggml llama.cpp third_party/cpp-httplib
scripts/configure.sh cuda-server
cmake --build --preset cuda-server
```
Expand All @@ -119,9 +152,13 @@ Windows, and container instructions are in

## License

NVIDIA-authored code is released under the [Apache License 2.0](LICENSE), with
the project copyright notice in [NOTICE](NOTICE). Third-party components retain
their respective terms; see [Third-Party Notices](THIRD_PARTY_NOTICES.md).
NVIDIA-authored code is released under the
[Apache License 2.0](https://github.com/NVIDIA/NeMo-Speech.cpp/blob/main/LICENSE),
with the project copyright notice in
[NOTICE](https://github.com/NVIDIA/NeMo-Speech.cpp/blob/main/NOTICE). Third-party
components retain their respective terms; see
[Third-Party Notices](https://github.com/NVIDIA/NeMo-Speech.cpp/blob/main/THIRD_PARTY_NOTICES.md).
Release archives also include these files under `share/licenses/nemo-speech/`.

## Contributing

Expand Down
Loading