Speak
view release on metacpan or search on metacpan
lib/Speak.pm view on Meta::CPAN
my $content = $response->content;
if (length ($content) == 0) {
carp "Fetch successful but content is empty";
return;
}
# Check if we got HTML instead of MP3 (e.g. Captcha/Error)
if ($content =~ /^\s*<(!DOCTYPE|html)/i) {
carp
"Received HTML response instead of MP3 (likely CAPTCHA/Blocked) from URL: $url";
return;
}
return $content;
} else {
carp "Failed to fetch TTS: " . $response->status_line;
return;
}
} ## end sub _fetch_mp3
sub _convert_mp3_to_wav ($mp3, $wav) {
# Try ffmpeg
if (system ("which ffmpeg >/dev/null 2>&1") == 0) {
return system ("ffmpeg -y -v error -i \"$mp3\" \"$wav\"") == 0;
}
# Try mpg123
if (system ("which mpg123 >/dev/null 2>&1") == 0) {
return system ("mpg123 -q -w \"$wav\" \"$mp3\"") == 0;
}
# Try lame
if (system ("which lame >/dev/null 2>&1") == 0) {
return system ("lame --decode --quiet \"$mp3\" \"$wav\"") == 0;
}
# Fallback to sox (might fail if no mp3 handler)
return system ("sox \"$mp3\" \"$wav\"") == 0;
} ## end sub _convert_mp3_to_wav
## no critic (Subroutines::ProhibitExcessComplexity)
sub speak ($msg, $log = undef, $lang = undef, $persona = undef) {
=pod
=head2 speak($msg, $log, $lang, $persona)
Convert $msg to speech.
Parameters:
=for html <blockquote>
=over
=item $msg:
Message to speak. If $msg is defined and scalar then that is the message
to speak. If it is a file handle then the text will be read from that file.
Otherwise the text in the clipboard will be used.
=item $log
If provided, errors and messages will be logged to the logfile, otherwise to speak.log
=item $lang
Language code (e.g. 'en', 'en-gb', 'en-au'). Defaults to $ENV{SPEAK_LANG} or 'en'.
=item $persona
Optional. The persona name to use for the voice. If provided, the MCP server is used instead of standard TTS.
=back
=for html </blockquote>
Returns:
=for html <blockquote>
=over
=item Nothing
=back
=for html </blockquote>
=cut
$log = Speak::Logger->new (
path => '/var/log',
name => 'speak',
timestamped => 'yes',
append => 1,
) unless $log;
unless ($msg) {
$msg = eval {
## no critic (InputOutput::RequireBriefOpen)
open my $olderr, '>&', \*STDERR or croak "Cannot dup STDERR: $!";
open STDERR, '>', '/dev/null' or croak "Cannot redirect STDERR: $!";
my $res = Clipboard->paste;
open STDERR, '>&', $olderr or croak "Cannot restore STDERR: $!";
close $olderr;
## use critic
$res;
};
$msg //= '';
} ## end unless ($msg)
$msg = do {local $/; <$msg>} if ref $msg eq 'GLOB';
my %sys_conf;
foreach my $conf_file (@CONFIG_PATHS) {
if (-f $conf_file) {
%sys_conf = _get_config ($conf_file);
last;
( run in 1.799 second using v1.01-cache-2.11-cpan-ff9377addf4 )