final call = StreamVideo.instance.makeCall(callType: StreamCallType.defaultType(), id: 'Your-call-ID');
await call.getOrCreate();
Joining and Creating Calls
Creating Calls
To create a call, we first call the makeCall
function on the StreamVideo
class and pass it the call type and ID.
The most common call type is default
, which enables full audio and video transmission.
However, there are multiple call types (and even custom types) from which you can choose based on your use case.
Call type | Name | Short overview |
---|---|---|
default | Default | simple 1-1 calls for larger group video calling with sensible defaults |
audio_room | Audio | pre-configured for a workflow around requesting permissions in audio settings (speaking, etc.) |
livestream | Livestream | access to calls is granted to all authenticated users, useful in one-to-many settings (such as livestreaming) |
development | Development | should only be used for testing, permissions are open and everything is enabled (use carefully) |
You can read more about call types here.
Calling makeCall
returns a Call
object for us to work with. However, it neither connects nor starts transmitting data automatically.
To create and join the call, we must then invoke getOrCreate
on the returned object which creates the call if it doesn’t exist and returns the existing call if it does.
For the call ID there are a few things to note:
- You can reuse the same call multiple times.
- If you have a unique id for the call we recommend passing that as the id.
- If you don’t have a unique id you can leave it empty and we’ll generate one for you.
As an example, if you’re building a telemedicine app, calls will be connected to an appointment. Using your own appointment id as the Call ID makes it easy to find the call later.
Managing Members and Ringing Calls
You can pass certain arguments to the call.getOrCreate()
method used in the previous example:
members
: Upon creation, we can supply a list of user IDs we would like to immediately add to the call.ringing
: If ringing is set totrue
, Stream will send a VoIP notification to the users on the call, triggering the platform call screen on iOS and Android.video
: When ringing, the notification will indicate whether it’s a video call or an audio-only call, depending on whether you set thevideo
parameter to true or false.custom
: Any custom data associated with the call.team
: A team is a part of Stream Video multi-tenancy support. You can separate different groups of videos and calls using this argument.notify
If notify is set to true, Stream will send a standard non-VoIP push notification to all the users in the call.
By default, calling getOrCreate()
assigns admin
permission to each user who is supplied during creation. Depending on call permissions settings, call member may have different permissions than other users joining the call. For example, call can be configured so only members can join. See here for more information.
When call is already active you can still manage members:
final call = client.makeCall(callType: StreamCallType.defaultType(), id: 'my-call-id');
call.getOrCreate(memberIds: ['alice', 'bob']);
// grant access to more users
await call.updateCallMembers(updateMembers: [const UserInfo(id: 'charlie', role: 'call_member')]);
// or
await call.addMembers([const UserInfo(id: 'charlie', role: 'call_member')]);
// remove access from some users
await call.updateCallMembers(removeIds: ['charlie']);
// or
await call.removeMembers(['charlie']);
Call CRUD Operations
With calls, we make it easy to perform basic create, read, update, and delete (CRUD) operations on calls providing the user has sufficient permissions.
For example, once a call is created a user can call.update
the information on the call by adding custom metadata such as a name, description, or any other arbitrary Map<String, Object>
to the call before getOrCreate
is invoked.
call.update(custom: {'name': 'My first Call'});
await call.getOrCreate();
Using the update method, a variety of settings can also be applied before the call is created such as:
- Ring
- Audio
- Video
- ScreenShare
- Recording
- Transcription
- Backstage
- Geofencing
Joining Calls
To join a call that already exists, you must first know two things:
- The
callType
of the existing call - The
ID
of the existing call
Similar to the flow of creating a call, we can use makeCall
to construct a Call
class for us to perform operations on.
final call = StreamVideo.instance.makeCall(callType: StreamCallType.defaultType(), id: 'My-existing-call-ID');
await call.getOrCreate();
Next, with our class instantiated, we can connect to the call and SFU by invoking join
.
await call.join();
Unlike the call creation flow and functions, the user must have sufficient permissions to join the call or a VideoError
will be returned. All users connected via the join()
function have the permission type of user
by default and are limited in the actions they can perform.
Backstage setup
The backstage feature makes it easy to build a use-case where you and your co-hosts can setup your camera before going live. Only after you call call.goLive()
the regular users be allowed to join the livestream.
However, you can also specify a joinAheadTimeSeconds
, which allows regular users to join the livestream before it is live, in the specified join time before the stream starts.
Here’s an example how to do that:
final call = StreamVideo.instance.makeCall(callType: StreamCallType.livestream(), id: 'my-call-id');
const backstageSetting = StreamBackstageSettings(
enabled: true,
joinAheadTimeSeconds: 300,
);
await call.getOrCreate(
memberIds: ['alice', 'bob'],
startsAt: DateTime.now().add(const Duration(seconds: 500)),
backstage: backstageSetting,
);
await call.join();
In the code snippet above, we are creating a call that starts 500 seconds from now. We are also enabling backstage mode, with a joinAheadTimeSeconds
of 300 seconds. That means that regular users will be able to join the call 200 seconds from now.
Restricting access
You can restrict access to a call by tweaking the Call Type permissions and roles. A typical use case is to restrict access to a call to a specific set of users -> call members.
Step 1: Set up the roles and permissions
On our dashboard, navigate to the Video & Audio -> Roles & Permissions section and select the appropriate role and scope. In this example, we will use my-call-type
scope.
By default, all users unless specified otherwise, have the user
role.
We start by removing the JoinCall
permission from the user
role for the my-call-type
scope. It will prevent regular users from joining a call of this type.
Next, let’s ensure that the call_member
role has the JoinCall
permission for the my-call-type
scope. It will allow users with the call_member
role to join a call of this type.
Once this is set, we can proceed with setting up a call instance.