1use std::ffi::CString;
15
16use transcribe_cpp_sys as sys;
17
18use crate::error::Result;
19
20#[derive(Debug, Clone, Default, PartialEq)]
23pub struct WhisperRunOptions {
24 pub initial_prompt: Option<String>,
25 pub condition_on_prev_tokens: Option<bool>,
26 pub temperature: Option<f32>,
27 pub temperature_inc: Option<f32>,
28 pub compression_ratio_thold: Option<f32>,
29 pub logprob_thold: Option<f32>,
30 pub no_speech_thold: Option<f32>,
31 pub max_prev_context_tokens: Option<i32>,
32 pub seed: Option<u32>,
33 pub max_initial_timestamp: Option<f32>,
34}
35
36#[derive(Debug, Clone, Default, PartialEq, Eq)]
38pub struct MoonshineStreamingOptions {
39 pub min_decode_interval_ms: Option<i32>,
40}
41
42#[derive(Debug, Clone, Default, PartialEq, Eq)]
44pub struct ParakeetStreamOptions {
45 pub att_context_right: Option<i32>,
46}
47
48#[derive(Debug, Clone, Default, PartialEq, Eq)]
50pub struct ParakeetBufferedStreamOptions {
51 pub left_ms: Option<i32>,
52 pub chunk_ms: Option<i32>,
53 pub right_ms: Option<i32>,
54}
55
56#[derive(Debug, Clone, Default, PartialEq, Eq)]
58pub struct VoxtralRealtimeStreamOptions {
59 pub num_delay_tokens: Option<i32>,
60 pub min_decode_interval_ms: Option<i32>,
61}
62
63#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
67pub enum SortformerPreset {
68 #[default]
69 Default,
70 VeryHighLatency,
72 HighLatency,
74 LowLatency,
77}
78
79impl SortformerPreset {
80 fn to_sys(self) -> sys::transcribe_sortformer_preset {
81 match self {
82 SortformerPreset::Default => {
83 sys::transcribe_sortformer_preset::TRANSCRIBE_SORTFORMER_PRESET_DEFAULT
84 }
85 SortformerPreset::VeryHighLatency => {
86 sys::transcribe_sortformer_preset::TRANSCRIBE_SORTFORMER_PRESET_VERY_HIGH_LATENCY
87 }
88 SortformerPreset::HighLatency => {
89 sys::transcribe_sortformer_preset::TRANSCRIBE_SORTFORMER_PRESET_HIGH_LATENCY
90 }
91 SortformerPreset::LowLatency => {
92 sys::transcribe_sortformer_preset::TRANSCRIBE_SORTFORMER_PRESET_LOW_LATENCY
93 }
94 }
95 }
96}
97
98#[derive(Debug, Clone, Default, PartialEq, Eq)]
102pub struct SortformerStreamOptions {
103 pub preset: Option<SortformerPreset>,
104}
105
106#[derive(Debug, Clone, PartialEq)]
108#[non_exhaustive]
109pub enum RunExtension {
110 Whisper(WhisperRunOptions),
111 Sortformer(SortformerStreamOptions),
112}
113
114#[derive(Debug, Clone, PartialEq, Eq)]
116#[non_exhaustive]
117pub enum StreamExtension {
118 ParakeetStream(ParakeetStreamOptions),
119 ParakeetBuffered(ParakeetBufferedStreamOptions),
120 MoonshineStreaming(MoonshineStreamingOptions),
121 VoxtralRealtime(VoxtralRealtimeStreamOptions),
122}
123
124pub(crate) enum RunExtRaw {
129 Whisper {
130 ext: Box<sys::transcribe_whisper_run_ext>,
131 _prompt: Option<CString>,
132 },
133 Sortformer(Box<sys::transcribe_sortformer_stream_ext>),
134}
135
136impl RunExtRaw {
137 pub(crate) fn ext_ptr(&self) -> *const sys::transcribe_ext {
138 match self {
139 RunExtRaw::Whisper { ext, .. } => {
141 (&**ext) as *const sys::transcribe_whisper_run_ext as *const sys::transcribe_ext
142 }
143 RunExtRaw::Sortformer(e) => {
144 (&**e) as *const sys::transcribe_sortformer_stream_ext as *const sys::transcribe_ext
145 }
146 }
147 }
148}
149
150impl RunExtension {
151 pub(crate) fn materialize(&self) -> Result<RunExtRaw> {
152 match self {
153 RunExtension::Whisper(o) => {
154 let mut ext: sys::transcribe_whisper_run_ext = unsafe { std::mem::zeroed() };
155 unsafe { sys::transcribe_whisper_run_ext_init(&mut ext) };
156 let prompt = o.initial_prompt.as_deref().map(CString::new).transpose()?;
159 if let Some(c) = prompt.as_ref() {
160 ext.initial_prompt = c.as_ptr();
161 }
162 set(
163 &mut ext.condition_on_prev_tokens,
164 o.condition_on_prev_tokens,
165 );
166 set(&mut ext.temperature, o.temperature);
167 set(&mut ext.temperature_inc, o.temperature_inc);
168 set(&mut ext.compression_ratio_thold, o.compression_ratio_thold);
169 set(&mut ext.logprob_thold, o.logprob_thold);
170 set(&mut ext.no_speech_thold, o.no_speech_thold);
171 set(&mut ext.max_prev_context_tokens, o.max_prev_context_tokens);
172 set(&mut ext.seed, o.seed);
173 set(&mut ext.max_initial_timestamp, o.max_initial_timestamp);
174 Ok(RunExtRaw::Whisper {
175 ext: Box::new(ext),
176 _prompt: prompt,
177 })
178 }
179 RunExtension::Sortformer(o) => {
180 let mut ext: sys::transcribe_sortformer_stream_ext = unsafe { std::mem::zeroed() };
181 unsafe { sys::transcribe_sortformer_stream_ext_init(&mut ext) };
182 set(&mut ext.preset, o.preset.map(SortformerPreset::to_sys));
183 Ok(RunExtRaw::Sortformer(Box::new(ext)))
184 }
185 }
186 }
187}
188
189pub(crate) enum StreamExtRaw {
191 ParakeetStream(Box<sys::transcribe_parakeet_stream_ext>),
192 ParakeetBuffered(Box<sys::transcribe_parakeet_buffered_stream_ext>),
193 MoonshineStreaming(Box<sys::transcribe_moonshine_streaming_stream_ext>),
194 VoxtralRealtime(Box<sys::transcribe_voxtral_realtime_stream_ext>),
195}
196
197impl StreamExtRaw {
198 pub(crate) fn ext_ptr(&self) -> *const sys::transcribe_ext {
199 match self {
200 StreamExtRaw::ParakeetStream(e) => {
201 (&**e) as *const sys::transcribe_parakeet_stream_ext as *const sys::transcribe_ext
202 }
203 StreamExtRaw::ParakeetBuffered(e) => {
204 (&**e) as *const sys::transcribe_parakeet_buffered_stream_ext
205 as *const sys::transcribe_ext
206 }
207 StreamExtRaw::MoonshineStreaming(e) => {
208 (&**e) as *const sys::transcribe_moonshine_streaming_stream_ext
209 as *const sys::transcribe_ext
210 }
211 StreamExtRaw::VoxtralRealtime(e) => {
212 (&**e) as *const sys::transcribe_voxtral_realtime_stream_ext
213 as *const sys::transcribe_ext
214 }
215 }
216 }
217}
218
219impl StreamExtension {
220 pub(crate) fn materialize(&self) -> StreamExtRaw {
221 match self {
222 StreamExtension::ParakeetStream(o) => {
223 let mut e: sys::transcribe_parakeet_stream_ext = unsafe { std::mem::zeroed() };
224 unsafe { sys::transcribe_parakeet_stream_ext_init(&mut e) };
225 set(&mut e.att_context_right, o.att_context_right);
226 StreamExtRaw::ParakeetStream(Box::new(e))
227 }
228 StreamExtension::ParakeetBuffered(o) => {
229 let mut e: sys::transcribe_parakeet_buffered_stream_ext =
230 unsafe { std::mem::zeroed() };
231 unsafe { sys::transcribe_parakeet_buffered_stream_ext_init(&mut e) };
232 set(&mut e.left_ms, o.left_ms);
233 set(&mut e.chunk_ms, o.chunk_ms);
234 set(&mut e.right_ms, o.right_ms);
235 StreamExtRaw::ParakeetBuffered(Box::new(e))
236 }
237 StreamExtension::MoonshineStreaming(o) => {
238 let mut e: sys::transcribe_moonshine_streaming_stream_ext =
239 unsafe { std::mem::zeroed() };
240 unsafe { sys::transcribe_moonshine_streaming_stream_ext_init(&mut e) };
241 set(&mut e.min_decode_interval_ms, o.min_decode_interval_ms);
242 StreamExtRaw::MoonshineStreaming(Box::new(e))
243 }
244 StreamExtension::VoxtralRealtime(o) => {
245 let mut e: sys::transcribe_voxtral_realtime_stream_ext =
246 unsafe { std::mem::zeroed() };
247 unsafe { sys::transcribe_voxtral_realtime_stream_ext_init(&mut e) };
248 set(&mut e.num_delay_tokens, o.num_delay_tokens);
249 set(&mut e.min_decode_interval_ms, o.min_decode_interval_ms);
250 StreamExtRaw::VoxtralRealtime(Box::new(e))
251 }
252 }
253 }
254}
255
256fn set<T>(slot: &mut T, value: Option<T>) {
258 if let Some(v) = value {
259 *slot = v;
260 }
261}