DEPRECATED: Use mizchi/whisper instead. MoonBit native bindings for whisper.cpp.
Dependencies
git clone --recursive https://github.com/mizchi/whisper-mbt.git
cd whisper-mbt
# Build whisper.cpp and download model
just setup
# Run
WHISPER_MODEL=models/ggml-base.bin \
WHISPER_WAV=vendor/whisper.cpp/samples/jfk.wav \
moon run src/main --target nativemoon add mizchi/whisper-mbt{
"name": "your/project",
"deps": {
"mizchi/whisper-mbt": {
"path": "/path/to/whisper-mbt"
}
},
"preferred-target": "native"
}git clone https://github.com/ggml-org/whisper.cpp.git
cd whisper.cpp
# macOS (Metal)
cmake -B build -DCMAKE_BUILD_TYPE=Release \
-DGGML_METAL=ON -DGGML_METAL_EMBED_LIBRARY=ON \
-DBUILD_SHARED_LIBS=OFF \
-DWHISPER_BUILD_EXAMPLES=OFF -DWHISPER_BUILD_TESTS=OFF -DWHISPER_BUILD_SERVER=OFF
cmake --build build --config Release -j$(sysctl -n hw.logicalcpu)
# Linux (CPU only)
cmake -B build -DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=OFF \
-DWHISPER_BUILD_EXAMPLES=OFF -DWHISPER_BUILD_TESTS=OFF -DWHISPER_BUILD_SERVER=OFF
cmake --build build --config Release -j$(nproc)// cmd/main/moon.pkg
import {
"mizchi/whisper-mbt" @whisper,
}
options(
"is-main": true,
link: {
"native": {
// macOS (Metal + Accelerate)
"cc-link-flags": "/path/to/whisper.cpp/build/src/libwhisper.a /path/to/whisper.cpp/build/ggml/src/libggml.a /path/to/whisper.cpp/build/ggml/src/libggml-base.a /path/to/whisper.cpp/build/ggml/src/libggml-cpu.a /path/to/whisper.cpp/build/ggml/src/ggml-metal/libggml-metal.a /path/to/whisper.cpp/build/ggml/src/ggml-blas/libggml-blas.a -lstdc++ -framework Accelerate -framework Metal -framework Foundation -framework MetalKit",
},
},
"supported-targets": [ "native" ],
)"cc-link-flags": "/path/to/whisper.cpp/build/src/libwhisper.a /path/to/whisper.cpp/build/ggml/src/libggml.a /path/to/whisper.cpp/build/ggml/src/libggml-base.a /path/to/whisper.cpp/build/ggml/src/libggml-cpu.a -lstdc++ -lm -lpthread"# ggml-base (147 MB)
curl -L -o models/ggml-base.bin \
https://huggingface.co/ggerganov/whisper.cpp/resolve/main/ggml-base.binfn main {
let ctx = @whisper.WhisperContext::init("models/ggml-base.bin")
match ctx {
None => println("Failed to load model")
Some(ctx) => {
let segments = ctx.transcribe("audio.wav", language="auto")
for i = 0; i < segments.length(); i = i + 1 {
println(segments[i].text)
}
ctx.free()
}
}
}WhisperContext::init(model_path : String) -> WhisperContext?
WhisperContext::transcribe(self, wav_path, language?="en", translate?=false, n_threads?=4, ...) -> Array[Segment]
WhisperContext::transcribe_parallel(self, wav_path, n_processors?=4, ...) -> Array[Segment]
WhisperContext::get_tokens(self, segment_index) -> Array[TokenData]
WhisperContext::model_info(self) -> ModelInfo
WhisperContext::detected_language(self) -> String
WhisperContext::get_timings(self) -> Timings
WhisperContext::print_timings(self) -> Unit
WhisperContext::free(self) -> Unit| Parameter | Type | Default | Description |
|---|---|---|---|
| language | String | "en" | Language code or "auto" |
| translate | Bool | false | Translate to English |
| n_threads | Int | 4 | Number of threads |
| offset_ms | Int | 0 | Start offset in ms |
| duration_ms | Int | 0 | Duration to process (0 = all) |
| no_timestamps | Bool | false | Disable timestamps |
| single_segment | Bool | false | Force single segment |
| token_timestamps | Bool | false | Token-level timestamps |
| max_len | Int | 0 | Max segment length (chars) |
| max_tokens | Int | 0 | Max tokens per segment |
| initial_prompt | String | "" | Initial prompt |
| temperature | Double | 0.0 | Decoding temperature |
| strategy | Strategy | Greedy | Greedy or BeamSearch |
| beam_size | Int | 5 | Beam size (when BeamSearch) |
| no_context | Bool | false | Disable past context |
| vad_model_path | String | "" | Path to Silero VAD model (enables VAD) |
| vad_params | VadParams? | None | VAD tuning parameters |
curl -L -o models/ggml-silero-v5.1.2.bin \
https://huggingface.co/ggml-org/whisper-vad/resolve/main/ggml-silero-v5.1.2.binlet segments = ctx.transcribe(
"audio.wav",
language="auto",
vad_model_path="models/ggml-silero-v5.1.2.bin",
)let segments = ctx.transcribe_parallel(
"long_audio.wav",
n_processors=4,
language="auto",
)just build-whisper
just update-headerspub struct ModelInfo {
model_type : String
is_multilingual : Bool
n_vocab : Int
n_text_ctx : Int
n_audio_ctx : Int
}pub struct Segment {
text : String
t0 : Int64
t1 : Int64
no_speech_prob : Double
speaker_turn_next : Bool
}pub(all) enum Strategy {
Greedy
BeamSearch
}pub struct Timings {
sample_ms : Double
encode_ms : Double
decode_ms : Double
batchd_ms : Double
prompt_ms : Double
}pub struct TokenData {
text : String
id : Int
prob : Double
t0 : Int64
t1 : Int64
}pub struct VadParams {
threshold : Double
min_speech_duration_ms : Int
min_silence_duration_ms : Int
max_speech_duration_s : Double
speech_pad_ms : Int
}pub struct WhisperContext {
// private fields
}fn WhisperContext::transcribe(self : WhisperContext, wav_path : String, language? : String, translate? : Bool, n_threads? : Int, offset_ms? : Int, duration_ms? : Int, no_timestamps? : Bool, single_segment? : Bool, token_timestamps? : Bool, max_len? : Int, max_tokens? : Int, audio_ctx? : Int, initial_prompt? : String, temperature? : Double, print_progress? : Bool, strategy? : Strategy, beam_size? : Int, no_context? : Bool, vad_model_path? : String, vad_params? : VadParams?) -> Array[Segment]fn WhisperContext::transcribe_parallel(self : WhisperContext, wav_path : String, n_processors? : Int, language? : String, translate? : Bool, n_threads? : Int, offset_ms? : Int, duration_ms? : Int, no_timestamps? : Bool, single_segment? : Bool, token_timestamps? : Bool, max_len? : Int, max_tokens? : Int, audio_ctx? : Int, initial_prompt? : String, temperature? : Double, print_progress? : Bool, strategy? : Strategy, beam_size? : Int, no_context? : Bool, vad_model_path? : String, vad_params? : VadParams?) -> Array[Segment]DEPRECATED: Use mizchi/whisper instead. MoonBit native bindings for whisper.cpp.
Dependencies