1use std::ffi::CString;
16
17use transcribe_cpp_sys as sys;
18
19use crate::error::Result;
20
21#[derive(Debug, Clone, Default, PartialEq)]
25#[cfg_attr(
26 feature = "serde",
27 derive(serde::Serialize, serde::Deserialize),
28 serde(default)
29)]
30pub struct WhisperRunOptions {
31 pub initial_prompt: Option<String>,
32 pub condition_on_prev_tokens: Option<bool>,
33 pub temperature: Option<f32>,
34 pub temperature_inc: Option<f32>,
35 pub compression_ratio_thold: Option<f32>,
36 pub logprob_thold: Option<f32>,
37 pub no_speech_thold: Option<f32>,
38 pub max_prev_context_tokens: Option<i32>,
39 pub seed: Option<u32>,
40 pub max_initial_timestamp: Option<f32>,
41}
42
43#[derive(Debug, Clone, Default, PartialEq, Eq)]
45#[cfg_attr(
46 feature = "serde",
47 derive(serde::Serialize, serde::Deserialize),
48 serde(default)
49)]
50pub struct MoonshineStreamingOptions {
51 pub min_decode_interval_ms: Option<i32>,
52}
53
54#[derive(Debug, Clone, Default, PartialEq, Eq)]
56#[cfg_attr(
57 feature = "serde",
58 derive(serde::Serialize, serde::Deserialize),
59 serde(default)
60)]
61pub struct ParakeetStreamOptions {
62 pub att_context_right: Option<i32>,
63}
64
65#[derive(Debug, Clone, Default, PartialEq, Eq)]
67#[cfg_attr(
68 feature = "serde",
69 derive(serde::Serialize, serde::Deserialize),
70 serde(default)
71)]
72pub struct ParakeetBufferedStreamOptions {
73 pub left_ms: Option<i32>,
74 pub chunk_ms: Option<i32>,
75 pub right_ms: Option<i32>,
76}
77
78#[derive(Debug, Clone, Default, PartialEq, Eq)]
80#[cfg_attr(
81 feature = "serde",
82 derive(serde::Serialize, serde::Deserialize),
83 serde(default)
84)]
85pub struct VoxtralRealtimeStreamOptions {
86 pub num_delay_tokens: Option<i32>,
87 pub min_decode_interval_ms: Option<i32>,
88}
89
90#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
94#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
95pub enum SortformerPreset {
96 #[default]
97 Default,
98 VeryHighLatency,
100 HighLatency,
102 LowLatency,
105}
106
107impl SortformerPreset {
108 fn to_sys(self) -> sys::transcribe_sortformer_preset {
109 match self {
110 SortformerPreset::Default => {
111 sys::transcribe_sortformer_preset::TRANSCRIBE_SORTFORMER_PRESET_DEFAULT
112 }
113 SortformerPreset::VeryHighLatency => {
114 sys::transcribe_sortformer_preset::TRANSCRIBE_SORTFORMER_PRESET_VERY_HIGH_LATENCY
115 }
116 SortformerPreset::HighLatency => {
117 sys::transcribe_sortformer_preset::TRANSCRIBE_SORTFORMER_PRESET_HIGH_LATENCY
118 }
119 SortformerPreset::LowLatency => {
120 sys::transcribe_sortformer_preset::TRANSCRIBE_SORTFORMER_PRESET_LOW_LATENCY
121 }
122 }
123 }
124}
125
126#[derive(Debug, Clone, Default, PartialEq, Eq)]
129#[cfg_attr(
130 feature = "serde",
131 derive(serde::Serialize, serde::Deserialize),
132 serde(default)
133)]
134pub struct SortformerDiarizeOptions {
135 pub preset: Option<SortformerPreset>,
136}
137
138#[derive(Debug, Clone, PartialEq, Eq)]
141#[non_exhaustive]
142#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
143pub enum DiarizeExtension {
144 Sortformer(SortformerDiarizeOptions),
145}
146
147pub(crate) enum DiarizeExtRaw {
149 Sortformer(Box<sys::transcribe_sortformer_diarize_ext>),
150}
151
152impl DiarizeExtRaw {
153 pub(crate) fn ext_ptr(&self) -> *const sys::transcribe_ext {
154 match self {
155 DiarizeExtRaw::Sortformer(e) => {
156 (&**e) as *const sys::transcribe_sortformer_diarize_ext
157 as *const sys::transcribe_ext
158 }
159 }
160 }
161}
162
163impl DiarizeExtension {
164 pub(crate) fn materialize(&self) -> DiarizeExtRaw {
165 match self {
166 DiarizeExtension::Sortformer(o) => {
167 let mut e: sys::transcribe_sortformer_diarize_ext = unsafe { std::mem::zeroed() };
168 unsafe { sys::transcribe_sortformer_diarize_ext_init(&mut e) };
169 set(&mut e.preset, o.preset.map(SortformerPreset::to_sys));
170 DiarizeExtRaw::Sortformer(Box::new(e))
171 }
172 }
173 }
174}
175
176#[derive(Debug, Clone, PartialEq)]
178#[non_exhaustive]
179#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
180pub enum RunExtension {
181 Whisper(WhisperRunOptions),
182}
183
184#[derive(Debug, Clone, PartialEq, Eq)]
186#[non_exhaustive]
187#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
188pub enum StreamExtension {
189 ParakeetStream(ParakeetStreamOptions),
190 ParakeetBuffered(ParakeetBufferedStreamOptions),
191 MoonshineStreaming(MoonshineStreamingOptions),
192 VoxtralRealtime(VoxtralRealtimeStreamOptions),
193}
194
195pub(crate) enum RunExtRaw {
200 Whisper {
201 ext: Box<sys::transcribe_whisper_run_ext>,
202 _prompt: Option<CString>,
203 },
204}
205
206impl RunExtRaw {
207 pub(crate) fn ext_ptr(&self) -> *const sys::transcribe_ext {
208 match self {
209 RunExtRaw::Whisper { ext, .. } => {
211 (&**ext) as *const sys::transcribe_whisper_run_ext as *const sys::transcribe_ext
212 }
213 }
214 }
215}
216
217impl RunExtension {
218 pub(crate) fn materialize(&self) -> Result<RunExtRaw> {
219 match self {
220 RunExtension::Whisper(o) => {
221 let mut ext: sys::transcribe_whisper_run_ext = unsafe { std::mem::zeroed() };
222 unsafe { sys::transcribe_whisper_run_ext_init(&mut ext) };
223 let prompt = o.initial_prompt.as_deref().map(CString::new).transpose()?;
226 if let Some(c) = prompt.as_ref() {
227 ext.initial_prompt = c.as_ptr();
228 }
229 set(
230 &mut ext.condition_on_prev_tokens,
231 o.condition_on_prev_tokens,
232 );
233 set(&mut ext.temperature, o.temperature);
234 set(&mut ext.temperature_inc, o.temperature_inc);
235 set(&mut ext.compression_ratio_thold, o.compression_ratio_thold);
236 set(&mut ext.logprob_thold, o.logprob_thold);
237 set(&mut ext.no_speech_thold, o.no_speech_thold);
238 set(&mut ext.max_prev_context_tokens, o.max_prev_context_tokens);
239 set(&mut ext.seed, o.seed);
240 set(&mut ext.max_initial_timestamp, o.max_initial_timestamp);
241 Ok(RunExtRaw::Whisper {
242 ext: Box::new(ext),
243 _prompt: prompt,
244 })
245 }
246 }
247 }
248}
249
250pub(crate) enum StreamExtRaw {
252 ParakeetStream(Box<sys::transcribe_parakeet_stream_ext>),
253 ParakeetBuffered(Box<sys::transcribe_parakeet_buffered_stream_ext>),
254 MoonshineStreaming(Box<sys::transcribe_moonshine_streaming_stream_ext>),
255 VoxtralRealtime(Box<sys::transcribe_voxtral_realtime_stream_ext>),
256}
257
258impl StreamExtRaw {
259 pub(crate) fn ext_ptr(&self) -> *const sys::transcribe_ext {
260 match self {
261 StreamExtRaw::ParakeetStream(e) => {
262 (&**e) as *const sys::transcribe_parakeet_stream_ext as *const sys::transcribe_ext
263 }
264 StreamExtRaw::ParakeetBuffered(e) => {
265 (&**e) as *const sys::transcribe_parakeet_buffered_stream_ext
266 as *const sys::transcribe_ext
267 }
268 StreamExtRaw::MoonshineStreaming(e) => {
269 (&**e) as *const sys::transcribe_moonshine_streaming_stream_ext
270 as *const sys::transcribe_ext
271 }
272 StreamExtRaw::VoxtralRealtime(e) => {
273 (&**e) as *const sys::transcribe_voxtral_realtime_stream_ext
274 as *const sys::transcribe_ext
275 }
276 }
277 }
278}
279
280impl StreamExtension {
281 pub(crate) fn materialize(&self) -> StreamExtRaw {
282 match self {
283 StreamExtension::ParakeetStream(o) => {
284 let mut e: sys::transcribe_parakeet_stream_ext = unsafe { std::mem::zeroed() };
285 unsafe { sys::transcribe_parakeet_stream_ext_init(&mut e) };
286 set(&mut e.att_context_right, o.att_context_right);
287 StreamExtRaw::ParakeetStream(Box::new(e))
288 }
289 StreamExtension::ParakeetBuffered(o) => {
290 let mut e: sys::transcribe_parakeet_buffered_stream_ext =
291 unsafe { std::mem::zeroed() };
292 unsafe { sys::transcribe_parakeet_buffered_stream_ext_init(&mut e) };
293 set(&mut e.left_ms, o.left_ms);
294 set(&mut e.chunk_ms, o.chunk_ms);
295 set(&mut e.right_ms, o.right_ms);
296 StreamExtRaw::ParakeetBuffered(Box::new(e))
297 }
298 StreamExtension::MoonshineStreaming(o) => {
299 let mut e: sys::transcribe_moonshine_streaming_stream_ext =
300 unsafe { std::mem::zeroed() };
301 unsafe { sys::transcribe_moonshine_streaming_stream_ext_init(&mut e) };
302 set(&mut e.min_decode_interval_ms, o.min_decode_interval_ms);
303 StreamExtRaw::MoonshineStreaming(Box::new(e))
304 }
305 StreamExtension::VoxtralRealtime(o) => {
306 let mut e: sys::transcribe_voxtral_realtime_stream_ext =
307 unsafe { std::mem::zeroed() };
308 unsafe { sys::transcribe_voxtral_realtime_stream_ext_init(&mut e) };
309 set(&mut e.num_delay_tokens, o.num_delay_tokens);
310 set(&mut e.min_decode_interval_ms, o.min_decode_interval_ms);
311 StreamExtRaw::VoxtralRealtime(Box::new(e))
312 }
313 }
314 }
315}
316
317fn set<T>(slot: &mut T, value: Option<T>) {
319 if let Some(v) = value {
320 *slot = v;
321 }
322}