stt-cli 0.2.1

Speech to text Cli using Groq API and OpenAI API
// providers/groq.rs
use crate::providers::TranscriptionProvider;
use anyhow::{Context, Result};
use async_trait::async_trait;
use groq_api_rust::{GroqClient, SpeechToTextRequest};
use std::env;
use std::time::Duration;
use tracing::{debug, info, instrument};
use tokio::task;

// #[derive(Clone)]
pub struct GroqProvider {
    client: GroqClient,
}

impl GroqProvider {
    pub fn new() -> Self {
        let api_key = env::var("GROQ_API_KEY").expect("GROQ_API_KEY environment variable not set");
        Self {
            client: GroqClient::new(api_key, None),
        }
    }
}

#[async_trait]
impl TranscriptionProvider for GroqProvider {
    fn name(&self) -> &'static str {
        "Groq"
    }

    fn min_chunk_duration(&self) -> Duration {
        Duration::from_secs(5) // 5 seconds minimum for Groq
    }

    #[instrument(skip(self, audio_data))]
    async fn transcribe(&self, audio_data: &[u8]) -> Result<String> {
        info!("Starting Groq transcription request");
        debug!("Audio data size: {} bytes", audio_data.len());

        let request = SpeechToTextRequest::new(audio_data.to_vec())
            .temperature(0.7)
            .language("en")
            .model("whisper-large-v3");

        // Use blocking call in async context
        let client = &self.client;
        let response = task::spawn_blocking(move || {
            client.speech_to_text(request)
        })
        .await
        .context("Failed to execute transcription task")?
        .context("Failed to get response from Groq")?;

        info!("Groq transcription successful");
        debug!("Received transcription: {}", response.text);

        Ok(response.text)
    }
}