mirror of
https://github.com/coral/sipcord-bridge.git
synced 2026-06-29 09:23:14 -06:00
better tts a little
This commit is contained in:
parent
fb8bd8e738
commit
2630ca154f
|
|
@ -72,9 +72,10 @@ timeout_seconds = 10
|
||||||
max_attempts = 3
|
max_attempts = 3
|
||||||
```
|
```
|
||||||
|
|
||||||
The menu uses `espeak-ng` for local text-to-speech. Press `#` to repeat the
|
The menu uses `espeak-ng` for local text-to-speech with a female English voice.
|
||||||
current menu page, `9` for the next page when available, and `*` for the
|
Emoji and common Discord channel separators are skipped in spoken names. Press
|
||||||
previous page when available.
|
`#` to repeat the current menu page, `9` for the next page when available, and
|
||||||
|
`*` for the previous page when available.
|
||||||
|
|
||||||
### 4a. Run with Docker (recommended)
|
### 4a. Run with Docker (recommended)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1594,7 +1594,7 @@ async fn select_guild_from_menu(
|
||||||
let prompt = build_option_prompt(
|
let prompt = build_option_prompt(
|
||||||
"Select a Discord server.",
|
"Select a Discord server.",
|
||||||
page_items,
|
page_items,
|
||||||
|guild| guild.name.as_str(),
|
|guild| clean_tts_label(&guild.name),
|
||||||
page,
|
page,
|
||||||
guilds.len(),
|
guilds.len(),
|
||||||
);
|
);
|
||||||
|
|
@ -1651,11 +1651,11 @@ async fn select_channel_from_menu(
|
||||||
let mut attempts = 0u8;
|
let mut attempts = 0u8;
|
||||||
loop {
|
loop {
|
||||||
let page_items = page_slice(channels, page);
|
let page_items = page_slice(channels, page);
|
||||||
let intro = format!("Select a voice channel in {}.", guild.name);
|
let intro = format!("Select a voice channel in {}.", clean_tts_label(&guild.name));
|
||||||
let prompt = build_option_prompt(
|
let prompt = build_option_prompt(
|
||||||
&intro,
|
&intro,
|
||||||
page_items,
|
page_items,
|
||||||
|channel| channel.name.as_str(),
|
|channel| clean_tts_label(&channel.name),
|
||||||
page,
|
page,
|
||||||
channels.len(),
|
channels.len(),
|
||||||
);
|
);
|
||||||
|
|
@ -1716,7 +1716,7 @@ fn has_next_page(total: usize, page: usize) -> bool {
|
||||||
fn build_option_prompt<T>(
|
fn build_option_prompt<T>(
|
||||||
intro: &str,
|
intro: &str,
|
||||||
items: &[T],
|
items: &[T],
|
||||||
label: impl Fn(&T) -> &str,
|
label: impl Fn(&T) -> String,
|
||||||
page: usize,
|
page: usize,
|
||||||
total: usize,
|
total: usize,
|
||||||
) -> String {
|
) -> String {
|
||||||
|
|
@ -1734,6 +1734,54 @@ fn build_option_prompt<T>(
|
||||||
prompt
|
prompt
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn clean_tts_label(label: &str) -> String {
|
||||||
|
let mut out = String::new();
|
||||||
|
let mut last_was_space = false;
|
||||||
|
|
||||||
|
for ch in label.chars() {
|
||||||
|
let replacement = if is_tts_skipped_symbol(ch) || ch.is_control() {
|
||||||
|
Some(' ')
|
||||||
|
} else {
|
||||||
|
match ch {
|
||||||
|
'_' | '-' | '|' | '/' | '\\' | ':' | ';' | ',' | '.' | '#' | '[' | ']' | '('
|
||||||
|
| ')' | '{' | '}' => Some(' '),
|
||||||
|
_ => Some(ch),
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(ch) = replacement {
|
||||||
|
if ch.is_whitespace() {
|
||||||
|
if !last_was_space {
|
||||||
|
out.push(' ');
|
||||||
|
last_was_space = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
out.push(ch);
|
||||||
|
last_was_space = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let cleaned = out.trim();
|
||||||
|
if cleaned.is_empty() {
|
||||||
|
"unnamed".to_string()
|
||||||
|
} else {
|
||||||
|
cleaned.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn is_tts_skipped_symbol(ch: char) -> bool {
|
||||||
|
matches!(
|
||||||
|
ch as u32,
|
||||||
|
0x200D
|
||||||
|
| 0x20E3
|
||||||
|
| 0xFE00..=0xFE0F
|
||||||
|
| 0x2500..=0x257F
|
||||||
|
| 0x2600..=0x27BF
|
||||||
|
| 0x1F000..=0x1FAFF
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
async fn wait_for_menu_digit(
|
async fn wait_for_menu_digit(
|
||||||
call_id: CallId,
|
call_id: CallId,
|
||||||
menu: &MenuRoute,
|
menu: &MenuRoute,
|
||||||
|
|
@ -1846,6 +1894,8 @@ async fn synthesize_tts_samples(
|
||||||
let out_path = std::env::temp_dir().join(format!("sipcord-tts-{}-{}.wav", call_id, stamp));
|
let out_path = std::env::temp_dir().join(format!("sipcord-tts-{}-{}.wav", call_id, stamp));
|
||||||
|
|
||||||
let espeak_status = Command::new("espeak-ng")
|
let espeak_status = Command::new("espeak-ng")
|
||||||
|
.arg("-v")
|
||||||
|
.arg("en+f3")
|
||||||
.arg("-w")
|
.arg("-w")
|
||||||
.arg(&raw_path)
|
.arg(&raw_path)
|
||||||
.arg(text)
|
.arg(text)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue