final call = StreamVideo.instance.makeCall(
callType: StreamCallType.liveStream(),
id: 'your_call_id',
);
await call.getOrCreate(
members: [
MemberRequest(
userId: StreamVideo.instance.currentUser.id,
role: 'host',
),
],
);
await call.join();Broadcasting
The Stream Video Flutter SDK has support for HLS broadcasting. This allows you to broadcast a call over HLS, which can then be watched using any HLS-compatible player. You can also use RTMP to ingest streams from external tools like OBS.
Call type for broadcasting
Among the pre-built call types, the livestream type is best suited for broadcasting events. When a livestream call is created, it is set to backstage mode by default. Backstage mode lets hosts set up cameras and equipment before going live.
Start and stop HLS broadcasting
You can start HLS broadcasting by calling startHLS() on the Call object. The user must have the start-broadcast-call capability to perform this action.
final result = await call.startHLS();
if (result.isSuccess) {
final hlsUrl = result.getDataOrNull();
// hlsUrl contains the HLS playlist URL
}To stop broadcasting:
await call.stopHLS();After a few seconds of setup, broadcasting will start and the call state will be updated — the isBroadcasting flag will become true.
Starting HLS when going live
You can start HLS broadcasting automatically when the call transitions out of backstage mode by passing startHls: true to goLive():
await call.goLive(startHls: true);This is a convenient way to ensure HLS broadcasting starts alongside the WebRTC stream.
Observing the broadcasting state
You can observe the isBroadcasting property from the call state to update your UI:
PartialCallStateBuilder(
call: call,
selector: (state) => state.isBroadcasting,
builder: (context, isBroadcasting) {
return Text(isBroadcasting ? 'Broadcasting' : 'Not broadcasting');
},
);Here is an example of a toggle button that starts and stops HLS broadcasting:
PartialCallStateBuilder(
call: call,
selector: (state) => state.isBroadcasting,
builder: (context, isBroadcasting) {
return ElevatedButton(
onPressed: () async {
if (isBroadcasting) {
await call.stopHLS();
} else {
await call.startHLS();
}
},
child: Text(isBroadcasting ? 'Stop Broadcasting' : 'Start Broadcasting'),
);
},
);Listening to broadcasting events
You can listen to broadcasting-related events via the callEvents stream on the Call object:
call.callEvents.on<StreamCallBroadcastingStartedEvent>((event) {
final hlsPlaylistUrl = event.hlsPlaylistUrl;
// Broadcasting has started, use hlsPlaylistUrl to watch the stream
});
call.callEvents.on<StreamCallBroadcastingStoppedEvent>((event) {
// Broadcasting has stopped
});
call.callEvents.on<StreamCallBroadcastingFailedEvent>((event) {
// Broadcasting failed
});See more about subscribing to events on the events page.
Retrieving the broadcast URL
The HLS playlist URL can be retrieved from the call state after broadcasting has started:
final hlsUrl = call.state.value.egress.hlsPlaylistUrl;This URL can be shared with viewers to watch the broadcast in any HLS-compatible player.
Displaying an HLS stream
To play an HLS stream in your Flutter app, use a video player package that supports HLS playback, such as video_player or media_kit.
Using video_player
import 'package:video_player/video_player.dart';
final controller = VideoPlayerController.networkUrl(
Uri.parse(hlsUrl),
);
await controller.initialize();
controller.play();Then use the VideoPlayer widget to display the video:
AspectRatio(
aspectRatio: controller.value.aspectRatio,
child: VideoPlayer(controller),
);Using media_kit
import 'package:media_kit/media_kit.dart';
import 'package:media_kit_video/media_kit_video.dart';
final player = Player();
final videoController = VideoController(player);
player.open(Media(hlsUrl));Then use the Video widget to display the video:
Video(controller: videoController);Remember to dispose the player when you no longer need it to free system resources.
RTMP-In
You can use RTMP streams as input for a call. This is useful for integrating professional broadcasting tools like OBS.
The RTMP address is available from the call state:
final rtmpAddress = call.state.value.rtmpIngress;The streaming key for OBS and other tools uses the format: apiKey/userToken.
Configuring OBS
- Open OBS and go to Settings > Stream
- Select Custom as the service
- Set the Server to the
rtmpAddressfrom the call state - Set the Stream Key to
your_api_key/user_token - Click Start Streaming in OBS
The RTMP stream will now show up in the call just like a regular video participant.
A user corresponding to the token provided to OBS will appear as a participant in the call. Consider creating a dedicated user for OBS streaming.
Error handling
Broadcasting depends on many factors, including network conditions. Wrap your broadcasting actions with proper error handling:
final result = await call.startHLS();
if (result.isFailure) {
// Show error to the user
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Failed to start broadcasting')),
);
}Permissions
Before a user can start or stop broadcasting, they must have the corresponding capabilities:
start-broadcast-callto start broadcastingstop-broadcast-callto stop broadcasting
Permissions for each role can be configured in the Stream Dashboard under Roles & Permissions for your call type.
final hasPermission = call.state.value.ownCapabilities.contains(
CallPermission.startBroadcastCall,
);