1use std::ffi::{c_char, c_float, c_int, c_void};
5
6#[repr(C)]
8pub struct WhisperContext(c_void);
9
10#[repr(C)]
12pub struct WhisperState(c_void);
13
14#[repr(C)]
16pub struct WhisperFullParams(c_void);
17
18#[repr(C)]
20pub struct WhisperContextParams(c_void);
21
22pub const CRISPASR_SAMPLING_GREEDY: c_int = 0;
24pub const CRISPASR_SAMPLING_BEAM_SEARCH: c_int = 1;
25
26pub type CrispasrProgressCallback =
29 Option<unsafe extern "C" fn(processed: c_int, total: c_int, user_data: *mut c_void)>;
30
31extern "C" {
32 pub fn whisper_init_from_file_with_params(
34 path: *const c_char,
35 params: *const WhisperContextParams,
36 ) -> *mut WhisperContext;
37
38 pub fn whisper_context_default_params_by_ref() -> *mut WhisperContextParams;
39 pub fn whisper_free(ctx: *mut WhisperContext);
40 pub fn whisper_free_params(params: *mut WhisperFullParams);
41 pub fn whisper_free_context_params(params: *mut WhisperContextParams);
42
43 pub fn whisper_full(
45 ctx: *mut WhisperContext,
46 params: *const WhisperFullParams,
47 samples: *const c_float,
48 n_samples: c_int,
49 ) -> c_int;
50
51 pub fn whisper_full_default_params_by_ref(strategy: c_int) -> *mut WhisperFullParams;
52
53 pub fn whisper_full_n_segments(ctx: *mut WhisperContext) -> c_int;
55
56 pub fn whisper_full_get_segment_text(
57 ctx: *mut WhisperContext,
58 i_segment: c_int,
59 ) -> *const c_char;
60
61 pub fn whisper_full_get_segment_t0(ctx: *mut WhisperContext, i_segment: c_int) -> i64;
62
63 pub fn whisper_full_get_segment_t1(ctx: *mut WhisperContext, i_segment: c_int) -> i64;
64
65 pub fn whisper_full_get_segment_no_speech_prob(
66 ctx: *mut WhisperContext,
67 i_segment: c_int,
68 ) -> c_float;
69
70 pub fn whisper_full_lang_id(ctx: *mut WhisperContext) -> c_int;
72 pub fn whisper_lang_str(id: c_int) -> *const c_char;
73 pub fn whisper_lang_id(lang: *const c_char) -> c_int;
74
75 pub fn crispasr_params_set_vad(p: *mut WhisperFullParams, v: c_int);
77 pub fn crispasr_params_set_vad_model_path(p: *mut WhisperFullParams, path: *const c_char);
78 pub fn crispasr_params_set_vad_threshold(p: *mut WhisperFullParams, threshold: c_float);
79 pub fn crispasr_params_set_vad_min_speech_ms(p: *mut WhisperFullParams, ms: c_int);
80 pub fn crispasr_params_set_vad_min_silence_ms(p: *mut WhisperFullParams, ms: c_int);
81 pub fn crispasr_params_set_tdrz(p: *mut WhisperFullParams, v: c_int);
82}
83
84#[repr(C)]
95pub struct CrispasrSession(c_void);
96
97#[repr(C)]
100pub struct CrispasrSessionResult(c_void);
101
102#[repr(C)]
106pub struct CrispasrStream(c_void);
107
108#[repr(C)]
111pub struct CrispasrMic(c_void);
112
113#[repr(C)]
116pub struct CrispasrAlignResult(c_void);
117
118#[repr(C)]
122#[derive(Clone, Copy, Debug)]
123pub struct CrispasrVadAbiOpts {
124 pub threshold: c_float,
125 pub min_speech_duration_ms: c_int,
126 pub min_silence_duration_ms: c_int,
127 pub speech_pad_ms: c_int,
128 pub chunk_seconds: c_int,
129 pub n_threads: c_int,
130}
131
132impl Default for CrispasrVadAbiOpts {
133 fn default() -> Self {
134 Self {
135 threshold: 0.5,
136 min_speech_duration_ms: 250,
137 min_silence_duration_ms: 100,
138 speech_pad_ms: 30,
139 chunk_seconds: 30,
140 n_threads: 4,
141 }
142 }
143}
144
145#[repr(C)]
148#[derive(Clone, Copy, Debug)]
149pub struct CrispasrDiarizeSegAbi {
150 pub t0_cs: i64,
151 pub t1_cs: i64,
152 pub speaker: c_int,
153 pub _pad: c_int,
154}
155
156#[repr(C)]
166#[derive(Clone, Copy, Debug)]
167pub struct CrispasrDiarizeOptsAbi {
168 pub method: c_int,
169 pub n_threads: c_int,
170 pub slice_t0_cs: i64,
171 pub pyannote_model_path: *const c_char,
172 pub foxnose_embedder_path: *const c_char,
174 pub min_speakers: c_int,
176 pub max_speakers: c_int,
178 pub num_speakers: c_int,
180 pub _pad2: c_int,
181}
182
183extern "C" {
184 pub fn crispasr_session_open(
185 model_path: *const c_char,
186 n_threads: c_int,
187 ) -> *mut CrispasrSession;
188
189 pub fn crispasr_session_open_explicit(
190 model_path: *const c_char,
191 backend_name: *const c_char,
192 n_threads: c_int,
193 ) -> *mut CrispasrSession;
194
195 pub fn crispasr_session_backend(s: *mut CrispasrSession) -> *const c_char;
196
197 pub fn crispasr_session_n_vocab(s: *mut CrispasrSession) -> c_int;
203 pub fn crispasr_session_token_text(s: *mut CrispasrSession, id: c_int) -> *const c_char;
204
205 pub fn crispasr_session_detected_language(
210 s: *mut CrispasrSession,
211 out_buf: *mut c_char,
212 out_cap: c_int,
213 ) -> c_int;
214
215 pub fn crispasr_session_available_backends(out_csv: *mut c_char, out_cap: c_int) -> c_int;
219
220 pub fn crispasr_session_transcribe(
221 s: *mut CrispasrSession,
222 pcm: *const c_float,
223 n_samples: c_int,
224 ) -> *mut CrispasrSessionResult;
225
226 pub fn crispasr_session_transcribe_lang(
232 s: *mut CrispasrSession,
233 pcm: *const c_float,
234 n_samples: c_int,
235 language: *const c_char,
236 ) -> *mut CrispasrSessionResult;
237
238 pub fn crispasr_session_transcribe_chunked_lang(
249 s: *mut CrispasrSession,
250 pcm: *const c_float,
251 n_samples: c_int,
252 chunk_seconds: c_int,
253 overlap_seconds: c_int,
254 language: *const c_char,
255 ) -> *mut CrispasrSessionResult;
256
257 pub fn crispasr_session_transcribe_chunked(
258 s: *mut CrispasrSession,
259 pcm: *const c_float,
260 n_samples: c_int,
261 chunk_seconds: c_int,
262 overlap_seconds: c_int,
263 ) -> *mut CrispasrSessionResult;
264
265 pub fn crispasr_session_set_progress_callback(
271 s: *mut CrispasrSession,
272 cb: CrispasrProgressCallback,
273 user_data: *mut c_void,
274 );
275
276 pub fn crispasr_session_transcribe_vad(
286 s: *mut CrispasrSession,
287 pcm: *const c_float,
288 n_samples: c_int,
289 sample_rate: c_int,
290 vad_model_path: *const c_char,
291 opts: *const CrispasrVadAbiOpts,
292 ) -> *mut CrispasrSessionResult;
293
294 pub fn crispasr_session_transcribe_vad_lang(
297 s: *mut CrispasrSession,
298 pcm: *const c_float,
299 n_samples: c_int,
300 sample_rate: c_int,
301 vad_model_path: *const c_char,
302 opts: *const CrispasrVadAbiOpts,
303 language: *const c_char,
304 ) -> *mut CrispasrSessionResult;
305
306 pub fn crispasr_diarize_segments_abi(
310 left_pcm: *const c_float,
311 right_pcm: *const c_float,
312 n_samples: c_int,
313 is_stereo: c_int,
314 segs: *mut CrispasrDiarizeSegAbi,
315 n_segs: c_int,
316 opts: *const CrispasrDiarizeOptsAbi,
317 ) -> c_int;
318
319 pub fn crispasr_detect_language_pcm(
325 samples: *const c_float,
326 n_samples: c_int,
327 method: c_int,
328 model_path: *const c_char,
329 n_threads: c_int,
330 use_gpu: c_int,
331 gpu_device: c_int,
332 flash_attn: c_int,
333 out_lang_buf: *mut c_char,
334 out_lang_cap: c_int,
335 out_confidence: *mut c_float,
336 ) -> c_int;
337
338 pub fn crispasr_align_words_abi(
345 aligner_model: *const c_char,
346 transcript: *const c_char,
347 samples: *const c_float,
348 n_samples: c_int,
349 t_offset_cs: i64,
350 n_threads: c_int,
351 ) -> *mut CrispasrAlignResult;
352
353 pub fn crispasr_align_result_n_words(r: *mut CrispasrAlignResult) -> c_int;
354 pub fn crispasr_align_result_word_text(r: *mut CrispasrAlignResult, i: c_int) -> *const c_char;
355 pub fn crispasr_align_result_word_t0(r: *mut CrispasrAlignResult, i: c_int) -> i64;
356 pub fn crispasr_align_result_word_t1(r: *mut CrispasrAlignResult, i: c_int) -> i64;
357 pub fn crispasr_align_result_free(r: *mut CrispasrAlignResult);
358
359 pub fn crispasr_cache_ensure_file_abi(
363 filename: *const c_char,
364 url: *const c_char,
365 quiet: c_int,
366 cache_dir_override: *const c_char,
367 out_buf: *mut c_char,
368 out_cap: c_int,
369 ) -> c_int;
370
371 pub fn crispasr_cache_dir_abi(
373 cache_dir_override: *const c_char,
374 out_buf: *mut c_char,
375 out_cap: c_int,
376 ) -> c_int;
377
378 pub fn crispasr_registry_lookup_abi(
380 backend: *const c_char,
381 out_filename: *mut c_char,
382 filename_cap: c_int,
383 out_url: *mut c_char,
384 url_cap: c_int,
385 out_size: *mut c_char,
386 size_cap: c_int,
387 ) -> c_int;
388
389 pub fn crispasr_registry_list_backends_abi(out_csv: *mut c_char, out_cap: c_int) -> c_int;
391
392 pub fn crispasr_registry_default_bundle_info_abi(
395 backend: *const c_char,
396 out_backend: *mut c_char,
397 backend_cap: c_int,
398 out_license: *mut c_char,
399 license_cap: c_int,
400 out_requires_acceptance: *mut c_int,
401 ) -> c_int;
402
403 pub fn crispasr_registry_default_bundle_artifact_abi(
405 backend: *const c_char,
406 index: c_int,
407 out_kind: *mut c_int,
408 out_filename: *mut c_char,
409 filename_cap: c_int,
410 out_url: *mut c_char,
411 url_cap: c_int,
412 out_size: *mut c_char,
413 size_cap: c_int,
414 ) -> c_int;
415
416 pub fn crispasr_session_stream_open(
418 s: *mut CrispasrSession,
419 n_threads: c_int,
420 step_ms: c_int,
421 length_ms: c_int,
422 keep_ms: c_int,
423 language: *const c_char,
424 translate: c_int,
425 ) -> *mut CrispasrStream;
426 pub fn crispasr_stream_feed(
427 s: *mut CrispasrStream,
428 pcm: *const c_float,
429 n_samples: c_int,
430 ) -> c_int;
431 pub fn crispasr_stream_get_text(
432 s: *mut CrispasrStream,
433 out_text: *mut c_char,
434 out_cap: c_int,
435 out_t0_s: *mut f64,
436 out_t1_s: *mut f64,
437 out_counter: *mut i64,
438 ) -> c_int;
439 pub fn crispasr_stream_flush(s: *mut CrispasrStream) -> c_int;
440 pub fn crispasr_stream_close(s: *mut CrispasrStream);
441
442 pub fn crispasr_stream_set_live_decode(s: *mut CrispasrStream, enabled: c_int);
446
447 pub fn crispasr_mic_open(
449 sample_rate: c_int,
450 channels: c_int,
451 cb: extern "C" fn(pcm: *const c_float, n_samples: c_int, userdata: *mut c_void),
452 userdata: *mut c_void,
453 ) -> *mut CrispasrMic;
454 pub fn crispasr_mic_start(m: *mut CrispasrMic) -> c_int;
455 pub fn crispasr_mic_stop(m: *mut CrispasrMic) -> c_int;
456 pub fn crispasr_mic_close(m: *mut CrispasrMic);
457 pub fn crispasr_mic_default_device_name() -> *const c_char;
458 pub fn crispasr_registry_lookup_by_filename_abi(
459 filename: *const c_char,
460 out_filename: *mut c_char,
461 filename_cap: c_int,
462 out_url: *mut c_char,
463 url_cap: c_int,
464 out_size: *mut c_char,
465 size_cap: c_int,
466 ) -> c_int;
467
468 pub fn crispasr_session_result_n_segments(r: *mut CrispasrSessionResult) -> c_int;
469 pub fn crispasr_session_result_segment_text(
470 r: *mut CrispasrSessionResult,
471 i: c_int,
472 ) -> *const c_char;
473 pub fn crispasr_session_result_segment_t0(r: *mut CrispasrSessionResult, i: c_int) -> i64;
474 pub fn crispasr_session_result_segment_t1(r: *mut CrispasrSessionResult, i: c_int) -> i64;
475
476 pub fn crispasr_session_result_n_words(r: *mut CrispasrSessionResult, i_seg: c_int) -> c_int;
477 pub fn crispasr_session_result_word_text(
478 r: *mut CrispasrSessionResult,
479 i_seg: c_int,
480 i_word: c_int,
481 ) -> *const c_char;
482 pub fn crispasr_session_result_word_t0(
483 r: *mut CrispasrSessionResult,
484 i_seg: c_int,
485 i_word: c_int,
486 ) -> i64;
487 pub fn crispasr_session_result_word_t1(
488 r: *mut CrispasrSessionResult,
489 i_seg: c_int,
490 i_word: c_int,
491 ) -> i64;
492 pub fn crispasr_session_result_word_p(
493 r: *mut CrispasrSessionResult,
494 i_seg: c_int,
495 i_word: c_int,
496 ) -> f32;
497 pub fn crispasr_session_result_segment_no_speech_prob(
501 r: *mut CrispasrSessionResult,
502 i_seg: c_int,
503 ) -> f32;
504
505 pub fn crispasr_session_result_n_logit_frames(r: *mut CrispasrSessionResult) -> c_int;
509 pub fn crispasr_session_result_n_logit_vocab(r: *mut CrispasrSessionResult) -> c_int;
510 pub fn crispasr_session_result_logits(r: *mut CrispasrSessionResult) -> *const c_float;
511
512 pub fn crispasr_session_result_free(r: *mut CrispasrSessionResult);
513 pub fn crispasr_session_close(s: *mut CrispasrSession);
514
515 pub fn crispasr_session_set_codec_path(s: *mut CrispasrSession, path: *const c_char) -> c_int;
517 pub fn crispasr_session_set_voice(
518 s: *mut CrispasrSession,
519 path: *const c_char,
520 ref_text_or_null: *const c_char,
521 ) -> c_int;
522 pub fn crispasr_session_set_speaker_name(s: *mut CrispasrSession, name: *const c_char)
523 -> c_int;
524 pub fn crispasr_session_n_speakers(s: *mut CrispasrSession) -> c_int;
525 pub fn crispasr_session_get_speaker_name(s: *mut CrispasrSession, i: c_int) -> *const c_char;
526 pub fn crispasr_session_set_instruct(s: *mut CrispasrSession, instruct: *const c_char)
528 -> c_int;
529 pub fn crispasr_session_set_tts_phonemes(
532 s: *mut CrispasrSession,
533 phonemes: *const c_char,
534 ) -> c_int;
535 pub fn crispasr_session_is_custom_voice(s: *mut CrispasrSession) -> c_int;
537 pub fn crispasr_session_is_voice_design(s: *mut CrispasrSession) -> c_int;
538 pub fn crispasr_session_synthesize(
539 s: *mut CrispasrSession,
540 text: *const c_char,
541 out_n_samples: *mut c_int,
542 ) -> *mut f32;
543 pub fn crispasr_session_speech_to_speech(
549 s: *mut CrispasrSession,
550 in_samples: *const f32,
551 n_in_samples: c_int,
552 out_text: *mut *mut c_char,
553 out_n_samples: *mut c_int,
554 ) -> *mut f32;
555 pub fn crispasr_session_separate(
560 s: *mut CrispasrSession,
561 pcm_stereo: *const f32,
562 n_samples: c_int,
563 ) -> c_int;
564 pub fn crispasr_session_separate_n_stems(s: *mut CrispasrSession) -> c_int;
565 pub fn crispasr_session_separate_stem_name(
566 s: *mut CrispasrSession,
567 stem_idx: c_int,
568 ) -> *const c_char;
569 pub fn crispasr_session_separate_stem(
570 s: *mut CrispasrSession,
571 stem_idx: c_int,
572 out_n_samples: *mut c_int,
573 ) -> *const f32;
574 pub fn crispasr_session_separate_sample_rate(s: *mut CrispasrSession) -> c_int;
575 pub fn crispasr_session_synthesize_raw(
579 s: *mut CrispasrSession,
580 text: *const c_char,
581 out_n_samples: *mut c_int,
582 ) -> *mut f32;
583 pub fn crispasr_session_accept_marking_responsibility(
586 s: *mut CrispasrSession,
587 attestation: *const c_char,
588 ) -> c_int;
589 pub fn crispasr_session_set_speaker_identity(
594 s: *mut CrispasrSession,
595 identity: *const c_char,
596 ) -> c_int;
597 pub fn crispasr_session_input_sample_rate(s: *mut CrispasrSession) -> c_int;
601 pub fn crispasr_session_output_sample_rate(s: *mut CrispasrSession) -> c_int;
605 pub fn crispasr_session_input_channels(s: *mut CrispasrSession) -> c_int;
606 pub fn crispasr_session_output_channels(s: *mut CrispasrSession) -> c_int;
607 pub fn crispasr_pcm_free(pcm: *mut f32);
608 pub fn crispasr_watermark_embed(pcm: *mut f32, n_samples: c_int, alpha: c_float);
613 pub fn crispasr_watermark_detect(pcm: *const c_float, n_samples: c_int) -> c_float;
616 pub fn crispasr_session_kokoro_clear_phoneme_cache(s: *mut CrispasrSession) -> c_int;
619
620 pub fn crispasr_session_set_source_language(
622 s: *mut CrispasrSession,
623 lang: *const c_char,
624 ) -> c_int;
625 pub fn crispasr_session_set_target_language(
626 s: *mut CrispasrSession,
627 lang: *const c_char,
628 ) -> c_int;
629 pub fn crispasr_session_set_tts_reference_language(
630 s: *mut CrispasrSession,
631 lang: *const c_char,
632 ) -> c_int;
633 pub fn crispasr_session_set_punctuation(s: *mut CrispasrSession, enable: c_int) -> c_int;
634 pub fn crispasr_session_set_punc_model(
635 s: *mut CrispasrSession,
636 punc_model: *const c_char,
637 ) -> c_int;
638 pub fn crispasr_session_set_hotwords(
639 s: *mut CrispasrSession,
640 hotwords: *const c_char,
641 boost: c_float,
642 ) -> c_int;
643 pub fn crispasr_session_set_sensitivity(
644 s: *mut CrispasrSession,
645 preset: *const c_char,
646 ) -> c_int;
647 pub fn crispasr_session_set_g2p_dict(s: *mut CrispasrSession, source: *const c_char) -> c_int;
648 pub fn crispasr_session_set_speaker_id(s: *mut CrispasrSession, id: c_int) -> c_int;
649 pub fn crispasr_session_set_translate(s: *mut CrispasrSession, enable: c_int) -> c_int;
650 pub fn crispasr_session_translate_text(
666 s: *mut CrispasrSession,
667 text: *const c_char,
668 src_lang: *const c_char,
669 tgt_lang: *const c_char,
670 max_tokens: c_int,
671 ) -> *mut c_char;
672 pub fn crispasr_session_translate_text_free(text: *mut c_char);
678 pub fn crispasr_session_set_temperature(
679 s: *mut CrispasrSession,
680 temperature: c_float,
681 seed: u64,
682 ) -> c_int;
683 pub fn crispasr_session_set_tts_seed(s: *mut CrispasrSession, seed: u64) -> c_int;
684 pub fn crispasr_session_set_max_new_tokens(
685 s: *mut CrispasrSession,
686 max_new_tokens: c_int,
687 ) -> c_int;
688 pub fn crispasr_session_set_frequency_penalty(
689 s: *mut CrispasrSession,
690 penalty: c_float,
691 ) -> c_int;
692 pub fn crispasr_session_set_tts_steps(s: *mut CrispasrSession, steps: c_int) -> c_int;
693 pub fn crispasr_session_set_tts_num_candidates(s: *mut CrispasrSession, n: c_int) -> c_int;
694 pub fn crispasr_session_set_top_p(s: *mut CrispasrSession, top_p: c_float) -> c_int;
695 pub fn crispasr_session_set_top_k(s: *mut CrispasrSession, top_k: c_int) -> c_int;
696 pub fn crispasr_session_set_do_sample(s: *mut CrispasrSession, enable: c_int) -> c_int;
697 pub fn crispasr_session_set_min_p(s: *mut CrispasrSession, min_p: c_float) -> c_int;
698 pub fn crispasr_session_set_repetition_penalty(s: *mut CrispasrSession, r: c_float) -> c_int;
699 pub fn crispasr_session_set_cfg_weight(s: *mut CrispasrSession, cfg_weight: c_float) -> c_int;
700 pub fn crispasr_session_set_tts_noise_temp(
701 s: *mut CrispasrSession,
702 noise_temp: c_float,
703 ) -> c_int;
704 pub fn crispasr_session_set_exaggeration(
705 s: *mut CrispasrSession,
706 exaggeration: c_float,
707 ) -> c_int;
708 pub fn crispasr_session_set_max_speech_tokens(s: *mut CrispasrSession, n: c_int) -> c_int;
709 pub fn crispasr_session_set_min_speech_tokens(s: *mut CrispasrSession, n: c_int) -> c_int;
710 pub fn crispasr_session_set_length_scale(s: *mut CrispasrSession, scale: c_float) -> c_int;
711 pub fn crispasr_session_set_best_of(s: *mut CrispasrSession, n: c_int) -> c_int;
712 pub fn crispasr_session_set_beam_size(s: *mut CrispasrSession, n: c_int) -> c_int;
713 pub fn crispasr_session_set_return_logits(s: *mut CrispasrSession, enable: c_int) -> c_int;
714 pub fn crispasr_session_set_grammar_text(
715 s: *mut CrispasrSession,
716 gbnf_text: *const c_char,
717 root_rule: *const c_char,
718 penalty: c_float,
719 ) -> c_int;
720 pub fn crispasr_session_set_fallback_thresholds(
721 s: *mut CrispasrSession,
722 entropy_thold: c_float,
723 logprob_thold: c_float,
724 no_speech_thold: c_float,
725 temperature_inc: c_float,
726 ) -> c_int;
727 pub fn crispasr_session_set_alt_n(s: *mut CrispasrSession, n: c_int) -> c_int;
728 pub fn crispasr_session_set_whisper_decode_extras(
729 s: *mut CrispasrSession,
730 suppress_nst: c_int,
731 suppress_regex: *const c_char,
732 carry_initial_prompt: c_int,
733 ) -> c_int;
734 pub fn crispasr_session_set_ask(s: *mut CrispasrSession, prompt: *const c_char) -> c_int;
735 pub fn crispasr_session_detect_language(
736 s: *mut CrispasrSession,
737 pcm: *const c_float,
738 n_samples: c_int,
739 lid_model_path: *const c_char,
740 method: c_int,
741 out_lang: *mut c_char,
742 out_lang_cap: c_int,
743 out_prob: *mut c_float,
744 ) -> c_int;
745
746 pub fn crispasr_text_detect_language(
761 text: *const c_char,
762 model_path: *const c_char,
763 n_threads: c_int,
764 out_label_buf: *mut c_char,
765 out_label_cap: c_int,
766 out_confidence: *mut c_float,
767 ) -> c_int;
768
769 pub fn crispasr_detect_backend_from_gguf(
770 path: *const c_char,
771 out_name: *mut c_char,
772 out_cap: c_int,
773 ) -> c_int;
774
775 pub fn crispasr_punc_init(model_path: *const c_char) -> *mut c_void;
777 pub fn crispasr_punc_process(ctx: *mut c_void, text: *const c_char) -> *mut c_char;
778 pub fn crispasr_punc_free_text(text: *mut c_char);
779 pub fn crispasr_punc_free(ctx: *mut c_void);
780
781 pub fn crispasr_c_api_version() -> *const c_char;
782
783 pub fn crispasr_kokoro_lang_is_german_abi(lang: *const c_char) -> bool;
786 pub fn crispasr_kokoro_lang_has_native_voice_abi(lang: *const c_char) -> bool;
787 pub fn crispasr_kokoro_resolve_model_for_lang_abi(
788 model_path: *const c_char,
789 lang: *const c_char,
790 out_path: *mut c_char,
791 out_path_len: c_int,
792 ) -> c_int;
793 pub fn crispasr_kokoro_resolve_fallback_voice_abi(
794 model_path: *const c_char,
795 lang: *const c_char,
796 out_path: *mut c_char,
797 out_path_len: c_int,
798 out_picked: *mut c_char,
799 out_picked_len: c_int,
800 ) -> c_int;
801
802 pub fn crispasr_titanet_init(model_path: *const c_char, n_threads: i32) -> *mut c_void;
804 pub fn crispasr_titanet_free(ctx: *mut c_void);
805 pub fn crispasr_titanet_embed(
806 ctx: *mut c_void,
807 pcm_16k: *const c_float,
808 n_samples: i32,
809 out: *mut c_float,
810 ) -> i32;
811 pub fn crispasr_titanet_cosine_sim(a: *const c_float, b: *const c_float, dim: i32) -> c_float;
812
813 pub fn crispasr_speaker_db_load(dir_path: *const c_char) -> *mut c_void;
815 pub fn crispasr_speaker_db_free(db: *mut c_void);
816 pub fn crispasr_speaker_db_count(db: *const c_void) -> i32;
817 pub fn crispasr_speaker_db_match(
818 db: *const c_void,
819 embedding: *const c_float,
820 dim: i32,
821 threshold: c_float,
822 out_name: *mut c_char,
823 out_cap: i32,
824 ) -> c_float;
825 pub fn crispasr_speaker_db_enroll(
826 dir_path: *const c_char,
827 name: *const c_char,
828 embedding: *const c_float,
829 dim: i32,
830 ) -> i32;
831
832 pub fn crispasr_speaker_embedder_make_abi(
841 model_spec: *const c_char,
842 n_threads: i32,
843 cache_dir: *const c_char,
844 ) -> *mut c_void;
845
846 pub fn crispasr_speaker_embedder_free_abi(embedder: *mut c_void);
847
848 pub fn crispasr_speaker_embedder_dim_abi(embedder: *const c_void) -> i32;
851
852 pub fn crispasr_speaker_embedder_embed_abi(
855 embedder: *mut c_void,
856 pcm_16k: *const c_float,
857 n_samples: i32,
858 out: *mut c_float,
859 ) -> i32;
860
861 pub fn crispasr_speaker_embedder_name_abi(embedder: *const c_void) -> *const c_char;
862
863 pub fn crispasr_speaker_cluster_abi(
868 embeddings: *const c_float,
869 n: i32,
870 dim: i32,
871 merge_threshold: c_float,
872 max_speakers: i32,
873 labels_out: *mut i32,
874 ) -> i32;
875
876 pub fn crispasr_pyannote_cache_compute_abi(
880 full_audio: *const c_float,
881 n_samples: i32,
882 model_path: *const c_char,
883 n_threads: i32,
884 ) -> *mut c_void;
885
886 pub fn crispasr_pyannote_cache_free_abi(cache: *mut c_void);
887
888 pub fn crispasr_pyannote_cache_apply_abi(
892 cache: *const c_void,
893 slice_t0_cs: i64,
894 segs: *mut CrispasrDiarizeSegAbi,
895 n_segs: i32,
896 ) -> i32;
897
898 pub fn crispasr_params_set_language(p: *mut WhisperFullParams, lang: *const c_char);
900 pub fn crispasr_params_set_translate(p: *mut WhisperFullParams, v: c_int);
901 pub fn crispasr_params_set_detect_language(p: *mut WhisperFullParams, v: c_int);
902 pub fn crispasr_params_set_token_timestamps(p: *mut WhisperFullParams, v: c_int);
903 pub fn crispasr_params_set_n_threads(p: *mut WhisperFullParams, n: c_int);
904 pub fn crispasr_params_set_max_len(p: *mut WhisperFullParams, n: c_int);
905 pub fn crispasr_params_set_best_of(p: *mut WhisperFullParams, n: c_int);
906 pub fn crispasr_params_set_split_on_word(p: *mut WhisperFullParams, v: c_int);
907 pub fn crispasr_params_set_no_context(p: *mut WhisperFullParams, v: c_int);
908 pub fn crispasr_params_set_single_segment(p: *mut WhisperFullParams, v: c_int);
909 pub fn crispasr_params_set_print_realtime(p: *mut WhisperFullParams, v: c_int);
910 pub fn crispasr_params_set_print_progress(p: *mut WhisperFullParams, v: c_int);
911 pub fn crispasr_params_set_print_timestamps(p: *mut WhisperFullParams, v: c_int);
912 pub fn crispasr_params_set_print_special(p: *mut WhisperFullParams, v: c_int);
913 pub fn crispasr_params_set_suppress_blank(p: *mut WhisperFullParams, v: c_int);
914 pub fn crispasr_params_set_temperature(p: *mut WhisperFullParams, t: c_float);
915 pub fn crispasr_params_set_max_tokens(p: *mut WhisperFullParams, n: c_int);
916 pub fn crispasr_params_set_initial_prompt(p: *mut WhisperFullParams, prompt: *const c_char);
917 pub fn crispasr_params_set_alt_n(p: *mut WhisperFullParams, n: c_int);
918
919 pub fn crispasr_token_t0(ctx: *mut WhisperContext, i_seg: c_int, i_tok: c_int) -> i64;
921 pub fn crispasr_token_t1(ctx: *mut WhisperContext, i_seg: c_int, i_tok: c_int) -> i64;
922 pub fn crispasr_token_p(ctx: *mut WhisperContext, i_seg: c_int, i_tok: c_int) -> c_float;
923 pub fn crispasr_token_n_alts(ctx: *mut WhisperContext, i_seg: c_int, i_tok: c_int) -> c_int;
924 pub fn crispasr_token_alt_id(
925 ctx: *mut WhisperContext,
926 i_seg: c_int,
927 i_tok: c_int,
928 i_alt: c_int,
929 ) -> i32;
930 pub fn crispasr_token_alt_p(
931 ctx: *mut WhisperContext,
932 i_seg: c_int,
933 i_tok: c_int,
934 i_alt: c_int,
935 ) -> c_float;
936 pub fn crispasr_token_alt_text(
937 ctx: *mut WhisperContext,
938 i_seg: c_int,
939 i_tok: c_int,
940 i_alt: c_int,
941 out: *mut c_char,
942 out_cap: c_int,
943 ) -> c_int;
944
945 pub fn crispasr_detect_language(
947 ctx: *mut WhisperContext,
948 pcm: *const c_float,
949 n_samples: c_int,
950 n_threads: c_int,
951 out_code: *mut c_char,
952 out_cap: c_int,
953 ) -> c_float;
954
955 pub fn crispasr_vad_segments(
957 vad_model_path: *const c_char,
958 pcm: *const c_float,
959 n_samples: c_int,
960 sample_rate: c_int,
961 threshold: c_float,
962 min_speech_ms: c_int,
963 min_silence_ms: c_int,
964 n_threads: c_int,
965 use_gpu: c_int,
966 out_spans: *mut *mut c_float,
967 ) -> c_int;
968 pub fn crispasr_vad_slices(
969 vad_model_path: *const c_char,
970 pcm: *const c_float,
971 n_samples: c_int,
972 sample_rate: c_int,
973 threshold: c_float,
974 min_speech_ms: c_int,
975 min_silence_ms: c_int,
976 speech_pad_ms: c_int,
977 max_chunk_duration_s: c_float,
978 n_threads: c_int,
979 out_spans: *mut *mut c_float,
980 ) -> c_int;
981 pub fn crispasr_vad_free(spans: *mut c_float);
982
983 pub fn crispasr_lcs_dedup_prefix_count(
985 prev_tail_tokens: *const i32,
986 n_prev: c_int,
987 curr_tokens: *const i32,
988 n_curr: c_int,
989 min_lcs_length: c_int,
990 ) -> c_int;
991
992 pub fn crispasr_stream_open(
994 ctx: *mut WhisperContext,
995 n_threads: c_int,
996 step_ms: c_int,
997 length_ms: c_int,
998 keep_ms: c_int,
999 language: *const c_char,
1000 translate: c_int,
1001 ) -> *mut CrispasrStream;
1002
1003 pub fn crispasr_parakeet_init(
1005 model_path: *const c_char,
1006 n_threads: c_int,
1007 use_flash: c_int,
1008 ) -> *mut c_void;
1009 pub fn crispasr_parakeet_free(ctx: *mut c_void);
1010 pub fn crispasr_parakeet_transcribe(
1011 ctx: *mut c_void,
1012 pcm: *const c_float,
1013 n_samples: c_int,
1014 language: *const c_char,
1015 ) -> *mut c_void;
1016 pub fn crispasr_parakeet_result_text(r: *mut c_void) -> *const c_char;
1017 pub fn crispasr_parakeet_result_n_words(r: *mut c_void) -> c_int;
1018 pub fn crispasr_parakeet_result_word_text(r: *mut c_void, i: c_int) -> *const c_char;
1019 pub fn crispasr_parakeet_result_word_t0(r: *mut c_void, i: c_int) -> i64;
1020 pub fn crispasr_parakeet_result_word_t1(r: *mut c_void, i: c_int) -> i64;
1021 pub fn crispasr_parakeet_result_n_tokens(r: *mut c_void) -> c_int;
1022 pub fn crispasr_parakeet_result_token_text(r: *mut c_void, i: c_int) -> *const c_char;
1023 pub fn crispasr_parakeet_result_token_t0(r: *mut c_void, i: c_int) -> i64;
1024 pub fn crispasr_parakeet_result_token_t1(r: *mut c_void, i: c_int) -> i64;
1025 pub fn crispasr_parakeet_result_token_p(r: *mut c_void, i: c_int) -> c_float;
1026 pub fn crispasr_parakeet_result_free(r: *mut c_void);
1027
1028 pub fn crispasr_enhance_audio_rnnoise(
1030 in_pcm: *const c_float,
1031 n_samples: i32,
1032 out_pcm: *mut c_float,
1033 out_cap: i32,
1034 ) -> c_int;
1035
1036 pub fn crispasr_session_open_with_params(
1038 model_path: *const c_char,
1039 backend_name: *const c_char,
1040 params: *const c_void,
1041 ) -> *mut CrispasrSession;
1042
1043 pub fn crispasr_session_result_word_n_alts(
1045 r: *mut CrispasrSessionResult,
1046 i_seg: c_int,
1047 i_word: c_int,
1048 ) -> c_int;
1049 pub fn crispasr_session_result_word_alt_text(
1050 r: *mut CrispasrSessionResult,
1051 i_seg: c_int,
1052 i_word: c_int,
1053 i_alt: c_int,
1054 ) -> *const c_char;
1055 pub fn crispasr_session_result_word_alt_p(
1056 r: *mut CrispasrSessionResult,
1057 i_seg: c_int,
1058 i_word: c_int,
1059 i_alt: c_int,
1060 ) -> c_float;
1061}
1062
1063#[repr(C)]
1075pub struct CrispasrChatSession(c_void);
1076
1077pub const CRISPASR_CHAT_ERR_ABORTED: i32 = 40;
1081
1082#[repr(C)]
1086#[derive(Clone, Copy, Debug)]
1087pub struct CrispasrChatError {
1088 pub code: i32,
1089 pub message: [c_char; 256],
1090}
1091
1092impl Default for CrispasrChatError {
1093 fn default() -> Self {
1094 Self {
1095 code: 0,
1096 message: [0; 256],
1097 }
1098 }
1099}
1100
1101#[repr(C)]
1104#[derive(Clone, Copy, Debug)]
1105pub struct CrispasrChatMessage {
1106 pub role: *const c_char,
1107 pub content: *const c_char,
1108}
1109
1110#[repr(C)]
1114#[derive(Clone, Copy, Debug)]
1115pub struct CrispasrChatOpenParams {
1116 pub n_threads: c_int,
1117 pub n_threads_batch: c_int,
1118 pub n_ctx: c_int,
1120 pub n_batch: c_int,
1121 pub n_ubatch: c_int,
1122 pub n_gpu_layers: c_int,
1124 pub use_mmap: bool,
1125 pub use_mlock: bool,
1126 pub embeddings: bool,
1127 pub chat_template: *const c_char,
1130}
1131
1132impl Default for CrispasrChatOpenParams {
1133 fn default() -> Self {
1134 Self {
1135 n_threads: 0,
1136 n_threads_batch: 0,
1137 n_ctx: 0,
1138 n_batch: 0,
1139 n_ubatch: 0,
1140 n_gpu_layers: 0,
1141 use_mmap: false,
1142 use_mlock: false,
1143 embeddings: false,
1144 chat_template: std::ptr::null(),
1145 }
1146 }
1147}
1148
1149#[repr(C)]
1152#[derive(Clone, Copy, Debug)]
1153pub struct CrispasrChatGenerateParams {
1154 pub max_tokens: c_int,
1155 pub temperature: c_float,
1157 pub top_k: c_int,
1158 pub top_p: c_float,
1159 pub min_p: c_float,
1160 pub repeat_penalty: c_float,
1161 pub repeat_last_n: c_int,
1162 pub seed: u32,
1164 pub stop: *const *const c_char,
1166 pub n_stop: usize,
1167 pub prefill_only: bool,
1169}
1170
1171impl Default for CrispasrChatGenerateParams {
1172 fn default() -> Self {
1173 Self {
1174 max_tokens: 0,
1175 temperature: 0.0,
1176 top_k: 0,
1177 top_p: 0.0,
1178 min_p: 0.0,
1179 repeat_penalty: 0.0,
1180 repeat_last_n: 0,
1181 seed: 0,
1182 stop: std::ptr::null(),
1183 n_stop: 0,
1184 prefill_only: false,
1185 }
1186 }
1187}
1188
1189pub type CrispasrChatOnToken =
1193 Option<unsafe extern "C" fn(utf8_chunk: *const c_char, user: *mut c_void)>;
1194
1195pub type CrispasrChatAbortCallback = Option<unsafe extern "C" fn(user: *mut c_void) -> bool>;
1202
1203extern "C" {
1204 pub fn crispasr_chat_open_params_default(out: *mut CrispasrChatOpenParams);
1206 pub fn crispasr_chat_generate_params_default(out: *mut CrispasrChatGenerateParams);
1207
1208 pub fn crispasr_chat_open(
1210 model_path: *const c_char,
1211 params: *const CrispasrChatOpenParams,
1212 err: *mut CrispasrChatError,
1213 ) -> *mut CrispasrChatSession;
1214 pub fn crispasr_chat_close(s: *mut CrispasrChatSession);
1215 pub fn crispasr_chat_reset(s: *mut CrispasrChatSession, err: *mut CrispasrChatError) -> i32;
1216
1217 pub fn crispasr_chat_generate(
1221 s: *mut CrispasrChatSession,
1222 messages: *const CrispasrChatMessage,
1223 n_messages: usize,
1224 params: *const CrispasrChatGenerateParams,
1225 err: *mut CrispasrChatError,
1226 ) -> *mut c_char;
1227
1228 pub fn crispasr_chat_generate_stream(
1232 s: *mut CrispasrChatSession,
1233 messages: *const CrispasrChatMessage,
1234 n_messages: usize,
1235 params: *const CrispasrChatGenerateParams,
1236 on_token: CrispasrChatOnToken,
1237 user: *mut c_void,
1238 err: *mut CrispasrChatError,
1239 ) -> i32;
1240
1241 pub fn crispasr_chat_set_abort_callback(
1245 s: *mut CrispasrChatSession,
1246 cb: CrispasrChatAbortCallback,
1247 user: *mut c_void,
1248 );
1249
1250 pub fn crispasr_chat_template_name(s: *mut CrispasrChatSession) -> *const c_char;
1252 pub fn crispasr_chat_n_ctx(s: *mut CrispasrChatSession) -> i32;
1253
1254 pub fn crispasr_chat_count_tokens(
1258 s: *mut CrispasrChatSession,
1259 messages: *const CrispasrChatMessage,
1260 n_messages: usize,
1261 err: *mut CrispasrChatError,
1262 ) -> i32;
1263
1264 pub fn crispasr_chat_memory_estimate(
1267 model_path: *const c_char,
1268 params: *const CrispasrChatOpenParams,
1269 err: *mut CrispasrChatError,
1270 ) -> usize;
1271
1272 pub fn crispasr_chat_string_free(s: *mut c_char);
1273
1274 pub fn crispasr_chat_ai_disclosure_text() -> *const c_char;
1277}
1278
1279#[cfg(test)]
1280mod tests {
1281 use super::*;
1282
1283 #[test]
1288 fn diarize_abi_layout() {
1289 use std::mem::{offset_of, size_of};
1290 assert_eq!(size_of::<CrispasrDiarizeSegAbi>(), 24);
1291 assert_eq!(size_of::<CrispasrDiarizeOptsAbi>(), 48);
1292 assert_eq!(offset_of!(CrispasrDiarizeOptsAbi, slice_t0_cs), 8);
1293 assert_eq!(offset_of!(CrispasrDiarizeOptsAbi, pyannote_model_path), 16);
1294 assert_eq!(
1295 offset_of!(CrispasrDiarizeOptsAbi, foxnose_embedder_path),
1296 24
1297 );
1298 assert_eq!(offset_of!(CrispasrDiarizeOptsAbi, min_speakers), 32);
1299 assert_eq!(offset_of!(CrispasrDiarizeOptsAbi, num_speakers), 40);
1300 }
1301
1302 #[test]
1307 fn chat_abi_layout() {
1308 use std::mem::{offset_of, size_of};
1309
1310 assert_eq!(size_of::<CrispasrChatError>(), 260);
1311 assert_eq!(offset_of!(CrispasrChatError, message), 4);
1312
1313 assert_eq!(size_of::<CrispasrChatMessage>(), 16);
1314 assert_eq!(offset_of!(CrispasrChatMessage, content), 8);
1315
1316 assert_eq!(size_of::<CrispasrChatOpenParams>(), 40);
1317 assert_eq!(offset_of!(CrispasrChatOpenParams, n_gpu_layers), 20);
1318 assert_eq!(offset_of!(CrispasrChatOpenParams, use_mmap), 24);
1319 assert_eq!(offset_of!(CrispasrChatOpenParams, use_mlock), 25);
1320 assert_eq!(offset_of!(CrispasrChatOpenParams, embeddings), 26);
1321 assert_eq!(offset_of!(CrispasrChatOpenParams, chat_template), 32);
1322
1323 assert_eq!(size_of::<CrispasrChatGenerateParams>(), 56);
1324 assert_eq!(offset_of!(CrispasrChatGenerateParams, seed), 28);
1325 assert_eq!(offset_of!(CrispasrChatGenerateParams, stop), 32);
1326 assert_eq!(offset_of!(CrispasrChatGenerateParams, n_stop), 40);
1327 assert_eq!(offset_of!(CrispasrChatGenerateParams, prefill_only), 48);
1328 }
1329}