API de streaming¶
O protocolo de streaming da API de STT é baseado na biblioteca socket.io, com as seguintes mensagens:
Mensagens do Servidor¶
broad¶
O servidor envia uma mensagem. Usado para debug.
speechData¶
O servidor envia os dados da transcrição, seguindo o seguinte formato:
{
"results": [
{
"text": "a abertura de novos grupos foi suspensa",
"score": -21.840528
},
{
"text": "a abertura de novos grupos foi suspensa",
"score": -31.796457
},
{
"text": "a a abertura de novos grupos foi suspensa",
"score": -39.00835
}
]
}
Note que a partir de cada mensagem de cliente de startStream (que será definido à seguir), iniciamos uma sessão de transcrição e todo o conteúdo da transcrição até o momento é retornado nas mensagems de speechData, até que a sessão seja finalizada com uma mensagem de endStream.
Mensagens dos Client¶
join¶
Iniciar uma conexão com o servidor.
messages¶
O cliente enviar uma mensagem. Usado para debug.
startStream¶
Inicia uma sessão de streaming.
endStream¶
Finaliza a sessão de streaming atual.
setModel¶
Define um modelo para a sessão de streaming atual.
binary¶
Envia um frame em WAV.
'use strict'
let endpoint = "wss://staging-api.alabiabot.com/";
const socket = io.connect(endpoint, {
transports: ['websocket']
});
//================= CONFIG =================
// Stream Audio
let bufferSize = 2048 * 8,
AudioContext,
context,
processor,
input,
globalStream,
model = "default";
//vars
let isStreaming = false;
//audioStream constraints
const constraints = {
audio: true,
video: false
};
//================= RECORDING =================
function startRecording() {
navigator.mediaDevices.getUserMedia(constraints)
.then(function (stream) {
console.log("recording...");
socket.emit('startStream', '');
socket.emit('setModel', model);
isStreaming = true;
AudioContext = window.AudioContext || window.webkitAudioContext;
context = new AudioContext({
latencyHint: 'interactive',
sampleRate: 16000,
});
processor = context.createScriptProcessor(bufferSize, 1, 1);
processor.onaudioprocess = function (event) {
let left16 = toIntArray(event.inputBuffer.getChannelData(0));
socket.emit('binary', left16);
};
processor.connect(context.destination);
context.resume();
globalStream = stream;
input = context.createMediaStreamSource(stream);
input.connect(processor);
});
}
function stopRecording() {
console.log("stop recording");
isStreaming = false;
socket.emit('endStream', '');
let track = globalStream.getTracks()[0];
track.stop();
input.disconnect(processor);
processor.disconnect(context.destination);
context.close().then(function () {
input = null;
processor = null;
context = null;
AudioContext = null;
startButton.disabled = false;
});
}
//================= SOCKET IO =================
socket.on('connect', function (data) {
socket.emit('join', 'Server Connected to Client');
});
socket.on('broad', function (data) {
console.log(data);
});
socket.on('speechData', function (data) {
console.log(data);
displayResult(addTimeSettingsFinal(data))
});
function addTimeSettingsFinal(speechData) {
return speechData.results[0].text;
}
window.onbeforeunload = function () {
if (isStreaming) { socket.emit('endStream', ''); }
};
function toIntArray(buffer) {
let array = new Int16Array(buffer.length);
for (let i = 0; i < buffer.length; i++) {
array[i] = Math.min(1, buffer[i]) * 0x7FFF;
}
return array.buffer;
}
Teste ao Vivo¶
...