目前,我正在尝试将 Kinesis Vides Stream GetMedia API 的响应转换为音频文件,但没有成功。根据 AWS 文档, - GetMedia 请求 的结果?建议使用Kinesis Video Stream Parser Library。但我想使用 js/ts 实现。是否可以仅使用 js/ts 将此流转换为音频文件?
谢谢您的帮助。
我终于弄清楚如何将 Kinesis Video Stream 转换为音频文件。这就是我使用 Node.js 和适用于 JavaScript 的 AWS 开发工具包完成此操作的方法:
>> mkdir aws-sdk-js && cd aws-sdk-js
>> npm init
选择默认的npm选项后,打开新生成的
package.json
文件并添加以下内容:
"dependencies": {
"aws-sdk": "^2.1587.0”,
“ebml”: “^3.0.0”
}
现在安装 SDK 模块:
>> npm install
>> touch index.js
然后在
index.js
文件中,复制并粘贴以下内容:
const AWS = require("aws-sdk");
const ebml = require("ebml");
const fs = require("fs");
const region = "<your AWS region>";
const streamInfo = {
streamName: "<your Kinesis Video stream name>",
startFragmentNumber: "<your Kinesis Video fragment number>",
//streamArn: "<your Kinesis Video stream ARN>"
};
// Suppress AWS SDK version warning message
process.env["AWS_SDK_JS_SUPPRESS_MAINTENANCE_MODE_MESSAGE"] = 1;
async function main() {
//const streamName = streamInfo.streamArn.split("stream/")[1].split("/")[0];
const streamName = streamInfo.streamName;
const fragmentNumber = streamInfo.startFragmentNumber;
const raw = await getMedia(streamName, fragmentNumber);
const wav = Converter.createWav(raw, 8000);
fs.writeFile("audio.wav", Buffer.from(wav.buffer), (err) => {
if (err) throw err;
console.log("Audio file saved.");
});
return {};
};
async function getMedia(streamName, fragmentNumber) {
// Obtain the Kinesis Video endpoint URL
const kinesisvideo = new AWS.KinesisVideo({region: region});
var params = {
APIName: "GET_MEDIA",
StreamName: streamName
};
const end = await kinesisvideo.getDataEndpoint(params).promise();
// Get the raw audio data
const kinesisvideomedia = new AWS.KinesisVideoMedia({endpoint: end.DataEndpoint, region:region});
var params = {
StartSelector: {
StartSelectorType: "FRAGMENT_NUMBER",
AfterFragmentNumber: fragmentNumber,
},
StreamName: streamName
};
const data = await kinesisvideomedia.getMedia(params).promise();
const decoder = new ebml.Decoder();
let chunks = [];
decoder.on("data", chunk => {
if(chunk[1].name == "SimpleBlock"){
chunks.push(chunk[1].data);
}
});
decoder.write(data["Payload"]);
// Join the audio chunks
const margin = 4;
var sumLength = 0;
chunks.forEach( chunk => {
sumLength += chunk.byteLength - margin;
})
var sample = new Uint8Array(sumLength);
var pos = 0;
chunks.forEach(chunk => {
let tmp = new Uint8Array(chunk.byteLength - margin);
for(var e = 0; e < chunk.byteLength - margin; e++){
tmp[e] = chunk[e + margin];
}
sample.set(tmp, pos);
pos += chunk.byteLength - margin;
})
return sample.buffer;
}
class Converter {
// Convert the raw audio into wav format
static createWav(samples, sampleRate) {
const len = samples.byteLength;
const view = new DataView(new ArrayBuffer(44 + len));
this._writeString(view, 0, "RIFF");
view.setUint32(4, 32 + len, true);
this._writeString(view, 8, "WAVE");
this._writeString(view, 12, "fmt ");
view.setUint32(16, 16, true);
view.setUint16(20, 1, true); // リニアPCM
view.setUint16(22, 1, true); // モノラル
view.setUint32(24, sampleRate, true);
view.setUint32(28, sampleRate * 2, true);
view.setUint16(32, 2, true);
view.setUint16(34, 16, true);
this._writeString(view, 36, "data");
view.setUint32(40, len, true);
let offset = 44;
const srcView = new DataView(samples);
for (var i = 0; i < len; i+=4, offset+=4) {
view.setInt32(offset, srcView.getUint32(i));
}
return view;
}
static _writeString(view, offset, string) {
for (var i = 0; i < string.length; i++) {
view.setUint8(offset + i, string.charCodeAt(i));
}
}
}
main();
运行脚本:
>> node index.js
这应该输出
audio.wav
文件!