Flex Audio SDK for Web: Quickstart
The Aircore Flex Audio SDK for Web allows you to quickly add high-quality, real-time voice chat to your web app. This lets you avoid dealing with the complexities of building a real-time system on your own.
This guide provides a basic pathway for adding the Flex Audio SDK to a web app.
Before starting
Minimum versions
- Node: 16.0.0
Supported browsers and devices
Desktop: Chrome, Edge, Firefox, and Safari
iOS: Chrome and Safari
Android: Chrome
Install the SDK
Navigate to your project workspace and install the SDK using npm:
npm i @aircore/aircore-media
Authenticate
For this SDK, you must use a secret API key and session auth tokens.
To get started:
Create an app in the Developer Console.
Copy the secret API key and use it to request a session auth token.
Use the session auth token to create a channel in the next section.
For an overview of API keys, see Authentication.
Create and use a channel
A channel is a connection to a real-time session with other users. See Channels for a general overview.
Joining a channel allows your app to:
Publish a local stream, which is audio shared to other users
Receive remote streams, which are audio shared from other users
Create a channel
Engine.sharedInstance
is a singleton that produces a Channel
object.
To start using a channel:
Set the Channel
allowAutoplayCallback
property. This prompts the user to interact to unblock audio streams on the page.import { Channel } from '@aircore/aircore-media'; // Set up a user prompt to allow audio autoplay Channel.allowAutoplayCallback = (play) => { const playButton = document.createElement('button'); playButton.innerHTML = 'Click to play media'; playButton.onclick = () => { playButton.remove(); play(); }; document.body.append(playButton); };
Use your secret API key to get a session auth token from your backend.
Then, call the
createChannel()
method and keep the resultingChannel
object.import { Engine, ChannelNotification } from '@aircore/aircore-media'; const getNewSessionAuthTokenFromBackend = () => { // Use your secret API key to fetch a token }; // Get a token const sessionAuthToken = getNewSessionAuthTokenFromBackend(); // Instantiate the channel const channel = Engine.sharedInstance.createChannel(sessionAuthToken); // Set up handler to fetch a new token and update the channel when necessary channel.on(ChannelNotification.SessionAuthTokenNearingExpiry, () => { const newToken = getNewSessionAuthTokenFromBackend(); await channel.updateSessionAuthToken(newToken); });
Use the channel's
join()
method to connect and start receiving audio.// Connect to the channel await channel.join();
Leave a channel
When you no longer need a channel, call its leave()
method. You can use this method at any time, except when the channel is already terminated.
Leaving destroys all objects for local and remote streams, releasing system resources used by the channel.
The local channel instance also terminates if there is an unrecoverable error. To listen for channel terminations you may track the channel's join state.
You cannot rejoin a terminated channel. To return to the session with the same users, create a new channel.
Track the status of a channel
The joinState
property shows a channel's connection status. Channel.JoinState
enumerates all the possible join states.
To track changes to this property, use the joinStateDidChange
notification:
import { Channel, ChannelNotification, ChannelNotificationKey } from '@aircore/aircore-media';
const addJoinStateHandler = (channel: Channel) => {
channel.on(ChannelNotification.JoinStateDidChange, (data) => {
const newState = data[ChannelNotificationKey.NewJoinState];
let terminationCause;
switch(newState) {
case Channel.JoinState.notJoined:
// The initial state. The channel has not yet connected.
// No interaction with other users is possible.
// NOTE: A notification for notJoined is not sent.
case Channel.JoinState.joining:
// The channel is connecting for the first time.
case Channel.JoinState.joined:
// The channel is connected and automatically plays remote streams.
case Channel.JoinState.rejoining:
// The channel connected and then disconnected.
// It is now reconnecting.
case Channel.JoinState.terminated:
// The channel has permanently disconnected. You can check the
// termination cause here.
// NOTE: You can't reuse the channel, but you can detect if the channel
// terminated unexpectedly and either create a new channel or show an
// error to the user.
terminationCause = channel.terminationCause;
}
});
};
You can use the join state to build your user experience and UI. See More options for examples.
Update expiring tokens
The sessionAuthTokenNearingExpiry
notification tells you when the token used to join a channel is about to expire. You must replace the token to continue using the channel.
Your backend requests a new token from the Aircore provisioning service. Then, your app can update the token for the channel.
This example shows how to handle token expiry notifications:
import { Channel, ChannelNotification, ChannelNotificationKey } from '@aircore/aircore-media';
const addSessionAuthTokenNearingExpiryHandler = (channel: Channel) => {
channel.on(ChannelNotification.SessionAuthTokenNearingExpiry, (data) => {
// The event data contains the expiration timestamp of the token.
const tokenExpiresAt = data[ChannelNotificationKey.TokenExpiresAt];
});
};
You can update the token at any time, except when the channel's join state is terminated
.
You can also change the permissions by updating the token. For example, if a user does not have permission to publish audio when they join a channel, you can provide a new token to give a user permission.
Note: When you update a channel, the new token must have the same user ID and the same channel ID. If one or both does not match, the channel terminates.
Handle expired tokens
Avoid letting tokens expire by listening for the sessionAuthTokenNearingExpiry
notification.
If your app tries to join a channel with an expired token:
The channel disconnects.
The
joinState
isterminated
.The
terminationCause
issessionAuthTokenInvalid
.
You can use the join state notification to handle this issue. See Track the status of a channel.
import { Engine, Channel, ChannelNotification, ChannelNotificationKey } from '@aircore/aircore-media';
const getNewSessionAuthTokenFromBackend = () => {
// Use your secret API key to fetch a token
};
const addJoinStateHandler = (channel: Channel) => {
channel.on(ChannelNotification.JoinStateDidChange, (data) => {
const newState = data[ChannelNotificationKey.NewJoinState];
if (
newState === Channel.JoinState.terminated &&
channel.terminationCause === Channel.TerminationCause.sessionAuthTokenInvalid
) {
const newToken = getNewSessionAuthTokenFromBackend();
channel = Engine.sharedInstance.createChannel(newToken);
}
});
};
Publish audio
Users share audio within a channel as streams. To publish audio to other users, you create a local stream.
Use a channel's
createLocalStream()
method to create a local stream.The channel's join state must be
joined
orrejoining
.import { Channel, LocalStreamParams } from '@aircore/aircore-media'; // ... Create and join a channel // Make sure the channel is connected const channelJoinState = channel.joinState; let localStream; if ( channelJoinState === Channel.JoinState.joined || channelJoinState === Channel.JoinState.rejoining ) { // Default paramaters const params = new LocalStreamParams(); try { localStream = channel.createLocalStream(params); } catch (err) { // Handle error case } }
Use
start()
to publish audio from the microphone:// Start the local stream await localStream.start(); // You can choose to keep the local stream or access it from the channel
Use
muteAudio()
to stop capturing and publishing audio:// Mute the audio await localStream.muteAudio(true); // Unmute the audio await localStream.muteAudio(false);
Stop the stream:
// To stop sending local audio, stop the local stream await localStream.stop();
Note: For local streams, muting and unmuting are asynchronous operations. If a channel's session auth token does not have permission to publish audio, unmuting fails.
Get notifications for local streams
The LocalStreamNotification
interface has notifications for mute state and connection state for local streams.
Receive audio
When your app connects to a channel, it receives audio streams from other users. These are called remote streams.
The SDK automatically connects to remote streams and plays them through the active output device. You don't have to do any setup to use remote streams.
For tasks such as getting metadata and muting a stream, you can use remote stream objects.
Check remote streams in a channel
To see a list of active remote streams within a channel, check its remoteStreams
property. You can use this property to show active streams in your UI.
Each item in the list is a RemoteStream
object, which represents a stream from one user.
To get notifications for added and removed streams, see More options.
Check the connection to a remote stream
To see if a remote stream is connected, check the connectionState
property.
To get notifications for remote stream connection status, see More options.
Mute a remote stream
To mute the incoming audio from a remote stream, use its muteAudio()
method. Your app still receives the audio but doesn't play it.
Track local audio muting
To track local muting of an incoming remote stream with muteAudio()
, you can use:
The
localAudioMuteStateDidChange
notificationThe
localAudioMuted
property
Track remote audio muting
The publisher can also mute a remote stream. To track when the publisher mutes audio that your app is receiving, you can use:
The
remoteAudioMuteStateDidChange
notificationThe
remoteAudioMuted
property
Check termination cause
To see why a remote stream ended, check the terminationCause
property.
More info
- To continue building your app, see More options.