RTMP Streaming / Recording
Want to preserve your video call for posterity in a recording? Or live stream it out to millions of viewers on Twitch or YouTube or whatever gives you an RTMP ingest URL?
Turn on RTMP Streaming or Recording!
In 100ms, recording and streaming are usually achieved by having a bot join your room and stream what it sees and hears to a file (recording) or an RTMP ingest URL (streaming).
Types of recordings
Apart from the RTMP stream and the browser recording, there is also a serverRecording, which can be turned on for the room for.
- Server Recording
This is used for archival purposes and cannot be stopped by method calls from SDK. This can only be enabled/disabled from the dashboard. This represents that the room was set to be recorded when it was created and all sessions within it will always be recorded for archival by the server.
- Browser Recording
This is a normal recording that can be enabled/disabled using HMSSDK
method startRtmpOrRecording
with toRecord
as true
RTMP Streaming & Recording
The topics covered in this doc are:
- How to start stop streaming / recording.
- How to check the current status for streaming/recording.
- When to check the current status
Start/Stop Streaming / Recording
Let's look at the implementation for starting/stopping RTMP streaming and browser recording:
class Meeting implements HMSUpdateListener, HMSActionResultListener{ void startRtmpOrRecording({ String? meetingUrl, required bool toRecord,List<String>? rtmpUrls,double height,double width}) async { HMSResolution streamResolution = HMSResolution(height: height, width: width); HMSRecordingConfig hmsRecordingConfig = new HMSRecordingConfig( meetingUrl: meetingUrl, toRecord: toRecord, rtmpUrls: rtmpUrls,resolution: streamResolution); ///[hmsRecordingConfig]: the object of HMSRecordingConfig which we created above ///[hmsActionResultListener]: an instance of a class that implements HMSActionResultListener //Here this is an instance of a class that implements HMSActionResultListener, that is, Meeting hmsSDK.startRtmpOrRecording( hmsRecordingConfig: hmsRecordingConfig, hmsActionResultListener: this); } void stopRtmpAndRecording() { ///[hmsActionResultListener]: an instance of a class that implements HMSActionResultListener //Here this is an instance of a class that implements HMSActionResultListener, that is, Meeting hmsSDK.stopRtmpAndRecording( hmsActionResultListener: this); } void onSuccess( {HMSActionResultListenerMethod methodType = HMSActionResultListenerMethod.unknown, Map<String, dynamic>? arguments}) { switch (methodType) { ... case HMSActionResultListenerMethod.startRtmpOrRecording: //RTMP stream started successfully. We will get the update here break; case HMSActionResultListenerMethod.stopRtmpAndRecording: //RTMP stream stopped successfully break; } } void onException( {HMSActionResultListenerMethod methodType = HMSActionResultListenerMethod.unknown, Map<String, dynamic>? arguments, required HMSException hmsException}) { switch (methodType) { ... case HMSActionResultListenerMethod.startRtmpOrRecording: // Check the HMSException object for details about the error break; case HMSActionResultListenerMethod.stopRtmpAndRecording: // Check the HMSException object for details about the error break; } } }
Let's break down the implementation
To start recording, streaming or both, create an instance of HMSRecordingConfig
.
HMSRecordingConfig hmsRecordingConfig = new HMSRecordingConfig( meetingUrl: "meeting_url", toRecord: "true for enabling recording", rtmpUrls: "List of URLs", resolution: "HMSResolution object for stream resolution");
Let's understand each parameter:
-
meetingUrl: String?. The URL the 100ms bot user will open to join your room. It must allow access without any user-level interaction.
-
rtmpUrls: List<String>. If streaming is required, this has to be one or more RTMP Ingest Urls with a max limit of 3 URLs where the stream should go. If only recording, this can be an empty list.
-
Format:
rtmp://server.com/app/STREAM_KEY
-
Example:
rtmp://a.rtmp.youtube.com/live2/k0jv-329m-1y7f-ktth-ck48
- "rtmp://a.rtmp.youtube.com/live2/" - RTMP stream URL.
- "k0jv-329m-1y7f-ktth-ck48" - RTMP stream key.
-
-
toRecord: Boolean. If the recording is required, set it
true
. If the recording is not required, set false. This value does not affect streaming. -
resolution: HMSResolution. An optional value for the output resolution of the stream. For instance, the default is a landscape at 1280x720 but this could be set for a portrait mode to 720x1280 or smaller values like 480x80. The
HMSResolution
class takes Width and Height.
Key Notes
- If both
rtmpUrls
andtoRecord = true
are provided, both streaming and recording will begin. - If only
rtmpUrls
are provided, only streaming will begin. - If only
toRecord
true is provided, only recording will begin.
If either one is started, the other can't be started without stopping whatever is running.
Eg: If only streaming is started then recording can't be started unless streaming is stopped first.
If both are required, they have to be started together by providing both rtmpUrls
and toRecord = true
.
Current Room Status
The current status for the room is always reflected in the HMSRoom
object that is returned from the HMSUpdateListener
.
This can be used to show the stream or recording status on UI something similar to this:
Room recording can be in one of the state at any given time:
enum HMSRecordingState { none, starting, started, paused, resumed, stopped, failed, }
Similarly, room streaming can be in one of the state at any given time:
enum HMSStreamingState { none, starting, started, stopped, failed, }
Here are the relevant properties inside the HMSRoom
object which we can read to get the current recording/streaming status of the room namely:
hmsRtmpStreamingState
- Contains info about RTMP Streaming,state
attribute if set toHMSStreamingState.started
indicates streaming is ON currentlyhmsBrowserRecordingState
- Contains info about Browser Recording,state
attribute if set toHMSRecordingState.started
indicates browser recording is ON currentlyhmsServerRecordingState
- Contains info about Server Recording,state
attribute if set toHMSRecordingState.started
indicates server recording is ON currentlyhmshlsRecordingState
- Contains info about HLS Recording,state
attribute if set toHMSRecordingState.started
indicates HLS recording is ON currentlyhmshlsStreamingState
- Contains info about HLS Streaming,state
attribute if set toHMSStreamingState.started
indicates HLS streaming is ON currently
Each of them is an object which contains a boolean state
which lets you know the streaming or recording state in the room and error
which lets you know if there was an error.
- HMSRtmpStreamingState an instance of
HMSRtmpStreamingState
, which looks like:
class HMSRtmpStreamingState { ///[error]: Gets populated if there is some error in starting the stream ///[running]: bool value `true` indicates that RTMP streaming is running ///[startedAt]: time at which RTMP streaming was started ///[state]: Contains info about current state of RTMP streaming final HMSException? error; final bool running; DateTime? startedAt; HMSStreamingState state; HMSRtmpStreamingState({required this.error, required this.running, this.startedAt, required this.state}); }
- browserRecordingState an instance of
HMSBrowserRecordingState
, which looks like:
class HMSBrowserRecordingState { ///[error]: Gets populated if there is some error in starting the browser recording ///[running]: bool value `true` indicates that browser recording is running ///[startedAt]: time at which browser recording was started ///[initialising]: flag to identify the recording initialisation status ///[state]: Contains info about current state of browser recording final HMSException? error; final bool running; final bool initialising; DateTime? startedAt; HMSRecordingState state; HMSBrowserRecordingState({required this.error, required this.running, this.startedAt, required this.state}); }
- serverRecordingState an instance of
HMSServerRecordingState
, which looks like:
class HMSServerRecordingState { ///[error]: Gets populated if there is some error in starting the server recording ///[running]: bool value `true` indicates that server recording is running ///[startedAt]: time at which server recording was started ///[state]: Contains info about current state of server recording final HMSException? error; final bool running; DateTime? startedAt; HMSRecordingState state; HMSServerRecordingState({required this.error,required this.running, this.startedAt, required this.state}); }
- hlsRecordingState an instance of
HMSHlsRecordingState
, which looks like:
class HMSHLSRecordingState { ///[error]: Gets populated if there is some error in starting the server recording ///[running]: bool value `true` indicates that hls recording is running ///[startedAt]: time at which server recording was started ///[state]: Contains info about current state of hls recording final HMSException? error; final bool running; DateTime? startedAt; HMSRecordingState state; HMSHLSRecordingState({required this.error, required this.running, this.startedAt, required this.state}); }
- hlsStreamingState an instance of
HMSHlsStreamingState
, which looks like:
class HMSHLSStreamingState { ///[running]: bool value `true` indicates that hls recording is running ///[variants] contains the information about HLS Streaming Url, meeting Url, metadata and startedAt. ///[state]: Contains info about current state of hls streaming final bool running; final List<HMSHLSVariant?> variants; HMSStreamingState state; HMSHLSStreamingState({required this.running, required this.variants, required this.state}); }
When to check for room status
The room status should be checked in three places:
onJoin
callback ofHMSUpdateListener
onRoomUpdate
callback ofHMSUpdateListener
- When
hmsSDK.startRtmpOrRecording()
is called - When
hmsSDK.stopRtmpAndRecording()
is called.
- In the
onJoin(room: HMSRoom)
&onRoomUpdate({required HMSRoom room, required HMSRoomUpdate update})
callback inHMSUpdateListener
The properties mentioned above will be on theHMSRoom
object. - Whenever either of the start or stop recording functions is called, their success or error callbacks are called, the values of the streaming and recording will be updated on the room object returned in
onRoomUpdate
. So update the instance of room in your application at that time.