#![cfg(feature = "stt-cloud-wasm")]
use async_trait::async_trait;
use super::{post_openai_compatible, SttProvider};
use crate::stt::SttError;
pub const DEFAULT_ENDPOINT: &str = "https://api.groq.com/openai/v1/audio/transcriptions";
pub const DEFAULT_MODEL: &str = "whisper-large-v3";
#[derive(Debug, Clone)]
pub struct GroqProvider {
endpoint: String,
api_key: String,
model: String,
}
impl GroqProvider {
pub fn new(api_key: impl Into<String>) -> Self {
Self {
endpoint: DEFAULT_ENDPOINT.to_string(),
api_key: api_key.into(),
model: DEFAULT_MODEL.to_string(),
}
}
pub fn with_endpoint(mut self, endpoint: impl Into<String>) -> Self {
self.endpoint = endpoint.into();
self
}
pub fn with_model(mut self, model: impl Into<String>) -> Self {
self.model = model.into();
self
}
}
#[cfg_attr(not(target_arch = "wasm32"), async_trait)]
#[cfg_attr(target_arch = "wasm32", async_trait(?Send))]
impl SttProvider for GroqProvider {
async fn transcribe(
&self,
audio_bytes: Vec<u8>,
audio_mime: &str,
lang_hint: Option<&str>,
) -> Result<String, SttError> {
post_openai_compatible(
&self.endpoint,
&self.api_key,
&self.model,
audio_bytes,
audio_mime,
lang_hint,
)
.await
}
fn name(&self) -> &'static str {
"groq"
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn defaults_point_at_groq_dot_com() {
let p = GroqProvider::new("gsk_...");
assert_eq!(p.endpoint, DEFAULT_ENDPOINT);
assert_eq!(p.model, DEFAULT_MODEL);
}
#[test]
fn builder_overrides_endpoint_and_model() {
let p = GroqProvider::new("gsk_...")
.with_endpoint("https://groq-mirror.example/v1/audio/transcriptions")
.with_model("whisper-large-v3-turbo");
assert_eq!(
p.endpoint,
"https://groq-mirror.example/v1/audio/transcriptions"
);
assert_eq!(p.model, "whisper-large-v3-turbo");
}
}