Files
ttyverse-extensions/tts.pl
2025-07-29 11:29:27 -04:00

153 lines
5.4 KiB
Perl

# TTYverse Text-to-Speech Extension
# By Storm Dragon: https://stormux.org/
# Support Storm Dragon's work: https://patreon.com/stormux
# Published under the Floodgap Free Software License: http://www.floodgap.com/software/ffsl/
# What is it?
# This extension uses text-to-speech to read incoming fediverse posts.
# Multiple synthesizer engines are supported for accessibility.
# Usage:
# Toggle TTS on/off: /tts
# Get help: /tts help
# Load extension when starting TTYverse or add to configuration
$addaction = sub {
my $command = shift;
my $speak = "";
# Get current TTS state from config
my $tts_config = "$ENV{'HOME'}/.config/ttyverse/tts_enabled";
if (-e $tts_config) {
open TTSSETTINGS, $tts_config;
$speak = <TTSSETTINGS>;
close TTSSETTINGS;
chomp($speak) if defined($speak);
} else {
$speak = 0;
}
if ($command eq '/tts') {
if ((!defined($speak)) || ($speak eq 1)) {
$speak = 0;
print $streamout "-- Text-to-speech disabled\n";
} else {
$speak = 1;
print $streamout "-- Text-to-speech enabled\n";
}
# Save new state
open TTSSETTINGS, ">$tts_config";
print TTSSETTINGS "$speak";
close TTSSETTINGS;
return 1;
}
if ($command eq "/tts help") {
my $ttsHelp = "TTYverse Text-to-Speech Extension\n\n" .
"Commands:\n" .
" /tts - Toggle speech on/off\n" .
" /tts help - Show this help\n\n" .
"Configuration (add to TTYverse config):\n\n" .
"extpref_tts_synthesizer=synthName\n" .
" Available: espeak (default), festival, pico, cepstral, mac\n\n" .
"extpref_tts_language=languageCode\n" .
" Default: en-US (supported by espeak and pico)\n\n" .
"extpref_tts_rate=number\n" .
" Speech rate, default: 175 (espeak only)\n\n" .
"extpref_tts_variant=name\n" .
" Voice variant/name (espeak variants, cepstral/mac voices)\n";
print $streamout "$ttsHelp";
return 1;
}
return 0;
};
$handle = sub {
my $ref = shift;
my $class = shift;
# Skip TTS during initial timeline load
if ($last_id eq 0) {
&defaulthandle($ref);
return 1;
}
my $speak = "";
# Get TTS state from config
my $tts_config = "$ENV{'HOME'}/.config/ttyverse/tts_enabled";
if (-e $tts_config) {
open TTSSETTINGS, $tts_config;
$speak = <TTSSETTINGS>;
close TTSSETTINGS;
chomp($speak) if defined($speak);
} else {
$speak = 0;
}
# Initialize TTS configuration
my $soundCommand = "paplay"; # Default for modern Linux/PulseAudio
my $synthesizer = $extpref_tts_synthesizer || "espeak";
my $language = $extpref_tts_language || "en-US";
my $variant = $extpref_tts_variant || "";
my $rate = $extpref_tts_rate || "";
# Override sound command if configured
if ($extpref_sound_command) {
$soundCommand = $extpref_sound_command;
}
# Extract post content for TTS
my $postText = &descape($ref->{'account'}->{'display_name'} || $ref->{'account'}->{'username'}) .
" posted: " . &descape($ref->{'content'});
# Make speech more accessible
$postText =~ s/\"/ /g; # Remove quotes
$postText =~ s/ \#/ hashtag /g; # Make hashtags readable
$postText =~ s/https?:\/\/\S+/ link /g; # Simplify links
$postText =~ s/www\./ /g; # Remove www
$postText =~ s/\// forward slash /g; # Make slashes readable
$postText =~ s/\\/ back slash /g; # Make backslashes readable
$postText =~ s/\blol\b/ laughs out loud /gi; # Expand common abbreviations
$postText =~ s/\brofl\b/ rolling on the floor laughing /gi;
$postText =~ s/<[^>]*>//g; # Remove any remaining HTML
my $speechCommand = "";
# Configure synthesizer command
if ($synthesizer eq "cepstral") {
$speechCommand = "aoss swift ";
if ($variant ne "") {
$speechCommand .= "-n $variant ";
}
$speechCommand .= "\"$postText\"";
} elsif ($synthesizer eq "espeak") {
if ($rate eq "") {
$rate = "175";
}
$speechCommand = "$synthesizer -v " . lc($language);
if ($variant ne "") {
$speechCommand .= "+$variant";
}
$speechCommand .= " -s $rate \"$postText\"";
} elsif ($synthesizer eq "festival") {
$speechCommand = "echo \"$postText\" | festival --tts";
} elsif ($synthesizer eq "mac") {
$speechCommand = "say ";
if ($variant ne "") {
$speechCommand .= "-v $variant ";
}
$speechCommand .= "\"$postText\"";
} elsif ($synthesizer eq "pico") {
$speechCommand = "pico2wave -l $language -w /tmp/ttyverse.wav \"$postText\" && $soundCommand /tmp/ttyverse.wav";
}
# Speak the post if TTS is enabled
if ($speak eq 1) {
system("$speechCommand");
}
# Allow TTYverse to display the post normally
&defaulthandle($ref);
return 1;
};