Skip to content
This repository was archived by the owner on May 6, 2022. It is now read-only.

Commit d50a959

Browse files
committed
feat(socket): allow full customization of socket servers
BREAKING CHANGE: this changes the API for asrSocketServer, googleASRSocketServer, and startStream() so that more WebSocket options can be passed as arguments. To migrate, change asrSocketServer(server) to asrSocketServer({ server }). Change googleASRSocketServer(server) to googleASRSocketServer({ server }). Change startStream(() => isPlaying) to startStream({ isPlaying: () => isPlaying }).
1 parent 47dbb86 commit d50a959

File tree

5 files changed

+75
-57
lines changed

5 files changed

+75
-57
lines changed

README.md

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ If you'd prefer to use Google ASR, follow these [instructions for setting up Goo
5252

5353
**spokestackMiddleware**(): function
5454

55-
_Defined in [server/expressMiddleware.ts:37](https://github.com/spokestack/node-spokestack/blob/7555411/src/server/expressMiddleware.ts#L37)_
55+
_Defined in [server/expressMiddleware.ts:37](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/server/expressMiddleware.ts#L37)_
5656

5757
Express middleware for adding a proxy to the Spokestack GraphQL API.
5858
A proxy is necessary to avoid exposing your Spokestack token secret on the client.
@@ -87,9 +87,9 @@ const graphQLFetcher = (graphQLParams) =>
8787

8888
### asrSocketServer
8989

90-
**asrSocketServer**(`server`: Server, `asrConfig?`: Omit<SpokestackASRConfig, \"sampleRate\"\>): void
90+
**asrSocketServer**(`serverConfig`: ServerOptions, `asrConfig?`: Omit<SpokestackASRConfig, \"sampleRate\"\>): void
9191

92-
_Defined in [server/socketServer.ts:25](https://github.com/spokestack/node-spokestack/blob/7555411/src/server/socketServer.ts#L25)_
92+
_Defined in [server/socketServer.ts:25](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/server/socketServer.ts#L25)_
9393

9494
Adds a web socket server to the given HTTP server
9595
to stream ASR using Spokestack ASR.
@@ -100,28 +100,28 @@ import { createServer } from 'http'
100100
const port = parseInt(process.env.PORT || '3000', 10)
101101
const server = createServer() // or express()
102102
// Attach the websocket server to the HTTP server
103-
asrSocketServer(server)
103+
asrSocketServer({ server })
104104
server.listen(port, () => {
105105
console.log(`Listening at http://localhost:${port}`)
106106
})
107107
```
108108

109109
#### Parameters:
110110

111-
| Name | Type | Default value |
112-
| ----------- | ------------------------------------------ | ------------- |
113-
| `server` | Server | - |
114-
| `asrConfig` | Omit<SpokestackASRConfig, \"sampleRate\"\> | {} |
111+
| Name | Type | Default value |
112+
| -------------- | ------------------------------------------ | ------------- |
113+
| `serverConfig` | ServerOptions | - |
114+
| `asrConfig` | Omit<SpokestackASRConfig, \"sampleRate\"\> | {} |
115115

116116
**Returns:** void
117117

118118
---
119119

120120
### googleASRSocketServer
121121

122-
**googleASRSocketServer**(`server`: Server): void
122+
**googleASRSocketServer**(`serverConfig`: ServerOptions): void
123123

124-
_Defined in [server/socketServer.ts:110](https://github.com/spokestack/node-spokestack/blob/7555411/src/server/socketServer.ts#L110)_
124+
_Defined in [server/socketServer.ts:110](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/server/socketServer.ts#L110)_
125125

126126
Adds a web socket server to the given HTTP server
127127
to stream ASR using Google Speech.
@@ -132,25 +132,25 @@ import { createServer } from 'http'
132132
const port = parseInt(process.env.PORT || '3000', 10)
133133
const server = createServer() // or express()
134134
// Attach the websocket server to the HTTP server
135-
googleASRSocketServer(server)
135+
googleASRSocketServer({ server })
136136
server.listen(port, () => {
137137
console.log(`Listening at http://localhost:${port}`)
138138
})
139139
```
140140

141141
#### Parameters:
142142

143-
| Name | Type |
144-
| -------- | ------ |
145-
| `server` | Server |
143+
| Name | Type |
144+
| -------------- | ------------- |
145+
| `serverConfig` | ServerOptions |
146146

147147
**Returns:** void
148148

149149
### asr
150150

151151
**asr**(`content`: string \| Uint8Array, `sampleRate`: number): Promise<string \| null\>
152152

153-
_Defined in [server/asr.ts:43](https://github.com/spokestack/node-spokestack/blob/7555411/src/server/asr.ts#L43)_
153+
_Defined in [server/asr.ts:43](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/server/asr.ts#L43)_
154154

155155
A one-off method for processing speech to text
156156
using Spokestack ASR.
@@ -203,7 +203,7 @@ expressApp.post('/asr', fileUpload(), (req, res) => {
203203

204204
**googleASR**(`content`: string \| Uint8Array, `sampleRate`: number): Promise<string \| null\>
205205

206-
_Defined in [server/asr.ts:97](https://github.com/spokestack/node-spokestack/blob/7555411/src/server/asr.ts#L97)_
206+
_Defined in [server/asr.ts:97](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/server/asr.ts#L97)_
207207

208208
A one-off method for processing speech to text
209209
using Google Speech.
@@ -254,7 +254,7 @@ expressApp.post('/asr', fileUpload(), (req, res) => {
254254

255255
**encryptSecret**(`body`: string): string
256256

257-
_Defined in [server/encryptSecret.ts:13](https://github.com/spokestack/node-spokestack/blob/7555411/src/server/encryptSecret.ts#L13)_
257+
_Defined in [server/encryptSecret.ts:13](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/server/encryptSecret.ts#L13)_
258258

259259
This is a convenience method for properly authorizing
260260
requests to the Spokestack graphql API.
@@ -283,7 +283,7 @@ These functions are available exports from `spokestack/client`.
283283

284284
**record**(`config?`: RecordConfig): Promise<AudioBuffer\>
285285

286-
_Defined in [client/record.ts:84](https://github.com/spokestack/node-spokestack/blob/7555411/src/client/record.ts#L84)_
286+
_Defined in [client/record.ts:84](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/client/record.ts#L84)_
287287

288288
A method to record audio for a given number of seconds
289289

@@ -363,31 +363,31 @@ fetch('/asr', {
363363

364364
`Optional` **onProgress**: undefined \| (remaining: number) => void
365365

366-
_Defined in [client/record.ts:16](https://github.com/spokestack/node-spokestack/blob/7555411/src/client/record.ts#L16)_
366+
_Defined in [client/record.ts:16](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/client/record.ts#L16)_
367367

368368
A callback function to be called each second of recording.
369369

370370
##### onStart
371371

372372
`Optional` **onStart**: undefined \| () => void
373373

374-
_Defined in [client/record.ts:14](https://github.com/spokestack/node-spokestack/blob/7555411/src/client/record.ts#L14)_
374+
_Defined in [client/record.ts:14](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/client/record.ts#L14)_
375375

376376
A callback function to be called when recording starts
377377

378378
##### time
379379

380380
`Optional` **time**: undefined \| number
381381

382-
_Defined in [client/record.ts:12](https://github.com/spokestack/node-spokestack/blob/7555411/src/client/record.ts#L12)_
382+
_Defined in [client/record.ts:12](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/client/record.ts#L12)_
383383

384384
The total time to record. Default: 3
385385

386386
### startStream
387387

388-
**startStream**(`isPlaying`: () => boolean): Promise<WebSocket, [ProcessorReturnValue]\>
388+
**startStream**(`__namedParameters`: { address: undefined \| string ; isPlaying: () => boolean }): Promise<WebSocket, [ProcessorReturnValue]\>
389389

390-
_Defined in [client/recordStream.ts:29](https://github.com/spokestack/node-spokestack/blob/7555411/src/client/recordStream.ts#L29)_
390+
_Defined in [client/recordStream.ts:44](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/client/recordStream.ts#L44)_
391391

392392
Returns a function to start recording using a native WebSocket.
393393
This assumes the socket is hosted on the current server.
@@ -397,7 +397,10 @@ import { startStream } from 'spokestack/client'
397397

398398
// ...
399399
try {
400-
const [ws] = await startStream(() => this.isPlaying)
400+
const [ws] = await startStream({
401+
address: 'wss://localhost:3000',
402+
isPlaying: () => this.isPlaying
403+
})
401404
ws.addEventListener('open', () => console.log('Recording started'))
402405
ws.addEventListener('close', () => console.log('Recording stopped'))
403406
ws.addEventListener('message', (e) => console.log('Speech processed: ', e.data))
@@ -408,9 +411,9 @@ try {
408411

409412
#### Parameters:
410413

411-
| Name | Type | Description |
412-
| ----------- | ------------- | ------------------------------------------------------------------------------------------------------------- |
413-
| `isPlaying` | () => boolean | A function returning whether audio is currently playing. This is necessary to prevent recording played audio. |
414+
| Name | Type |
415+
| ------------------- | ----------------------------------------------------------- |
416+
| `__namedParameters` | { address: undefined \| string ; isPlaying: () => boolean } |
414417

415418
**Returns:** Promise<WebSocket, [ProcessorReturnValue]\>
416419

@@ -420,7 +423,7 @@ try {
420423

421424
**stopStream**(): void
422425

423-
_Defined in [client/recordStream.ts:80](https://github.com/spokestack/node-spokestack/blob/7555411/src/client/recordStream.ts#L80)_
426+
_Defined in [client/recordStream.ts:97](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/client/recordStream.ts#L97)_
424427

425428
Stop the current recording stream if one exists.
426429

@@ -435,7 +438,7 @@ stopStream()
435438

436439
**convertFloat32ToInt16**(`fp32Samples`: Float32Array): Int16Array
437440

438-
_Defined in [client/convertFloat32ToInt16.ts:16](https://github.com/spokestack/node-spokestack/blob/7555411/src/client/convertFloat32ToInt16.ts#L16)_
441+
_Defined in [client/convertFloat32ToInt16.ts:16](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/client/convertFloat32ToInt16.ts#L16)_
439442

440443
A utility method to convert Float32Array audio
441444
to an Int16Array to be passed directly to Speech APIs
@@ -466,7 +469,7 @@ These are low-level functions for working with your own processors, available fr
466469

467470
**startProcessor**(): Promise<Error] \| [null, [ProcessorReturnValue]\>
468471

469-
_Defined in [client/processor.ts:32](https://github.com/spokestack/node-spokestack/blob/7555411/src/client/processor.ts#L32)_
472+
_Defined in [client/processor.ts:32](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/client/processor.ts#L32)_
470473

471474
Underlying utility method for recording audio,
472475
used by the `record` and `recordStream` methods.
@@ -485,7 +488,7 @@ We'll switch to AudioWorklet when it does.
485488

486489
**stopProcessor**(): void
487490

488-
_Defined in [client/processor.ts:60](https://github.com/spokestack/node-spokestack/blob/7555411/src/client/processor.ts#L60)_
491+
_Defined in [client/processor.ts:60](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/client/processor.ts#L60)_
489492

490493
Underlying utility method to stop the current processor
491494
if it exists and disconnect the microphone.
@@ -498,19 +501,19 @@ if it exists and disconnect the microphone.
498501

499502
**context**: AudioContext
500503

501-
_Defined in [client/processor.ts:18](https://github.com/spokestack/node-spokestack/blob/7555411/src/client/processor.ts#L18)_
504+
_Defined in [client/processor.ts:18](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/client/processor.ts#L18)_
502505

503506
##### processor
504507

505508
**processor**: ScriptProcessorNode
506509

507-
_Defined in [client/processor.ts:19](https://github.com/spokestack/node-spokestack/blob/7555411/src/client/processor.ts#L19)_
510+
_Defined in [client/processor.ts:19](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/client/processor.ts#L19)_
508511

509512
### concatenateAudioBuffers
510513

511514
**concatenateAudioBuffers**(`buffer1`: AudioBuffer \| null, `buffer2`: AudioBuffer \| null, `context`: AudioContext): null \| AudioBuffer
512515

513-
_Defined in [client/concatenateAudioBuffers.ts:4](https://github.com/spokestack/node-spokestack/blob/7555411/src/client/concatenateAudioBuffers.ts#L4)_
516+
_Defined in [client/concatenateAudioBuffers.ts:4](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/client/concatenateAudioBuffers.ts#L4)_
514517

515518
A utility method to concatenate two AudioBuffers
516519

@@ -528,7 +531,7 @@ A utility method to concatenate two AudioBuffers
528531

529532
**countdown**(`time`: number, `progress`: (remaining: number) => void, `complete`: () => void): void
530533

531-
_Defined in [client/countdown.ts:7](https://github.com/spokestack/node-spokestack/blob/7555411/src/client/countdown.ts#L7)_
534+
_Defined in [client/countdown.ts:7](https://github.com/spokestack/node-spokestack/blob/47dbb86/src/client/countdown.ts#L7)_
532535

533536
Countdown a number of seconds
534537

examples/with-next/pages/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -177,7 +177,7 @@ export default class Index extends PureComponent {
177177
} else {
178178
this.initialize()
179179
try {
180-
const [ws] = await startStream(() => this.playing)
180+
const [ws] = await startStream({ isPlaying: () => this.playing })
181181
ws.addEventListener('open', () =>
182182
this.setState({ status: 'Recording...', streaming: true })
183183
)

examples/with-next/server/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,9 @@ app.prepare().then(() => {
107107

108108
const server = createServer(expressApp)
109109
if (useGoogleAsr) {
110-
googleASRSocketServer(server)
110+
googleASRSocketServer({ server })
111111
} else {
112-
asrSocketServer(server)
112+
asrSocketServer({ server })
113113
}
114114
server.listen(port, () => {
115115
console.log(`Listening at http://localhost:${port}`)

src/client/recordStream.ts

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,21 @@ import { setCookie } from '../cookies'
55

66
let stop: (() => void) | undefined
77

8+
interface StartStreamOptions {
9+
/**
10+
* The address (with protocol and port) of the Spokestack ASR websocket.
11+
* Defaults to the same domain and port as the current window location,
12+
* but with ws(s) as the protocol (depending on https).
13+
* See asrSocketServer for help creating a socket server.
14+
* */
15+
address?: string
16+
/**
17+
* A function returning whether audio is currently playing.
18+
* This is necessary to prevent recording played audio.
19+
*/
20+
isPlaying: () => boolean
21+
}
22+
823
/**
924
* Returns a function to start recording using a native WebSocket.
1025
* This assumes the socket is hosted on the current server.
@@ -14,30 +29,32 @@ let stop: (() => void) | undefined
1429
*
1530
* // ...
1631
* try {
17-
* const [ws] = await startStream(() => this.isPlaying)
32+
* const [ws] = await startStream({
33+
* address: 'wss://localhost:3000',
34+
* isPlaying: () => this.isPlaying
35+
* })
1836
* ws.addEventListener('open', () => console.log('Recording started'))
1937
* ws.addEventListener('close', () => console.log('Recording stopped'))
2038
* ws.addEventListener('message', (e) => console.log('Speech processed: ', e.data))
2139
* } catch (e) {
2240
* console.error(e)
2341
* }
2442
* ```
25-
*
26-
* @param isPlaying A function returning whether audio is currently playing.
27-
* This is necessary to prevent recording played audio.
2843
*/
29-
export async function startStream(
30-
isPlaying: () => boolean
31-
): Promise<[WebSocket, ProcessorReturnValue]> {
44+
export async function startStream({
45+
address,
46+
isPlaying
47+
}: StartStreamOptions): Promise<[WebSocket, ProcessorReturnValue]> {
48+
if (!address) {
49+
address = `${location.protocol === 'https:' ? 'wss:' : 'ws:'}//${location.hostname}${
50+
location.port ? `:${location.port}` : ''
51+
}`
52+
}
3253
const [error, result] = await startProcessor()
3354
if (error) {
3455
throw error
3556
}
3657
const { context, processor } = result as ProcessorReturnValue
37-
const address = `${location.protocol === 'https:' ? 'wss:' : 'ws:'}//${location.hostname}${
38-
location.port ? `:${location.port}` : ''
39-
}`
40-
4158
const ws = new WebSocket(address)
4259
setCookie('sampleRate', context.sampleRate + '')
4360

src/server/socketServer.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import spokestackService, { SpokestackASRConfig } from './spokestackASRService'
2-
3-
import { Server } from 'http'
42
import { SpeechClient } from '@google-cloud/speech'
53
import WebSocket from 'ws'
64
import { getCookie } from '../cookies'
@@ -16,17 +14,17 @@ import { google } from '@google-cloud/speech/build/protos/protos'
1614
* const port = parseInt(process.env.PORT || '3000', 10)
1715
* const server = createServer() // or express()
1816
* // Attach the websocket server to the HTTP server
19-
* asrSocketServer(server)
17+
* asrSocketServer({ server })
2018
* server.listen(port, () => {
2119
* console.log(`Listening at http://localhost:${port}`)
2220
* })
2321
* ```
2422
*/
2523
export function asrSocketServer(
26-
server: Server,
24+
serverConfig: WebSocket.ServerOptions,
2725
asrConfig: Omit<SpokestackASRConfig, 'sampleRate'> = {}
2826
): void {
29-
const wss = new WebSocket.Server({ server })
27+
const wss = new WebSocket.Server(serverConfig)
3028
console.log('Websocket started')
3129

3230
wss.on('connection', async (ws, request) => {
@@ -101,14 +99,14 @@ export function asrSocketServer(
10199
* const port = parseInt(process.env.PORT || '3000', 10)
102100
* const server = createServer() // or express()
103101
* // Attach the websocket server to the HTTP server
104-
* googleASRSocketServer(server)
102+
* googleASRSocketServer({ server })
105103
* server.listen(port, () => {
106104
* console.log(`Listening at http://localhost:${port}`)
107105
* })
108106
* ```
109107
*/
110-
export function googleASRSocketServer(server: Server): void {
111-
const wss = new WebSocket.Server({ server })
108+
export function googleASRSocketServer(serverConfig: WebSocket.ServerOptions): void {
109+
const wss = new WebSocket.Server(serverConfig)
112110
console.log('Websocket started')
113111

114112
wss.on('connection', (ws, request) => {

0 commit comments

Comments
 (0)