Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@speechly/browser-client

Package Overview
Dependencies
Maintainers
6
Versions
79
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@speechly/browser-client - npm Package Compare versions

Comparing version 1.0.12 to 1.0.13

2

package.json
{
"name": "@speechly/browser-client",
"version": "1.0.12",
"version": "1.0.13",
"description": "Browser client for Speechly API",

@@ -5,0 +5,0 @@ "private": false,

@@ -1,2 +0,2 @@

declare const _default: "\n// Indices for the Control SAB.\nconst CONTROL = {\n WRITE_INDEX: 0,\n FRAMES_AVAILABLE: 1,\n}\nlet ws\nconst state = {\n isContextStarted: false,\n isStartContextConfirmed: false,\n shouldResendLastFramesSent: false,\n sourceSampleRate: undefined,\n targetSampleRate: undefined,\n resampleRatio: 1,\n buffer: new Float32Array(0),\n lastFramesSent: new Int16Array(0), // to re-send after switch context\n filter: undefined,\n controlSAB: undefined,\n dataSAB: undefined,\n}\n\nasync function initializeWebsocket(url, protocol) {\n ws = new WebSocket(url, protocol)\n\n return new Promise((resolve, reject) => {\n const errhandler = () => {\n ws.removeEventListener('close', errhandler)\n ws.removeEventListener('error', errhandler)\n ws.removeEventListener('open', openhandler)\n\n reject(Error('Connection failed'))\n }\n\n const openhandler = () => {\n ws.removeEventListener('close', errhandler)\n ws.removeEventListener('error', errhandler)\n ws.removeEventListener('open', openhandler)\n\n resolve(ws)\n }\n\n ws.addEventListener('close', errhandler)\n ws.addEventListener('error', errhandler)\n ws.addEventListener('open', openhandler)\n })\n}\n\nfunction closeWebsocket(code, message) {\n if (ws === undefined) {\n throw Error('Websocket is not open')\n }\n\n ws.removeEventListener('message', onWebsocketMessage)\n ws.removeEventListener('error', onWebsocketError)\n ws.removeEventListener('close', onWebsocketClose)\n\n ws.close(code, message)\n}\n\nfunction onWebsocketClose(event) {\n ws = undefined\n}\n\nfunction onWebsocketError(_event) {\n onWebsocketClose(1000, 'Client disconnecting due to an error')\n}\n\nfunction onWebsocketMessage(event) {\n let response\n try {\n response = JSON.parse(event.data)\n } catch (e) {\n console.error('[SpeechlyClient] Error parsing response from the server:', e)\n return\n }\n\n if (response.type === 'started') {\n state.isStartContextConfirmed = true\n if (state.shouldResendLastFramesSent) {\n if (state.lastFramesSent.length > 0) {\n if (ws !== undefined) {\n ws.send(state.lastFramesSent)\n }\n state.lastFramesSent = new Int16Array(0)\n }\n state.shouldResendLastFramesSent = false\n }\n }\n\n self.postMessage(response)\n}\n\nfunction float32ToInt16(buffer) {\n const buf = new Int16Array(buffer.length)\n\n for (let l = 0; l < buffer.length; l++) {\n buf[l] = buffer[l] * (buffer[l] < 0 ? 0x8000 : 0x7fff)\n }\n\n return buf\n}\n\nself.onmessage = function(e) {\n switch (e.data.type) {\n case 'INIT':\n if (ws === undefined) {\n initializeWebsocket(e.data.apiUrl, e.data.authToken).then(function() {\n self.postMessage({\n type: 'WEBSOCKET_OPEN',\n })\n ws.addEventListener('message', onWebsocketMessage)\n ws.addEventListener('error', onWebsocketError)\n ws.addEventListener('close', onWebsocketClose)\n })\n\n state.targetSampleRate = e.data.targetSampleRate\n }\n break\n case 'SET_SOURSE_SAMPLE_RATE':\n state.sourceSampleRate = e.data.sourceSampleRate\n state.resampleRatio = e.data.sourceSampleRate / state.targetSampleRate\n if (state.resampleRatio > 1) {\n state.filter = generateFilter(e.data.sourceSampleRate, state.targetSampleRate, 127)\n }\n self.postMessage({\n type: 'SOURSE_SAMPLE_RATE_SET_SUCCESS',\n })\n\n if (isNaN(state.resampleRatio)) {\n throw Error('resampleRatio is NaN')\n }\n break\n case 'SET_SHARED_ARRAY_BUFFERS':\n state.controlSAB = new Int32Array(e.data.controlSAB)\n state.dataSAB = new Float32Array(e.data.dataSAB)\n setInterval(sendAudioFromSAB, 4)\n break\n case 'CLOSE':\n if (ws !== undefined) {\n closeWebsocket(e.data.code, e.data.message)\n }\n break\n case 'START_CONTEXT':\n if (ws === undefined) {\n throw Error('Cant start context: websocket is undefined')\n }\n if (state.isContextStarted) {\n console.log('Cant start context: it has been already started')\n break\n }\n\n state.isContextStarted = true\n state.isStartContextConfirmed = false\n\n const appId = e.data.appId\n if (appId !== undefined) {\n ws.send(JSON.stringify({ event: 'start', appId }))\n } else {\n ws.send(JSON.stringify({ event: 'start' }))\n }\n break\n case 'SWITCH_CONTEXT':\n const newAppId = e.data.appId\n if (ws !== undefined && state.isContextStarted && newAppId !== undefined) {\n state.isStartContextConfirmed = false\n const StopEventJSON = JSON.stringify({ event: 'stop' })\n ws.send(StopEventJSON)\n state.shouldResendLastFramesSent = true\n ws.send(JSON.stringify({ event: 'start', appId: newAppId }))\n }\n break\n case 'STOP_CONTEXT':\n if (ws !== undefined && state.isContextStarted) {\n state.isContextStarted = false\n state.isStartContextConfirmed = false\n const StopEventJSON = JSON.stringify({ event: 'stop' })\n ws.send(StopEventJSON)\n }\n break\n case 'AUDIO':\n if (ws !== undefined && state.isContextStarted) {\n if (e.data.payload.length > 0) {\n if (state.resampleRatio > 1) {\n // Downsampling\n ws.send(downsample(e.data.payload))\n } else {\n ws.send(float32ToInt16(e.data.payload))\n }\n }\n }\n break\n default:\n console.log('WORKER', e)\n }\n}\n\nlet lastTime = Date.now()\n\nfunction sendAudioFromSAB() {\n if (state.isStartContextConfirmed && CONTROL.FRAMES_AVAILABLE > 0) {\n const data = state.dataSAB.subarray(0, state.controlSAB[CONTROL.FRAMES_AVAILABLE])\n state.controlSAB[CONTROL.FRAMES_AVAILABLE] = 0\n state.controlSAB[CONTROL.WRITE_INDEX] = 0\n if (data.length > 0) {\n let frames\n if (state.resampleRatio > 1) {\n frames = downsample(data)\n } else {\n frames = float32ToInt16(data)\n }\n ws.send(frames)\n\n // 16000 per second, 1000 in 100 ms\n // save last 250 ms\n if (state.lastFramesSent.length > 1024 * 4) {\n state.lastFramesSent = frames\n } else {\n let concat = new Int16Array(state.lastFramesSent.length + frames.length)\n concat.set(state.lastFramesSent)\n concat.set(frames, state.lastFramesSent.length)\n state.lastFramesSent = concat\n }\n }\n } else {\n if (!state.isContextStarted) {\n state.controlSAB[CONTROL.FRAMES_AVAILABLE] = 0\n state.controlSAB[CONTROL.WRITE_INDEX] = 0\n }\n }\n}\n\nfunction downsample(input) {\n const inputBuffer = new Float32Array(state.buffer.length + input.length)\n inputBuffer.set(state.buffer, 0)\n inputBuffer.set(input, state.buffer.length)\n\n const outputLength = Math.ceil((inputBuffer.length - state.filter.length) / state.resampleRatio)\n const outputBuffer = new Int16Array(outputLength)\n\n for (let i = 0; i < outputLength; i++) {\n const offset = Math.round(state.resampleRatio * i)\n let val = 0.0\n\n for (let j = 0; j < state.filter.length; j++) {\n val += inputBuffer[offset + j] * state.filter[j]\n }\n\n outputBuffer[i] = val * (val < 0 ? 0x8000 : 0x7fff)\n }\n\n const remainingOffset = Math.round(state.resampleRatio * outputLength)\n if (remainingOffset < inputBuffer.length) {\n state.buffer = inputBuffer.subarray(remainingOffset)\n } else {\n state.buffer = emptyBuffer\n }\n\n return outputBuffer\n}\n\nfunction generateFilter(sourceSampleRate, targetSampleRate, length) {\n if (length % 2 === 0) {\n throw Error('Filter length must be odd')\n }\n\n const cutoff = targetSampleRate / 2\n const filter = new Float32Array(length)\n let sum = 0\n\n for (let i = 0; i < length; i++) {\n const x = sinc(((2 * cutoff) / sourceSampleRate) * (i - (length - 1) / 2))\n\n sum += x\n filter[i] = x\n }\n\n for (let i = 0; i < length; i++) {\n filter[i] = filter[i] / sum\n }\n\n return filter\n}\n\nfunction sinc(x) {\n if (x === 0.0) {\n return 1.0\n }\n\n const piX = Math.PI * x\n return Math.sin(piX) / piX\n}\n\n";
declare const _default: "\n// Indices for the Control SAB.\nconst CONTROL = {\n WRITE_INDEX: 0,\n FRAMES_AVAILABLE: 1,\n}\nlet ws\nlet url\nlet token\nconst state = {\n isContextStarted: false,\n isStartContextConfirmed: false,\n shouldResendLastFramesSent: false,\n sourceSampleRate: undefined,\n targetSampleRate: undefined,\n resampleRatio: 1,\n buffer: new Float32Array(0),\n lastFramesSent: new Int16Array(0), // to re-send after switch context\n filter: undefined,\n controlSAB: undefined,\n dataSAB: undefined,\n}\n\nasync function initializeWebsocket() {\n ws = new WebSocket(url, token)\n\n return new Promise((resolve, reject) => {\n const errhandler = () => {\n ws.removeEventListener('close', errhandler)\n ws.removeEventListener('error', errhandler)\n ws.removeEventListener('open', openhandler)\n\n reject(Error('Connection failed'))\n }\n\n const openhandler = () => {\n ws.removeEventListener('close', errhandler)\n ws.removeEventListener('error', errhandler)\n ws.removeEventListener('open', openhandler)\n\n resolve(ws)\n }\n\n ws.addEventListener('close', errhandler)\n ws.addEventListener('error', errhandler)\n ws.addEventListener('open', openhandler)\n })\n}\n\nfunction connect(timeout = 1000) {\n setTimeout(function() {\n initializeWebsocket().then(function() {\n console.log('connect')\n self.postMessage({\n type: 'WEBSOCKET_OPEN',\n })\n ws.addEventListener('message', onWebsocketMessage)\n ws.addEventListener('error', onWebsocketError)\n ws.addEventListener('close', onWebsocketClose)\n }).catch((error) => {\n console.log(error)\n connect(1000)\n })\n }, timeout)\n}\n\nfunction closeWebsocket(code, message) {\n if (ws === undefined) {\n throw Error('Websocket is not open')\n }\n\n ws.removeEventListener('message', onWebsocketMessage)\n ws.removeEventListener('error', onWebsocketError)\n ws.removeEventListener('close', onWebsocketClose)\n\n ws.close(code, message)\n}\n\nfunction onWebsocketClose(event) {\n connect(0)\n}\n\nfunction onWebsocketError(_event) {\n onWebsocketClose(1000, 'Client disconnecting due to an error')\n}\n\nfunction onWebsocketMessage(event) {\n let response\n try {\n response = JSON.parse(event.data)\n } catch (e) {\n console.error('[SpeechlyClient] Error parsing response from the server:', e)\n return\n }\n\n if (response.type === 'started') {\n state.isStartContextConfirmed = true\n if (state.shouldResendLastFramesSent) {\n if (state.lastFramesSent.length > 0) {\n if (ws !== undefined) {\n ws.send(state.lastFramesSent)\n }\n state.lastFramesSent = new Int16Array(0)\n }\n state.shouldResendLastFramesSent = false\n }\n }\n\n self.postMessage(response)\n}\n\nfunction float32ToInt16(buffer) {\n const buf = new Int16Array(buffer.length)\n\n for (let l = 0; l < buffer.length; l++) {\n buf[l] = buffer[l] * (buffer[l] < 0 ? 0x8000 : 0x7fff)\n }\n\n return buf\n}\n\nself.onmessage = function(e) {\n switch (e.data.type) {\n case 'INIT':\n if (ws === undefined) {\n url = e.data.apiUrl\n token = e.data.authToken\n connect(0)\n state.targetSampleRate = e.data.targetSampleRate\n }\n break\n case 'SET_SOURSE_SAMPLE_RATE':\n state.sourceSampleRate = e.data.sourceSampleRate\n state.resampleRatio = e.data.sourceSampleRate / state.targetSampleRate\n if (state.resampleRatio > 1) {\n state.filter = generateFilter(e.data.sourceSampleRate, state.targetSampleRate, 127)\n }\n self.postMessage({\n type: 'SOURSE_SAMPLE_RATE_SET_SUCCESS',\n })\n\n if (isNaN(state.resampleRatio)) {\n throw Error('resampleRatio is NaN')\n }\n break\n case 'SET_SHARED_ARRAY_BUFFERS':\n state.controlSAB = new Int32Array(e.data.controlSAB)\n state.dataSAB = new Float32Array(e.data.dataSAB)\n setInterval(sendAudioFromSAB, 4)\n break\n case 'CLOSE':\n if (ws !== undefined) {\n closeWebsocket(e.data.code, e.data.message)\n }\n break\n case 'START_CONTEXT':\n if (ws === undefined) {\n throw Error('Cant start context: websocket is undefined')\n }\n if (state.isContextStarted) {\n console.log('Cant start context: it has been already started')\n break\n }\n\n state.isContextStarted = true\n state.isStartContextConfirmed = false\n\n const appId = e.data.appId\n if (appId !== undefined) {\n ws.send(JSON.stringify({ event: 'start', appId }))\n } else {\n ws.send(JSON.stringify({ event: 'start' }))\n }\n break\n case 'SWITCH_CONTEXT':\n const newAppId = e.data.appId\n if (ws !== undefined && state.isContextStarted && newAppId !== undefined) {\n state.isStartContextConfirmed = false\n const StopEventJSON = JSON.stringify({ event: 'stop' })\n ws.send(StopEventJSON)\n state.shouldResendLastFramesSent = true\n ws.send(JSON.stringify({ event: 'start', appId: newAppId }))\n }\n break\n case 'STOP_CONTEXT':\n if (ws !== undefined && state.isContextStarted) {\n state.isContextStarted = false\n state.isStartContextConfirmed = false\n const StopEventJSON = JSON.stringify({ event: 'stop' })\n ws.send(StopEventJSON)\n }\n break\n case 'AUDIO':\n if (ws !== undefined && state.isContextStarted) {\n if (e.data.payload.length > 0) {\n if (state.resampleRatio > 1) {\n // Downsampling\n ws.send(downsample(e.data.payload))\n } else {\n ws.send(float32ToInt16(e.data.payload))\n }\n }\n }\n break\n default:\n console.log('WORKER', e)\n }\n}\n\nlet lastTime = Date.now()\n\nfunction sendAudioFromSAB() {\n if (state.isStartContextConfirmed && CONTROL.FRAMES_AVAILABLE > 0) {\n const data = state.dataSAB.subarray(0, state.controlSAB[CONTROL.FRAMES_AVAILABLE])\n state.controlSAB[CONTROL.FRAMES_AVAILABLE] = 0\n state.controlSAB[CONTROL.WRITE_INDEX] = 0\n if (data.length > 0) {\n let frames\n if (state.resampleRatio > 1) {\n frames = downsample(data)\n } else {\n frames = float32ToInt16(data)\n }\n ws.send(frames)\n\n // 16000 per second, 1000 in 100 ms\n // save last 250 ms\n if (state.lastFramesSent.length > 1024 * 4) {\n state.lastFramesSent = frames\n } else {\n let concat = new Int16Array(state.lastFramesSent.length + frames.length)\n concat.set(state.lastFramesSent)\n concat.set(frames, state.lastFramesSent.length)\n state.lastFramesSent = concat\n }\n }\n } else {\n if (!state.isContextStarted) {\n state.controlSAB[CONTROL.FRAMES_AVAILABLE] = 0\n state.controlSAB[CONTROL.WRITE_INDEX] = 0\n }\n }\n}\n\nfunction downsample(input) {\n const inputBuffer = new Float32Array(state.buffer.length + input.length)\n inputBuffer.set(state.buffer, 0)\n inputBuffer.set(input, state.buffer.length)\n\n const outputLength = Math.ceil((inputBuffer.length - state.filter.length) / state.resampleRatio)\n const outputBuffer = new Int16Array(outputLength)\n\n for (let i = 0; i < outputLength; i++) {\n const offset = Math.round(state.resampleRatio * i)\n let val = 0.0\n\n for (let j = 0; j < state.filter.length; j++) {\n val += inputBuffer[offset + j] * state.filter[j]\n }\n\n outputBuffer[i] = val * (val < 0 ? 0x8000 : 0x7fff)\n }\n\n const remainingOffset = Math.round(state.resampleRatio * outputLength)\n if (remainingOffset < inputBuffer.length) {\n state.buffer = inputBuffer.subarray(remainingOffset)\n } else {\n state.buffer = emptyBuffer\n }\n\n return outputBuffer\n}\n\nfunction generateFilter(sourceSampleRate, targetSampleRate, length) {\n if (length % 2 === 0) {\n throw Error('Filter length must be odd')\n }\n\n const cutoff = targetSampleRate / 2\n const filter = new Float32Array(length)\n let sum = 0\n\n for (let i = 0; i < length; i++) {\n const x = sinc(((2 * cutoff) / sourceSampleRate) * (i - (length - 1) / 2))\n\n sum += x\n filter[i] = x\n }\n\n for (let i = 0; i < length; i++) {\n filter[i] = filter[i] / sum\n }\n\n return filter\n}\n\nfunction sinc(x) {\n if (x === 0.0) {\n return 1.0\n }\n\n const piX = Math.PI * x\n return Math.sin(piX) / piX\n}\n\n";
export default _default;

@@ -10,2 +10,4 @@ "use strict";

let ws
let url
let token
const state = {

@@ -25,4 +27,4 @@ isContextStarted: false,

async function initializeWebsocket(url, protocol) {
ws = new WebSocket(url, protocol)
async function initializeWebsocket() {
ws = new WebSocket(url, token)

@@ -52,2 +54,19 @@ return new Promise((resolve, reject) => {

function connect(timeout = 1000) {
setTimeout(function() {
initializeWebsocket().then(function() {
console.log('connect')
self.postMessage({
type: 'WEBSOCKET_OPEN',
})
ws.addEventListener('message', onWebsocketMessage)
ws.addEventListener('error', onWebsocketError)
ws.addEventListener('close', onWebsocketClose)
}).catch((error) => {
console.log(error)
connect(1000)
})
}, timeout)
}
function closeWebsocket(code, message) {

@@ -66,3 +85,3 @@ if (ws === undefined) {

function onWebsocketClose(event) {
ws = undefined
connect(0)
}

@@ -113,11 +132,5 @@

if (ws === undefined) {
initializeWebsocket(e.data.apiUrl, e.data.authToken).then(function() {
self.postMessage({
type: 'WEBSOCKET_OPEN',
})
ws.addEventListener('message', onWebsocketMessage)
ws.addEventListener('error', onWebsocketError)
ws.addEventListener('close', onWebsocketClose)
})
url = e.data.apiUrl
token = e.data.authToken
connect(0)
state.targetSampleRate = e.data.targetSampleRate

@@ -124,0 +137,0 @@ }

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc