Connection State
Establishing and maintaining a video connection involves many steps, and unexpected errors may occur at any point during a session. Proper handling of all connection states in your code will ensure you have full visibility of what went wrong and why, which will be essential in providing a positive user experience, and also in debugging any issues.
Connection Success
A successful call to connect()
resolves to a sessionId
string which uniquely identifies the current user's video session.
session.connect().then((sessionId) => onConnectionSuccess(sessionId));
function onConnectionSuccess(sessionId) {
console.log('Connected with sessionId:', sessionId);
}
There is no requirement to store the sessionId
in your application for later use, but you may find it useful for tracking and grouping your own events for analytics purposes, or for debugging a particular session with Soul Machines support, who can look up the server logs for a given sessionId
.
When Session Persistence is enabled, each new video session will re-use the same underlying Digital Person session on the server, and so the sessionId
will remain the same each time the user reconnects to that same persisted session.
For a simple use case, it is okay to ignore the sessionId
.
Connection Failure
A failed call to connect()
will throw an error
which includes some details about what went wrong.
A connection can fail for many different reasons, but the error.name
and error.message
will provide some guidance for where to start with debugging.
session
.connect()
.then((sessionId) => onConnectionSuccess(sessionId))
.catch((error) => onConnectionError(error));
function onConnectionError(error: Error) {
console.log('Connection failed with error:', error);
}
A basic implementation of handling the most common errors might look something like this:
function onConnectionError(error: Error) {
console.log('Connection failed with error:', error);
switch (error.name) {
case 'noUserMedia':
console.log('user declined device access:', error.message);
// ask the user to unblock devices
break;
case 'noScene':
console.log('the server is busy:', error.message);
// ask the user to retry later
break;
case 'serverConnectionFailed':
console.log('server connection failed:', error.message);
// ask the user to connect from a different network
break;
default:
console.log('unhandled error:', error.name, error.message);
}
}
Possible connection errors:
- noUserMedia: the microphone/camera is either not available, not usable or the user declined permission
- noScene: no persona was available, the server was busy
- serverConnectionFailed: the connection to the server failed
- notSupported: the user's browser does not support getUserMedia
- mediaStreamFailed: the audio/video stream failed
- sessionTimeout: the session timed out before it was fully available
- controlFailed: a connection to the orchestration server could not be established
- noSessionToResume: an API Key with session persistence enabled was unable to reconnect to the previous session
Disconnection
If something goes wrong during a session, the scene will disconnect.
scene.onDisconnectedEvent.addListener((scene, sessionId, reason) => {
console.log('scene disconnected:', sessionId, reason);
// handle disconnection
});
Possible disconnect reasons:
- sessionTimeout: the user did not interact for the length of time defined in the project's session timeout
- conversationEnded: the conversation or NLP provider has requested for the session to be ended
- controlDisconnected: The orchestration server has disconnected and is no longer able to direct the conversation
- normal: the connection was closed
Connection Progress
The connection speed to the Digital Person (DP) varies due to time, location, and internet speed, which makes visibility into the state of the loading process important for user experience. To display the connection progress, Connection state events are available for use (e.g. to customise the loading interface before the connection succeeds). To this end, infrastructure has been put together that classifies the connection as being in one of the following ConnectionStateTypes
:
Disconnected
SearchingForDigitalPerson
DownloadingAssets
ConnectingToDigitalPerson
Connected
When scene.connect()
is called, the connection process has started. It will go through following steps.
SearchingForDigitalPerson
- open websocket connection to DP server, searching for an available DP, may require queuingDownloadingAssets
- DP is found, starting downloading assetsConnectingToDigitalPerson
- DP is starting, forming webrtc connectionConnected
- DP is ready, webrtc session has connected
Subscribing to Connection State/Progress
After creating the Scene
, you can add callback function to handle connection state before calling the connect()
method of Scene
to get the connection progress updates.
scene = new Scene({...});
scene.connectionState.onConnectionStateUpdated.addListener(
(connectionStateData: ConnectionStateData) => {
// display connectionState updates to the user
}
);
scene.connect();
The callback will receive the current connectionStateData
. If you are using TypeScript you can import the type ConnectionStateData
from the Web SDK.
Example of the data you will receive in the callback as below. You can use the suggested percentageLoaded
value to update a progress bar, or use currentStep
value to indicate the progress.
name: Disconnected
currentStep: 0
totalSteps: 5
percentageLoaded: 0
name: SearchingForDigitalPerson
currentStep: 1
totalSteps: 5
percentageLoaded: 25
name: DownloadingAssets
currentStep: 2
totalSteps: 5
percentageLoaded: 50
name: ConnectingToDigitalPerson
currentStep: 3
totalSteps: 5
percentageLoaded: 75
name: Connected
currentStep: 4
totalSteps: 5
percentageLoaded: 100
Progress states are an estimate. They should be used for the display of connection progress only, and should not be relied upon for identifying the overall Session connection state.