[英]Amazon Transcribe Streaming service request in Node.js with Http/2 gives no response
我正在尝试将 Amazon Transcribe Streaming Service 与来自 Node.js 的 http2 请求一起使用,这是我遵循Streaming 请求格式的文档链接。 根据此文档的端点是https://transcribe-streaming .<'region'>.amazonaws.com,但是向该 url 发出请求会出现 url not found 错误。 但是在Java 示例中发现端点为https://transcribestreaming .''.amazonaws.com,因此向此 url 发出请求不会返回任何错误或响应。 我正在从 us-east-1 地区尝试。
这是我正在尝试的代码。
const http2 = require('http2');
var aws4 = require('aws4');
var opts = {
service: 'transcribe',
region: 'us-east-1',
path: '/stream-transcription',
headers:{
'content-type': 'application/json',
'x-amz-target': 'com.amazonaws.transcribe.Transcribe.StartStreamTranscription'
}
}
var urlObj = aws4.sign(opts, {accessKeyId: '<access key>', secretAccessKey: '<aws secret>'});
const client = http2.connect('https://transcribestreaming.<region>.amazonaws.com');
client.on('error', function(err){
console.error("error in request ",err);
});
const req = client.request({
':method': 'POST',
':path': '/stream-transcription',
'authorization': urlObj.headers.Authorization,
'content-type': 'application/json',
'x-amz-content-sha256': 'STREAMING-AWS4-HMAC-SHA256-EVENTS',
'x-amz-target': 'com.amazonaws.transcribe.Transcribe.StartStreamTranscription',
'x-amz-date': urlObj['headers']['X-Amz-Date'],
'x-amz-transcribe-language-code': 'en-US',
'x-amz-transcribe-media-encoding': 'pcm',
'x-amz-transcribe-sample-rate': 44100
});
req.on('response', (headers, flags) => {
for (const name in headers) {
console.log(`${name}: ${headers[name]}`);
}
});
let data = '';
req.on('data', (chunk) => { data += chunk; });
req.on('end', () => {
console.log(`\n${data}`);
client.close();
});
req.end();
谁能指出我在这里缺少什么。 我也找不到任何使用 HTTP/2 实现它的示例。
更新:将 Content-type 更改为 application/json 返回响应状态为 200,但有以下异常:
`{"Output":{"__type":"com.amazon.coral.service#SerializationException"},"Version":"1.0"}`
更新(2019 年 4 月 22 日):
req.setEncoding('utf8');
req.write(audioBlob);
var audioBlob = new Buffer(JSON.stringify({
"AudioStream": {
"AudioEvent": {
"AudioChunk": audioBufferData
}
}
在结束请求之前,我通过序列化添加了一个“audioblod”作为有效负载。 我的“audioBufferData”是来自浏览器的原始 PCM 音频格式。 我从文档中看到有效负载必须编码为“事件流编码”,但无法弄清楚如何实现它。
因此,如果没有此事件流编码,目前我会收到以下异常,并具有 200 响应状态。
{"Output":{"__type":"com.amazon.coral.service#UnknownOperationException"},"Version":"1.0"}
我联系了 AWS 支持,他们似乎无法获得与 NodeJS 一起使用的 HTTP/2 实现。
然而,他们现在提供了一种通过 websockets 直接与 Transcribe 流 API 交互的方法(博客文章在这里)
如果这适合您的用例,我强烈建议您查看新的示例存储库: https : //github.com/aws-samples/amazon-transcribe-websocket-static
如果您在面向公众的页面中使用它,我建议您使用未经身份验证的 Cognito 会话来处理凭据检索。 我已经在一个生产应用程序中使用了这个,所以请随时在任何其他问题中标记我。
这并没有直接回答问题,但我认为作为答案而不是评论发布已经足够有用了。
AWS 刚刚宣布了对 Amazon Transcribe 的 WebSocket 支持。 这里是文档,这里是客户端示例应用程序。 最大的区别,也是我认为与 WebSockets 集成更直接的区别在于,您不需要像 http/2 那样对每个音频块进行签名。
使用预签名 URL 授权和启动连接的相关代码位于lib/aws-signature-v4.js
exports.createPresignedURL = function(method, host, path, service, payload, options) {
options = options || {};
options.key = options.key || process.env.AWS_ACCESS_KEY_ID;
options.secret = options.secret || process.env.AWS_SECRET_ACCESS_KEY;
options.protocol = options.protocol || 'https';
options.headers = options.headers || {};
options.timestamp = options.timestamp || Date.now();
options.region = options.region || process.env.AWS_REGION || 'us-east-1';
options.expires = options.expires || 86400; // 24 hours
options.headers = options.headers || {};
// host is required
options.headers.Host = host;
var query = options.query ? querystring.parse(options.query) : {};
query['X-Amz-Algorithm'] = 'AWS4-HMAC-SHA256';
query['X-Amz-Credential'] = options.key + '/' + exports.createCredentialScope(options.timestamp, options.region, service);
query['X-Amz-Date'] = toTime(options.timestamp);
query['X-Amz-Expires'] = options.expires;
query['X-Amz-SignedHeaders'] = exports.createSignedHeaders(options.headers);
var canonicalRequest = exports.createCanonicalRequest(method, path, query, options.headers, payload);
var stringToSign = exports.createStringToSign(options.timestamp, options.region, service, canonicalRequest);
var signature = exports.createSignature(options.secret, options.timestamp, options.region, service, stringToSign);
query['X-Amz-Signature'] = signature;
return options.protocol + '://' + host + path + '?' + querystring.stringify(query);
};
我们在lib/main.js
调用它:
function createPresignedUrl() {
let endpoint = "transcribestreaming." + region + ".amazonaws.com:8443";
// get a preauthenticated URL that we can use to establish our WebSocket
return v4.createPresignedURL(
'GET',
endpoint,
'/stream-transcription-websocket',
'transcribe',
crypto.createHash('sha256').update('', 'utf8').digest('hex'), {
'key': $('#access_id').val(),
'secret': $('#secret_key').val(),
'protocol': 'wss',
'expires': 15,
'region': region,
'query': "language-code=" + languageCode + "&media-encoding=pcm&sample-rate=" + sampleRate
}
);
}
为了以我们需要的事件流消息格式打包东西,我们将 PCM 编码的音频包装在一个 JSON 信封中并将其转换为二进制
function convertAudioToBinaryMessage(audioChunk) {
let raw = mic.toRaw(audioChunk);
if (raw == null)
return;
// downsample and convert the raw audio bytes to PCM
let downsampledBuffer = audioUtils.downsampleBuffer(raw, sampleRate);
let pcmEncodedBuffer = audioUtils.pcmEncode(downsampledBuffer);
// add the right JSON headers and structure to the message
let audioEventMessage = getAudioEventMessage(Buffer.from(pcmEncodedBuffer));
//convert the JSON object + headers into a binary event stream message
let binary = eventStreamMarshaller.marshall(audioEventMessage);
return binary;
}
function getAudioEventMessage(buffer) {
// wrap the audio data in a JSON envelope
return {
headers: {
':message-type': {
type: 'string',
value: 'event'
},
':event-type': {
type: 'string',
value: 'AudioEvent'
}
},
body: buffer
};
}
我有一个类似的要求,即在节点 js 中使用 AWS transcribe 服务和他们的 WebSocket API。 鉴于目前官方包中还没有对此提供支持,我已经按照github 上提供的这个实现编写了一个包。 它称为 AWS-transcribe,可在此处找到。 我希望这有帮助。
它提供了一个围绕 WebSocket 的流接口,可以像下面的例子一样使用
import { AwsTranscribe, StreamingClient } from "aws-transcribe"
const client = new AwsTranscribe({
// if these aren't provided, they will be taken from the environment
accessKeyId: "ACCESS KEY HERE",
secretAccessKey: "SECRET KEY HERE",
})
const transcribeStream = client
.createStreamingClient({
region: "eu-west-1",
sampleRate,
languageCode: "en-US",
})
// enums for returning the event names which the stream will emit
.on(StreamingClient.EVENTS.OPEN, () => console.log(`transcribe connection opened`))
.on(StreamingClient.EVENTS.ERROR, console.error)
.on(StreamingClient.EVENTS.CLOSE, () => console.log(`transcribe connection closed`))
.on(StreamingClient.EVENTS.DATA, (data) => {
const results = data.Transcript.Results
if (!results || results.length === 0) {
return
}
const result = results[0]
const final = !result.IsPartial
const prefix = final ? "recognized" : "recognizing"
const text = result.Alternatives[0].Transcript
console.log(`${prefix} text: ${text}`)
})
someStream.pipe(transcribeStream)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.