stt-cli 0.2.1

Speech to text Cli using Groq API and OpenAI API
// --- WAV Conversion Layer ---
// This Tower layer converts audio chunks into WAV format for downstream services.
// Used as the first stage in the pipeline to ensure audio is in the correct format for transcription.

use tower::{Layer, Service};
use std::task::{Context, Poll};
use std::pin::Pin;
use futures::future::BoxFuture;
use crate::pipeline::types::{AudioRequest, WavAudioRequest, AudioResponse, PipelineError};

/// Tower Layer that wraps a service to convert AudioRequest to WavAudioRequest.
#[derive(Clone, Debug, Default)]
pub struct WavConversionLayer;

impl<S> Layer<S> for WavConversionLayer {
    type Service = WavConversionService<S>;

    fn layer(&self, inner: S) -> Self::Service {
        WavConversionService { inner }
    }
}

/// Tower Service that performs the WAV conversion.
#[derive(Clone, Debug)]
pub struct WavConversionService<S> {
    pub(crate) inner: S,
}

impl<S> Service<AudioRequest> for WavConversionService<S>
where
    S: Service<WavAudioRequest, Response = AudioResponse, Error = PipelineError> + Send + 'static,
    S::Future: Send + 'static,
{
    type Response = AudioResponse;
    type Error = PipelineError;
    type Future = BoxFuture<'static, Result<Self::Response, Self::Error>>;

    fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
        self.inner.poll_ready(cx).map_err(|e| PipelineError::WavConversionError(format!("Inner service not ready: {}", e)))
    }

    fn call(&mut self, req: AudioRequest) -> Self::Future {
        // Converts the audio chunk to WAV and passes it to the inner service.
        let wav_data = match crate::transcription::convert_samples_to_wav(&req.0.data) {
            Ok(data) => data,
            Err(e) => return Box::pin(async move { Err(PipelineError::WavConversionError(e.to_string())) }),
        };
        let wav_req = WavAudioRequest {
            wav_data,
            timestamp: req.0.timestamp,
        };
        let fut = self.inner.call(wav_req);
        Box::pin(async move { fut.await })
    }
}