# 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 = ; 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 = ; 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; };