# 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](/video/docs/flutter/guides/call-types/) 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.

```dart
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();
```

## 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.

```dart
final result = await call.startHLS();

if (result.isSuccess) {
  final hlsUrl = result.getDataOrNull();
  // hlsUrl contains the HLS playlist URL
}
```

To stop broadcasting:

```dart
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()`:

```dart
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:

```dart
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:

```dart
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:

```dart
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](/video/docs/flutter/guides/call-events/) page.

## Retrieving the broadcast URL

The HLS playlist URL can be retrieved from the call state after broadcasting has started:

```dart
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](https://pub.dev/packages/video_player) or [media_kit](https://pub.dev/packages/media_kit).

### Using `video_player`

```dart
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:

```dart
AspectRatio(
  aspectRatio: controller.value.aspectRatio,
  child: VideoPlayer(controller),
);
```

### Using `media_kit`

```dart
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:

```dart
Video(controller: videoController);
```

<admonition type="tip">

Remember to dispose the player when you no longer need it to free system resources.

</admonition>

## RTMP-In

You can use RTMP streams as input for a call. This is useful for integrating professional broadcasting tools like [OBS](https://obsproject.com/).

The RTMP address is available from the call state:

```dart
final rtmpAddress = call.state.value.rtmpIngress;
```

The streaming key for OBS and other tools uses the format: `apiKey/userToken`.

### Configuring OBS

1. Open OBS and go to **Settings > Stream**
2. Select **Custom** as the service
3. Set the **Server** to the `rtmpAddress` from the call state
4. Set the **Stream Key** to `your_api_key/user_token`
5. Click **Start Streaming** in OBS

The RTMP stream will now show up in the call just like a regular video participant.

<admonition type="note">

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.

</admonition>

## Error handling

Broadcasting depends on many factors, including network conditions. Wrap your broadcasting actions with proper error handling:

```dart
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-call` to start broadcasting
- `stop-broadcast-call` to stop broadcasting

Permissions for each role can be configured in the [Stream Dashboard](https://dashboard.getstream.io/) under Roles & Permissions for your call type.

```dart
final hasPermission = call.state.value.ownCapabilities.contains(
  CallPermission.startBroadcastCall,
);
```


---

This page was last updated at 2026-05-13T13:39:06.572Z.

For the most recent version of this documentation, visit [https://getstream.io/video/docs/flutter/advanced/broadcasting/](https://getstream.io/video/docs/flutter/advanced/broadcasting/).