#![allow(clippy::wildcard_imports)]
#[must_use]
pub fn elevenlabs_smd_platform<'a>(provider: &'a str, model: Option<&str>) -> &'a str {
if provider == "elevenlabs"
&& model.is_some_and(|m| m.starts_with("eleven_v3") | m.starts_with("eleven_v4"))
{
"elevenlabs-v3"
} else {
provider
}
}
#[cfg(feature = "speechmarkdown")]
#[must_use]
pub fn ssml_to_dialect(ssml: &str, smd_platform: &str) -> Option<String> {
use speechmarkdown_rust::{Platform, SpeechMarkdownParser};
let platform = Platform::from_platform_str(smd_platform)?;
let smd = SpeechMarkdownParser::to_smd(ssml).ok()?;
SpeechMarkdownParser::to_ssml(&smd, platform).ok()
}
#[must_use]
pub fn parse_elevenlabs_alignment(
alignment: &serde_json::Map<String, serde_json::Value>,
) -> Vec<(String, f32, f32)> {
let Some(chars) = alignment.get("characters").and_then(|v| v.as_array()) else {
return Vec::new();
};
let Some(starts) = alignment
.get("character_start_times_seconds")
.and_then(|v| v.as_array())
else {
return Vec::new();
};
let Some(ends) = alignment
.get("character_end_times_seconds")
.and_then(|v| v.as_array())
else {
return Vec::new();
};
let mut out: Vec<(String, f32, f32)> = Vec::new();
let mut current_word = String::new();
let mut word_start: f32 = 0.0;
let mut has_started = false;
for i in 0..chars.len() {
let char_str = chars.get(i).and_then(|v| v.as_str()).unwrap_or("");
let start_time = starts
.get(i)
.and_then(serde_json::Value::as_f64)
.unwrap_or(0.0) as f32;
let end_time = ends
.get(i)
.and_then(serde_json::Value::as_f64)
.unwrap_or(0.0) as f32;
if char_str.trim().is_empty() {
if has_started {
out.push((current_word.clone(), word_start, end_time));
current_word.clear();
has_started = false;
}
} else if !has_started {
word_start = start_time;
has_started = true;
current_word.push_str(char_str);
} else {
current_word.push_str(char_str);
}
}
if has_started {
let end_time = ends
.last()
.and_then(serde_json::Value::as_f64)
.unwrap_or(0.0) as f32;
out.push((current_word, word_start, end_time));
}
out
}