我正在尝试使用来自 Go 1.11 的 Amazon 新的流式转录 API。目前亚马逊仅提供 Java SDK,所以我正在尝试低级方式。
唯一相关的文档在这里,但它没有显示端点。我在一个Java 示例中找到了它https://transcribestreaming.<region>.amazonaws.com
,我正在尝试爱尔兰地区,即https://transcribestreaming.eu-west-1.amazonaws.com
. 这是我打开 HTTP/2 双向流的代码:
import (
"crypto/tls"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/aws/external"
"github.com/aws/aws-sdk-go-v2/aws/signer/v4"
"golang.org/x/net/http2"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"time"
)
const (
HeaderKeyLanguageCode = "x-amzn-transcribe-language-code" // en-US
HeaderKeyMediaEncoding = "x-amzn-transcribe-media-encoding" // pcm only
HeaderKeySampleRate = "x-amzn-transcribe-sample-rate" // 8000, 16000 ... 48000
HeaderKeySessionId = "x-amzn-transcribe-session-id" // For retrying a session. Pattern: [a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}
HeaderKeyVocabularyName = "x-amzn-transcribe-vocabulary-name"
HeaderKeyRequestId = "x-amzn-request-id"
)
...
region := "eu-west-1"
cfg, err := external.LoadDefaultAWSConfig(aws.Config{
Region: region,
})
if err != nil {
log.Printf("could not load default AWS config: %v", err)
return
}
signer := v4.NewSigner(cfg.Credentials)
transport := &http2.Transport{
TLSClientConfig: &tls.Config{
// allow insecure just for debugging
InsecureSkipVerify: true,
},
}
client := &http.Client{
Transport: transport,
}
signTime := time.Now()
header := http.Header{}
header.Set(HeaderKeyLanguageCode, "en-US")
header.Set(HeaderKeyMediaEncoding, "pcm")
header.Set(HeaderKeySampleRate, "16000")
header.Set("Content-type", "application/json")
// Bi-directional streaming via a pipe.
pr, pw := io.Pipe()
req, err := http.NewRequest(http.MethodPost, "https://transcribestreaming.eu-west-1.amazonaws.com/stream-transcription", ioutil.NopCloser(pr))
if err != nil {
log.Printf("err: %+v", err)
return
}
req.Header = header
_, err = signer.Sign(req, nil, "transcribe", region, signTime)
if err != nil {
log.Printf("problem signing headers: %+v", err)
return
}
// This freezes and ends after 5 minutes with "unexpected EOF".
res, err := client.Do(req)
...
问题是执行请求 ( client.Do(req)
) 冻结了五分钟,然后以“意外 EOF”错误结束。
任何想法我做错了什么?有人在没有 Java SDK 的情况下成功使用了新的流式转录 API 吗?
编辑(2019 年 3 月 11 日):
我再次对此进行了测试,现在它不会超时,而是立即返回200 OK
响应。但是,响应正文中有一个“异常”:{"Output":{"__type":"com.amazon.coral.service#SerializationException"},"Version":"1.0"}
io.Pipe
我尝试使用(如上面的代码)以及文档中描述的 JSON 主体打开 HTTP2 流:
{
"AudioStream": {
"AudioEvent": {
"AudioChunk": ""
}
}
}
结果是一样的。
编辑(2019 年 3 月 13 日):
正如@gpeng 所提到的,content-type
从标头中删除将修复SerializationException
. 但随后出现 IAM 异常,需要将transcription:StartStreamTranscription
权限添加到您的 IAM 用户。这虽然在 AWS IAM 控制台中无处可寻,但必须手动添加为自定义 JSON 权限:/
这里还有一个新的/另一个文档文档显示不正确host
和一个新的content-type
(不要使用它content-type
,请求将返回 404)。
删除content-type
并添加新权限后,现在我得到了一个异常{"Message":"A complete signal was sent without the preceding empty frame."}
。也永远写入管道块,所以我又被卡住了。新文档中描述的消息与旧文档中的消息不同,现在终于二进制了,但我不明白它们。任何想法如何在 Go 中发送此类 HTTP2 消息?
编辑(2019 年第 15 场比赛):*
如果您收到有关签名不匹配的 HTTP 403 错误,请不要设置transfer-encoding
和x-amz-content-sha256
HTTP 标头。当我设置它们时,使用 AWS SDK 的 V4 签名者对请求进行签名,然后我收到 HTTP 403The request signature we calculated does not match the signature you provided.