msedge-tts 0.4.0

This library is a wrapper of MSEdge Read aloud function API. You can use it to synthesize text to speech with many voices MS provided.
Documentation
use crate::error::Result;
use crate::tts::{
    Payload, RustlsStream, SpeechConfig, build_config_message, build_ssml_message,
    client::SynthesizedAudio, websocket_connect,
};
use std::io::{Read, Write};
use std::net::TcpStream;

/// Sync Client
pub struct MSEdgeTTSClient<T: Read + Write>(pub(crate) tungstenite::WebSocket<RustlsStream<T>>);

impl<T: Read + Write> MSEdgeTTSClient<T> {
    /// Synthesize text to speech with a [SpeechConfig] synchronously
    pub fn synthesize(&mut self, text: &str, config: &SpeechConfig) -> Result<SynthesizedAudio> {
        let config_message = build_config_message(config);
        let ssml_message = build_ssml_message(text, config);
        self.0.send(config_message)?;
        self.0.send(ssml_message)?;

        let mut audio_bytes = Vec::new();
        let mut audio_metadata = Vec::new();
        let mut turn_start = false;
        let mut response = false;
        let mut turn_end = false;
        loop {
            if turn_end {
                break;
            }

            let message = self.0.read()?;
            let payload = Payload::process(message, &mut turn_start, &mut response, &mut turn_end)?;
            if let Some(payload) = payload {
                match payload {
                    Payload::AudioBytes(payload) => {
                        audio_bytes.push(payload);
                    }
                    Payload::AudioMetadata(metadata) => {
                        audio_metadata.extend(metadata);
                    }
                }
            }
        }

        let audio_bytes = audio_bytes
            .iter()
            .flat_map(|(bytes, index)| &bytes[*index..])
            .copied()
            .collect();

        Ok(SynthesizedAudio {
            audio_format: config.audio_format.clone(),
            audio_bytes,
            audio_metadata,
        })
    }
}

/// Create Sync TTS [Client](MSEdgeTTSClient)
pub fn connect() -> Result<MSEdgeTTSClient<TcpStream>> {
    Ok(MSEdgeTTSClient(websocket_connect()?))
}

#[cfg(feature = "proxy")]
#[cfg_attr(docsrs, doc(cfg(all(feature = "blocking", feature = "proxy"))))]
pub use crate::tts::proxy::blocking::connect_proxy;