README
Symbl Web SDK
The Symbl Web SDK provides convenient access to the Symbl API from applications written in the Javascript language directly in the browser. It includes a pre-defined set of classes for a simple and clear utilization of APIs.
Documentation
See the API docs.
Browser Support
Chrome | Edge | Firefox | Safari | |
---|---|---|---|---|
macOS | ✓ | ✓ | ✓ | ✓ |
Windows | ✓ | ✓ | ✓ | - |
Linux | ✓ | - | ✓ | - |
iOS | ✓ | - | ✓ | ✓ |
Android | ✓ | - | ✓ | ✓ |
Installation
npm install @symblai/symbl-web-sdk
Build
If you'd like to build a local copy of the SDK you will need Node.js installed and you can simply run the following command inside of the repository folder:
npm install && npm run build
Your build will be located in the dist/
folder.
Setup
In order to use the Symbl Web SDK you need to include it via script tags in your HTML file or in the case of a front-end web application using a framework such as React, import it in the ES2015 style.
HTML script:
<script src="https://sdk.symbl.ai/js/beta/symbl-web-sdk/latest/symbl.min.js"></script>
or
<script src="https://sdk.symbl.ai/js/beta/symbl-web-sdk/v0.8.6/symbl.min.js"></script>
Web Application import:
import symbl from "@symblai/symbl-web-sdk";
Authentication
The SDK needs to be initialized with your account's credentials (appId & appSecret) which is available in your Symbl Platform.
symbl.init({
appId: '<your App ID>',
appSecret: '<your App Secret>',
// accessToken: '<your Access Token>', // can be used instead of appId and appSecret
// basePath: '<your custom base path (optional)>',
// logLevel: 'debug' // you can set which log level you want to view
});
Streaming API config options
The full details of the Streaming API config options can be seen here.
Additional Web SDK configs
These are configs that have been added that are specific to the Web SDK.
Name | Default | Description |
---|---|---|
sourceNode |
null |
For passing in an external MediaStreamAudioSourceNode object. By default the Web SDK will handle audio context and source nodes on it's own, though if you wish to handle that externally we've provided that option. |
reconnectOnError |
false |
If true the Web SDK will attempt to reconnect to the WebSocket in case of error. You can also make sure of our onReconnectFail callback which will fire in case the reconnection attempt fails. |
Usage Example:
const id = btoa("my-first-symbl-ai-code");
const connectionConfig = {
id,
insightTypes: ['action_item', 'question'],
sourceNode: sourceNode,
reconnectOnError: true,
handlers: { // Read the handlers section for more
ondevicechange: () => {
alert('device changed!');
},
...
}
...
}
...
// Creates the WebSocket in a non-processing state
const stream = await symbl.createStream(connectionConfig);
// Send the start request
await symbl.start(stream);
Handlers / Callbacks
Web SDK provides a suite of callbacks for you to utilize in your application.
Name | Description |
---|---|
onClose(event) |
Fires when the WebSocket connection closes for any reason. |
onSpeechDetected(data) |
To retrieve the real-time transcription results as soon as they are detected. You can use this callback to render live transcription which is specific to the speaker of this audio stream. View an example of the response here |
onMessageResponse(messages) |
This callback function contains the "finalized" transcription data for this speaker and if used with multiple streams with other speakers this callback would also provide their messages. View an example of the response here |
onInsightResponse(insights) |
This callback provides you with any of the detected insights in real-time as they are detected. As with the onMessageCallback this would also return every speaker's insights in case of multiple streams. View an example of the response here |
onTrackerResponse(trackers) |
This callback provides you with any of the detected trackers in real-time as they are detected. As with the onMessageCallback this would also return every tracker in case of multiple streams. View an example of the response here |
onTopicResponse(topics) |
This callback provides you with any of the detected topics in real-time as they are detected. As with the onMessageCallback this would also return every topic in case of multiple streams. View an example of the response here |
onRequestError(err) |
Fires when the WebSocket has an error. |
onConversationCompleted(message) |
Fires when the conversation_completed event is recieved from the WebSocket. |
onReconnectFail(err) |
Fires when the reconnection attempt fails. Related to the reconnectOnError config. |
onStartedListening(message) |
Fires when the started_listening event is received from the WebSocket. |
onRequestStart(message) |
Fires when the recognition_started event is received from the WebSocket |
onRequestStop(message) |
Fires when the recognition_stopped event is received from the WebSocket |
createStream
to start a realtime request
Using Creating a stream using symbl.startRealtimeRequest(config)
has been deprecated in favor of symbl.createStream(config)
. For createStream
, the WebSocket is started in a non processing state. You must send the start request before processing any audio.
After the stream is created, you need to call symbl.start(stream)
to start the stream.
How to pass in a custom sourceNode
If you wish you can pass in a custom MediaStreamAudioSourceNode object to the Web SDK. By default the Web SDK will create the AudioContext and the MediaStreamAudioSourceNode object automatically but using this will give you more control over those.
Once you create the MediaStreamAudioSourceNode object you can pass it via the connectionConfig as sourceNode
// create the MediaStreamAudioSourceNode
const AudioContext = window.AudioContext || window.webkitAudioContext;
stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: false
});
context = new AudioContext();
const sourceNode = context.createMediaStreamSource(stream);
symbl.init({
appId: '<your App ID>',
appSecret: '<your App Secret>',
// accessToken: '<your Access Token>', // can be used instead of appId and appSecret
basePath: 'https://api.symbl.ai',
});
const id = btoa("my-first-symbl-ai-code");
// pass in the MediaStreamAudioSourceNode as sourceNode
const connectionConfig = {
id,
sourceNode,
insightTypes: ['action_item', 'question'],
config: {
meetingTitle: 'My Test Meeting ' + id,
confidenceThreshold: 0.7,
timezoneOffset: 480, // Offset in minutes from UTC
languageCode: 'en-US',
sampleRateHertz: 48000
},
speaker: {
// Optional, if not specified, will simply not send an email in the end.
userId: '', // Update with valid email
name: ''
},
handlers: {
/**
* This will return live speech-to-text transcription of the call.
*/
onSpeechDetected: (data) => {
if (data) {
const {punctuated} = data
console.log('Live: ', punctuated && punctuated.transcript)
console.log('');
}
// console.log('onSpeechDetected ', JSON.stringify(data, null, 2));
},
/**
* When processed messages are available, this callback will be called.
*/
onMessageResponse: (data) => {
// console.log('onMessageResponse', JSON.stringify(data, null, 2))
},
/**
* When Symbl detects an insight, this callback will be called.
*/
onInsightResponse: (data) => {
// console.log('onInsightResponse', JSON.stringify(data, null, 2))
},
/**
* When Symbl detects a topic, this callback will be called.
*/
onTopicResponse: (data) => {
// console.log('onTopicResponse', JSON.stringify(data, null, 2))
}
}
};
(async () => {
// Creates the WebSocket in a non-processing state
const stream = await symbl.createStream(connectionConfig);
// Send the start request
await stream.start(stream);
})();
Updating your external source node
If you wish to update your external source node you can do se by using the symbl.updateSourceNode
function:
symbl.updateSourceNode(stream, sourceNode);
ondevicechange
handler.
Passing in custom By default the Symbl Web SDK will handle the ondevicechange
event and send a modify_request
event to modify the sample rate with the new device's sample rate. If you wish to override this logic you can pass in your own ondevicechange
handler in the handlers config.
symbl.init({
appId: '<your App ID>',
appSecret: '<your App Secret>',
// accessToken: '<your Access Token>', // can be used instead of appId and appSecret
basePath: 'https://api.symbl.ai',
});
const id = btoa("my-first-symbl-ai-code");
// pass in the MediaStreamAudioSourceNode as sourceNode
const connectionConfig = {
id,
insightTypes: ['action_item', 'question'],
config: {
languageCode: 'en-US',
sampleRateHertz: 48000
},
handlers: {
ondevicechange: () => {
// add your logic here.
}
}
};
(async () => {
// Creates the WebSocket in a non-processing state
const stream = await symbl.createStream(connectionConfig);
// Send the start request
await stream.start(stream);
})();
deviceChanged
callback
Using the You can also make use of our callback using our deviceChanged
callback:
symbl.deviceChanged = () => {
// Add your logic here
}
Transcribing live audio input through the microphone
As a simple test of the Streaming API you can simply setup a live microphone and push the audio stream using the browser APIs to access the microphone.
Initialize the SDK and connect via the built-in websocket connector. This will output the live transcription to the console.
NOTE: The symbl.startRealtimeRequest
function creates a new AudioContext, so the call must be made on user interaction, such as a button click.
symbl.init({
appId: '<your App ID>',
appSecret: '<your App Secret>',
// accessToken: '<your Access Token>', // can be used instead of appId and appSecret
// basePath: '<your custom base path (optional)>',
});
const id = btoa("my-first-symbl-ai-code");
const connectionConfig = {
id,
insightTypes: ['action_item', 'question'],
config: {
meetingTitle: 'My Test Meeting ' + id,
confidenceThreshold: 0.7,
timezoneOffset: 480, // Offset in minutes from UTC
languageCode: 'en-US',
// sampleRateHertz: 48000
},
speaker: {
// Optional, if not specified, will simply not send an email in the end.
userId: '', // Update with valid email
name: ''
},
handlers: {
/**
* This will return live speech-to-text transcription of the call.
*/
onSpeechDetected: (data) => {
if (data) {
const {punctuated} = data
console.log('Live: ', punctuated && punctuated.transcript)
console.log('');
}
// console.log('onSpeechDetected ', JSON.stringify(data, null, 2));
},
/**
* When processed messages are available, this callback will be called.
*/
onMessageResponse: (data) => {
// console.log('onMessageResponse', JSON.stringify(data, null, 2))
},
/**
* When Symbl detects an insight, this callback will be called.
*/
onInsightResponse: (data) => {
// console.log('onInsightResponse', JSON.stringify(data, null, 2))
},
/**
* When Symbl detects a topic, this callback will be called.
*/
onTopicResponse: (data) => {
// console.log('onTopicResponse', JSON.stringify(data, null, 2))
}
}
};
(async () => {
const stream = await symbl.createStream(connectionConfig);
})();
Muting and unmuting the connected device
You can mute and unmute the connected device by simply calling symbl.mute()
or symbl.unmute()
.
Note that if disconnectOnStopRequest
is passed in as true
in the createStream
function call, the mute
and unmute
function also invoke the start
and stop
functions, that signal the Streaming API to start and stop processing the audio being sent in between these two calls.
Muting
A quick snippet on how to use the mute method.
(async () => {
const stream = await symbl.createStream(connectionConfig);
await symbl.mute(stream);
})();
Unmuting
A quick snippet on how to use the unmute method.
(async () => {
const stream = await symbl.createStream(connectionConfig);
await symbl.unmute(stream);
})();
Reconnecting to an existing realtime connection
In the case that a user closes their browser or has an interruption in their WebSocket connection you can use the store
object to grab the Connection ID you last used.
const id = symbl.store.get('connectionID');
const connectionConfig = {
id,
insightTypes: ['action_item', 'question'],
config: {
meetingTitle: 'My Test Meeting ' + id,
confidenceThreshold: 0.7,
timezoneOffset: 480, // Offset in minutes from UTC
languageCode: 'en-US',
sampleRateHertz: 44100
},
speaker: {
// Optional, if not specified, will simply not send an email in the end.
userId: '', // Update with valid email
name: ''
},
handlers: {
/**
* This will return live speech-to-text transcription of the call.
*/
onSpeechDetected: (data) => {
if (data) {
const {punctuated} = data
console.log('Live: ', punctuated && punctuated.transcript)
console.log('');
}
// console.log('onSpeechDetected ', JSON.stringify(data, null, 2));
},
/**
* When processed messages are available, this callback will be called.
*/
onMessageResponse: (data) => {
// console.log('onMessageResponse', JSON.stringify(data, null, 2))
},
/**
* When Symbl detects an insight, this callback will be called.
*/
onInsightResponse: (data) => {
// console.log('onInsightResponse', JSON.stringify(data, null, 2))
},
/**
* When Symbl detects a topic, this callback will be called.
*/
onTopicResponse: (data) => {
// console.log('onTopicResponse', JSON.stringify(data, null, 2))
}
}
};
(async () => {
const stream = await symbl.createStream(connectionConfig);
})();
Stopping realtime connection
In order to end the connection to the realtime WebSocket you'll need to use the following command with your connection
object:
symbl.stopRequest(stream);
If you do not sever the connection you could use more minutes of time than intended, so it is recommended to always end the connection programmatically.
Subscribing to an existing realtime connection with Subscribe API
With the Subscribe API you can connect to an existing connection via the connection ID. Building on the previous example we can connect to that ID. You'll want to open this example in a different browser while the realtime transcription example is running.
/**
* id: connectionId
* cb: message callback
* reconnectOnerror: boolean
*/
const conversationStream = await symbl.subscribeToStream(id, (message) => { ... }, true);
Closing the Subscribe API connection
In order to end the connection to the Subscribe API WebSocket, you'll need to use the following command with your conversationStream
object:
conversationStream.close();
Need support?
If you can't find your answers, do let us know at support@symbl.ai or join our slack channel here.