Skip to main content

transcribe_cpp/
lib.rs

1//! Safe, idiomatic Rust bindings for
2//! [transcribe.cpp](https://github.com/handy-computer/transcribe.cpp), a C/C++
3//! speech-to-text library built on ggml.
4//!
5//! The raw FFI lives in the [`transcribe-cpp-sys`](transcribe_cpp_sys) crate
6//! (re-exported as [`sys`]); this crate wraps it with owned result types, an
7//! error enum, RAII handles, and a thread-safety model that matches the C
8//! contract.
9//!
10//! # Quickstart
11//!
12//! ```no_run
13//! use transcribe_cpp::{Model, RunOptions};
14//!
15//! let mut session = Model::load("model.gguf")?.session()?;
16//! let pcm: Vec<f32> = vec![/* 16 kHz mono samples in [-1, 1] */];
17//! let result = session.run(&pcm, &RunOptions::default())?;
18//! println!("{}", result.text);
19//! # Ok::<(), transcribe_cpp::Error>(())
20//! ```
21//!
22//! # Threading
23//!
24//! - [`Model`] is `Send + Sync` and cheap to clone (`Arc`-backed). The native
25//!   model is freed only after the last [`Model`] handle and every [`Session`]
26//!   derived from it are dropped — in any order.
27//! - [`Session`] is `Send` but not `Sync`; its mutating calls take `&mut self`,
28//!   so the type system enforces one-call-at-a-time.
29//! - **0.x concurrency:** the C library permits at most one in-flight
30//!   `run`/stream across all sessions of a model. This crate enforces that with
31//!   a per-model mutex (held only for the native compute call), so concurrent
32//!   calls from many sessions queue rather than race. For real parallelism, use
33//!   one [`Model`] per worker today.
34//!
35//! # ABI verification
36//!
37//! The per-field struct-layout check that the ctypes binding performs is
38//! **waived** here: bindgen takes every struct's layout from a real compiler at
39//! generation time, so the generated FFI cannot disagree with the headers it
40//! was built against. The load-time base-version lock (see [`Model::load`]) is
41//! retained.
42
43#![doc(html_root_url = "https://docs.rs/transcribe-cpp")]
44#![warn(missing_debug_implementations)]
45
46pub use transcribe_cpp_sys as sys;
47
48mod backend;
49mod cancel;
50mod error;
51mod family;
52mod logging;
53mod model;
54mod result;
55mod session;
56mod streaming;
57mod types;
58mod version;
59
60pub use backend::{
61    allowed_backends, backend_available, device_count, devices, init_backends,
62    init_backends_default, init_backends_with, BackendMask, Device, DeviceType,
63};
64pub use cancel::CancelToken;
65pub use error::{Error, Result};
66pub use family::{
67    MoonshineStreamingOptions, ParakeetBufferedStreamOptions, ParakeetStreamOptions, RunExtension,
68    SortformerPreset, SortformerStreamOptions, StreamExtension, VoxtralRealtimeStreamOptions,
69    WhisperRunOptions,
70};
71pub use logging::{disable_logging, init_logging};
72pub use model::{Capabilities, Model, ModelOptions, SessionLimits, SessionOptions};
73pub use result::{Segment, SpeakerSegment, Timings, Token, Transcript, Word};
74pub use session::{RunOptions, Session, Stream};
75pub use streaming::{StreamOptions, StreamText, StreamUpdate};
76pub use types::{
77    AbiStruct, Backend, CommitPolicy, Diarize, ExtSlot, Feature, Itn, KvType, Pnc, StreamState,
78    Task, TimestampKind,
79};
80pub use version::{
81    abi_struct_align, abi_struct_size, compiled_version, header_hash, version, version_commit,
82};
83
84/// Convenience: load a model, transcribe one PCM buffer, and return the result.
85///
86/// For repeated transcription, hold a [`Session`] instead of paying model load
87/// on every call.
88pub fn transcribe(
89    model_path: impl AsRef<std::path::Path>,
90    pcm: &[f32],
91    options: &RunOptions,
92) -> Result<Transcript> {
93    let mut session = Model::load(model_path)?.session()?;
94    session.run(pcm, options)
95}