如何在 Perl 中使用 HTTP POST 接收 wav 音频文件并在 Asterisk AGI 中播放
How to receive a wav audio file using HTTP POST in Perl and play it in Asterisk AGI
我正在使用 IBM Watson TTS 进行文本转语音功能。
我可以使用 Postman 的 Send and Download 功能获取音频文件。但是,我应该如何在 Perl 中做到这一点。
我对 Perl 完全陌生。
我使用 Perl 的原因是我需要在 Asterisk AGI 中实现 TTS。
编辑: 我可以保存文件。但是,无法在 Asterisk 中播放。
我正在为 POST 请求和播放音频使用以下代码片段:
....
my $uaresponse = $ua->post(
"$url",
Content_Type => "application/json",
Accept => "audio/wav",
Authorization => "Basic OWFmMjhhYmItMWFmMi00ZjU0LWE1YTAtNTJhNGUxNjRjNGQ1OnlkYWgwN3BRdEJMVA==",
Content => $json_text,
);
if(!$uaresponse->is_success){
print "Failed request to IBM \n";
} else{
print "Successful with IBM \n";
($fh, $tmpname) = tempfile("ggl_XXXXXXXX", DIR => $tmpdir, UNLINK => 1);
$tmpname = $uaresponse->content;
# my approach is wrong somewhere here...??
#print "$tmpname\n";
# open(my $out, '>:wav', "$tmpname.wav") or die "unable to open $!";
# print $out pack('a*', $ua_response2->content);
# Playback and save file in cache #
$res = playback($tmpname, $intkey);
die if ($res < 0);
last if ($res > 0);
}
sub checkresponse {
my $input = <STDIN>;
my @values;
chomp $input;
if ($input =~ /^200 result=(-?\d+)\s?(.*)$/) {
@values = ("", "");
} else {
$input .= <STDIN> if ($input =~ /^520-Invalid/);
warn "$name Unexpected result: $input\n";
@values = (-1, -1);
}
return @values;
}
sub playback {
my ($file, $keys) = @_;
my @response;
print "STREAM FILE $file \"$keys\"\n";
@response = checkresponse();
if ($response[0] >= 32 && chr($response[0]) =~ /[\w*#]/) {
console_log("Got digit chr($response[0])") if ($debug);
print "SET EXTENSION ", chr($response[0]), "\n";
checkresponse();
print "SET PRIORITY 1\n";
checkresponse();
} elsif ($response[0] == -1) {
console_log("Failed to play $file.");
}
return $response[0];
}
我假设您正在使用 LWP::UserAgent for your $ua
and File::Temp 作为 tempfile
函数。
tempfile
returns a filehandle and a filename. $uaresponse
is an HTTP::Response object, and its method content
returns HTTP 响应的未解码原始主体。
您正在将该正文(可能是完整的 wave 文件)分配给保存临时文件文件名的变量。您永远不会将内容写入文件。您正在尝试在注释掉的代码中执行此操作,但由于您已经覆盖了文件名,因此它不会起作用。
你可以直接使用tempfile
给你的$fh
。由于 wave 是二进制数据,因此在 $fh
上设置 binmode
是有意义的。然后就可以直接写入了。
if(!$uaresponse->is_success){
print "Failed request to IBM \n";
} else{
print "Successful with IBM \n";
my ($fh, $tmpname) = tempfile("ggl_XXXXXXXX.wav", DIR => $tmpdir, UNLINK => 1);
binmode $fh;
print $fh $uaresponse->content; # or with pack if you want
}
应该是这样。 Perl 中没有 :wav
编码,因此您尝试的那部分代码无论如何都不会起作用。
请注意,在您对 tempfile
的调用中,您设置了 UNLINK => 1
选项,这意味着临时文件将在您的程序结束后自动删除。看起来这不是你想要的。看起来您想保留该文件。在那种情况下,也许 File::Temp 不是正确的方法。
这里是按最喜欢的顺序排列的问题。
1) 文件必须具有 EXACT 格式:wav、pcm 8khz、16 位、单声道。任何其他格式都将被忽略。如果您有其他格式,您首先使用 sox 或其他工具更改格式。如果您不确定格式,您应该使用 sox 或其他工具来确保格式受支持。
2) 您发送给asterisk 的文件名末尾应该没有.wav 扩展名。用户Asterisk::AGI模块,无需从头重写agi交互。
3) 文件必须有 asterisk 用户的读取权限
4) 文件所在的目录必须有星号用户
对open/read的权限
@arheops 和@simbabque 提供的答案肯定有帮助。
阻碍我的程序正常运行的恶作剧错误是打印语句:
print "Successful with IBM \n";
我通过在 Asterisk CLI 上执行打印语句的艰难方式了解到,上面的一个给出了一个我忽略的错误(510 无效或未知命令)。一旦我注释掉打印响应,它就可以正常工作了。
但是,如果你想使用打印,正确的方法应该是:
print "VERBOSE \" Successful with IBM \" \n";
我正在使用 IBM Watson TTS 进行文本转语音功能。 我可以使用 Postman 的 Send and Download 功能获取音频文件。但是,我应该如何在 Perl 中做到这一点。 我对 Perl 完全陌生。 我使用 Perl 的原因是我需要在 Asterisk AGI 中实现 TTS。
编辑: 我可以保存文件。但是,无法在 Asterisk 中播放。
我正在为 POST 请求和播放音频使用以下代码片段:
....
my $uaresponse = $ua->post(
"$url",
Content_Type => "application/json",
Accept => "audio/wav",
Authorization => "Basic OWFmMjhhYmItMWFmMi00ZjU0LWE1YTAtNTJhNGUxNjRjNGQ1OnlkYWgwN3BRdEJMVA==",
Content => $json_text,
);
if(!$uaresponse->is_success){
print "Failed request to IBM \n";
} else{
print "Successful with IBM \n";
($fh, $tmpname) = tempfile("ggl_XXXXXXXX", DIR => $tmpdir, UNLINK => 1);
$tmpname = $uaresponse->content;
# my approach is wrong somewhere here...??
#print "$tmpname\n";
# open(my $out, '>:wav', "$tmpname.wav") or die "unable to open $!";
# print $out pack('a*', $ua_response2->content);
# Playback and save file in cache #
$res = playback($tmpname, $intkey);
die if ($res < 0);
last if ($res > 0);
}
sub checkresponse {
my $input = <STDIN>;
my @values;
chomp $input;
if ($input =~ /^200 result=(-?\d+)\s?(.*)$/) {
@values = ("", "");
} else {
$input .= <STDIN> if ($input =~ /^520-Invalid/);
warn "$name Unexpected result: $input\n";
@values = (-1, -1);
}
return @values;
}
sub playback {
my ($file, $keys) = @_;
my @response;
print "STREAM FILE $file \"$keys\"\n";
@response = checkresponse();
if ($response[0] >= 32 && chr($response[0]) =~ /[\w*#]/) {
console_log("Got digit chr($response[0])") if ($debug);
print "SET EXTENSION ", chr($response[0]), "\n";
checkresponse();
print "SET PRIORITY 1\n";
checkresponse();
} elsif ($response[0] == -1) {
console_log("Failed to play $file.");
}
return $response[0];
}
我假设您正在使用 LWP::UserAgent for your $ua
and File::Temp 作为 tempfile
函数。
tempfile
returns a filehandle and a filename. $uaresponse
is an HTTP::Response object, and its method content
returns HTTP 响应的未解码原始主体。
您正在将该正文(可能是完整的 wave 文件)分配给保存临时文件文件名的变量。您永远不会将内容写入文件。您正在尝试在注释掉的代码中执行此操作,但由于您已经覆盖了文件名,因此它不会起作用。
你可以直接使用tempfile
给你的$fh
。由于 wave 是二进制数据,因此在 $fh
上设置 binmode
是有意义的。然后就可以直接写入了。
if(!$uaresponse->is_success){
print "Failed request to IBM \n";
} else{
print "Successful with IBM \n";
my ($fh, $tmpname) = tempfile("ggl_XXXXXXXX.wav", DIR => $tmpdir, UNLINK => 1);
binmode $fh;
print $fh $uaresponse->content; # or with pack if you want
}
应该是这样。 Perl 中没有 :wav
编码,因此您尝试的那部分代码无论如何都不会起作用。
请注意,在您对 tempfile
的调用中,您设置了 UNLINK => 1
选项,这意味着临时文件将在您的程序结束后自动删除。看起来这不是你想要的。看起来您想保留该文件。在那种情况下,也许 File::Temp 不是正确的方法。
这里是按最喜欢的顺序排列的问题。
1) 文件必须具有 EXACT 格式:wav、pcm 8khz、16 位、单声道。任何其他格式都将被忽略。如果您有其他格式,您首先使用 sox 或其他工具更改格式。如果您不确定格式,您应该使用 sox 或其他工具来确保格式受支持。
2) 您发送给asterisk 的文件名末尾应该没有.wav 扩展名。用户Asterisk::AGI模块,无需从头重写agi交互。
3) 文件必须有 asterisk 用户的读取权限
4) 文件所在的目录必须有星号用户
对open/read的权限@arheops 和@simbabque 提供的答案肯定有帮助。
阻碍我的程序正常运行的恶作剧错误是打印语句:
print "Successful with IBM \n";
我通过在 Asterisk CLI 上执行打印语句的艰难方式了解到,上面的一个给出了一个我忽略的错误(510 无效或未知命令)。一旦我注释掉打印响应,它就可以正常工作了。
但是,如果你想使用打印,正确的方法应该是:
print "VERBOSE \" Successful with IBM \" \n";