Streams
Red5 Pro Streams
- 1 About Red5 Pro streams
- 2 Red5 Pro stream action callbacks in application adapter
- 3 Fetching all the live stream names in an application
- 4 Access a live stream object in a red5pro scope
- 5. Record a live stream
- 6 Stream Statistics
- 7 Terminate a stream
- 8 Securing publish & playback
1. About Red5 Pro streams
Streams are the core objects in Red5 Pro that represent audio/video operations in the context of the media server. Red5 Pro stream objects encapsulate information about client/server streams for live/video-on-demand content.
At its core, every Red5 Pro stream is a IStream object.
-
A generic broadcaster stream extends from an
IStream
and is represented by aIBroadcastStream
. -
A generic subscriber stream extends from the
IStream
object and is represented by aISubscriberStream
You can explore the APIs in details by inspecting each IStream
interface and its implementation individually, starting at the IStream interface.
2. Red5 Pro stream action callbacks in application adapter
Every Red5 Pro application extends the MultiThreadedApplicationAdapter and has access to specific callback methods for stream events. We can override these methods in our own application class to handle the callbacks ourselves.
Following is a snippet from a sample application adapter class that extends the MultiThreadedApplicationAdapter:
@Override
public void streamBroadcastClose(IBroadcastStream stream) {
log.info("Stream broadcast close {}", stream);
}
@Override
public void streamBroadcastStart(IBroadcastStream stream) {
log.info("Stream broadcast start {}", stream);
}
@Override
public void streamRecordStart(IBroadcastStream stream) {
log.info("Stream record start {}", stream);
}
@Override
public void streamRecordStop(IBroadcastStream stream) {
log.info("Stream record stop {}", stream);
}
@Override
public void streamSubscriberStart(ISubscriberStream stream) {
log.info("Stream subscribe start {}", stream);
}
@Override
public void streamSubscriberClose(ISubscriberStream stream) {
log.info("Stream subscribe close {}", stream);
}
streamBroadcastStart
: Invoked when a broadcast starts
streamBroadcastClose
: Invoked when a broadcast stops
streamRecordStart
: Invoked when the recording of a broadcast stream starts
streamRecordStop
: Invoked when the recording of a broadcast stream stops
streamSubscriberStart
: Invoked when a subscriber requests a stream
streamSubscriberClose
: Invoked when a subscriber stops subscribing
For detailed information on these callbacks and more, check out the MultiThreadedApplicationAdapter documentation You can access the complete source code of the snippet shown above on GitHub here.
3. Fetching all the live stream names in an application
Often when developing a live streaming application you may want to fetch the list of active live streams in your application. The MultiThreadedApplicationAdapter documentation provides a method specifically for this. The snippet below shows how you can use the getBroadcastStreamNames method to list out live streams.
public List<String> getLiveStreams(String appname, IScope scope) throws Exception {
List<String> streams = null;
try
{
MultiThreadedApplicationAdapter adapter = (MultiThreadedApplicationAdapter) application.getHandler();
Set<String> broadcastStreams = adapter.getBroadcastStreamNames(scope);
Iterator<String> iter = broadcastStreams.iterator();
streams = new ArrayList<String>();
while (iter.hasNext()) {
String name = iter.next();
IProStream stream = (IProStream ) adapter.getBroadcastStream(application, name);
IConnection conn = stream.getConnection();
if (conn != null && conn.isConnected())
streams.add(name);
}
return streams;
}
catch (Exception e)
{
log.error("An unexpected error occurred." + e.getMessage());
throw e;
}
}
The important line to notice above is this one:
Set<String> broadcastStreams = adapter.getBroadcastStreamNames(scope);
If you are looking for live streams at the application level then scope
would be your APPLICATION
scope or if you are looking for streams in a sub-scope, scope
should refer to a ROOM
scope.
Exception
will be thrown if thescope
is not found on the server.
It is recommended that you read through Red5 Pro scopes document for more information on scopes.
4. Access a live stream object in a Red5 Pro scope
Once you have a list of live stream names, you may want to reference the stream object itself to operate on it using the Red5 Pro API. Similar to the stream list look up, the use of scopes applies here as well. Following is a snippet showing how to fetch a reference to a stream as a broadcast stream.
If you look back at our getLiveStreams
method earlier, you will see how we resolve a ClientBroadcastStream
using the stream name. The MultiThreadedApplicationAdapter documentation provides a method called getBroadcastStream
to resolve the reference object of a live stream.
Example:
IProStream stream = (IProStream) adapter.getBroadcastStream(scope, name);
The method requires the stream name and the scope
, where to look for the stream. If your stream is at the application level, then scope
should refer to your APPLICATION
scope else if your stream exists in a subscope then scope
should refer to the appropriate ROOM
scope.
The
getBroadcastStream
returns aIBroadcastStream
object, which can be casted to aIProStream
. It is recommended that you read through Red5 Pro scopes document for more information on scopes.
5. Record a live stream
Having reference of the stream object means we can now operate on it. You can take a look at the IClientBroadcastStream class to see the various method available to us. The IProStream
interface extends IClientBroadcastStream
and a few other interfaces from Red5 open source allowing us to use the same methods by name but referencing the Red5 pro implementation of streams at runtime.
NOTE: The
ClientBroadcastStream
class orIClientBroadcastStream
(from Red5 open source) should not be used with Red5 pro streams. TheIProStream
interface, which is an extension of Red5 open source interfaces specifically for Red5 pro streams provides access to Red5 pro implementation of the stream methods. To use theIProStream
interface, make sure to add the red5pro-commons dependency to your project.
5.1. Start Record
One of the most common operations on broadcast streams is live recording
, capturing the broadcast stream to a file. In the previous section, we type-casted the IBroadcastStream
object to IProStream
.
To record a live stream we use the saveas
method through the IProStream interface.
Following is a code snippet showing how to record a live broadcast stream to disk when the broadcast starts.
@Override
public void streamBroadcastStart(IBroadcastStream stream)
{
try
{
IProStream bStream = (IProStream ) stream;
if(!bStream.isRecording()) {
bStream.saveAs(bStream.getPublishedName(), false);
}
}
catch (Exception e) {
log.error("Error starting stream recording {} ", e);
}
}
The streamBroadcastStart
callback method is invoked when the broadcast starts. At this point, the callback receives a reference to the stream as an IBroadcastStream
object. We then explicitly cast it to an IProStream
object. Once the object is cast to an IProStream
, we get access to a range of stream methods through the IProStream
interface.
We use the isRecording()
method to check whether the stream is already recording or not. If not then we start recording the stream using the saveas
method.
The saveas
method accepts two parameters, the filename
to use for recording and a Boolean
parameters indicating whether the recording is to be appended
or overwritten
if the file already exists.
5.2 Stop Record
Normally recording automatically terminates when the stream is closed (client closes connection/stream). However, if you wish to stop the recording manually, you can use the stopRecording
method through the IProStream
interface.
public void stopRecording(IBroadcastStream stream)
{
try
{
IProStream bStream = (IProStream ) stream;
if(bStream.isRecording()) {
bStream.stopRecording();
}
}
catch (Exception e) {
log.error("Error stopping stream recording {} ", e);
}
}
6. Stream Statistics
A Red5 Pro broadcast stream object provides statistics information through the getStatistics() method of the IClientBroadcastStream
interface which returns a IClientBroadcastStreamStatistics
. Use the extended IProStream
interface instead of IClientBroadcastStream
to access the getStatistics
method.
Example :
IProStream bStream = (IProStream ) stream;
IClientBroadcastStreamStatistics stats = broadcastStream.getStatistics();
To obtain the
IClientBroadcastStreamStatistics
object from a broadcast stream it should be cast to anIProStream
object.
Check out the stream-statistics-demo example on GitHub for more information on how to fetch live stream statistics.
7. Terminate a stream
If you wish to close a Red5 Pro stream from the server side, you can use the close()
method of the IStream
interface. Every stream object in Red5 is an IStream
object and hence implements the close
method.
Example:
@Override
public void streamBroadcastStart(IBroadcastStream stream) {
stream.close();
}
In the above snippet, we close a broadcast stream as soon as the publisher starts publishing. The streamBroadcastStart
is invoked when the broadcast starts. then we call the close
method on the IBroadcastStream
object received through the streamBroadcastStart
method to close it.
8. Securing publish & playback
The Red5 Pro framework provides a simple yet sturdy security mechanism for protection of publish & playback streams. In this section, we shall see how we can prevent illegal access to Red5 pro streams using the stream security features of Red5.
Red5 provides two security interfaces – IStreamPublishSecurity
& IStreamPlaybackSecurity
in its API, which simplify the process of controlling access to streams. The IStreamPublishSecurity
is used to secure access to stream publishing whereas IStreamPlaybackSecurity
is used to secure stream subscription.
Publisher security
To add publisher security, you need to create a implementation of IStreamPublishSecurity
and register it with your application adapter using the registerStreamPublishSecurity method.
An application adapter can have multiple IStreamPublishSecurity implementations registered with it. When you have multiple IStreamPublishSecurity implementations, even a single rejection (returning false) will override the results of other implementations.
Let us see how the IStreamPublishSecurity
implementation works.
When you create an implementation of the IStreamPublishSecurity
interface you must also implement the isPublishAllowed method.
@Override
public boolean isPublishAllowed(IScope scope, String name, String mode)
{
return true;
}
This method hooks us to the flow of the publisher session initialization event chain. Whenever a client tries to publish
a stream, this method gets invoked. The method returns a boolean value. Returning a true
allows the session initialization chain to continue whereas returning a false
breaks the chain and causes the publish request to be rejected.
The method provides three parameters which can be used for authorizing/rejecting the publish request:
scope
: The scope (location) in the application where the stream is going to be published to.name
: Name of the streammode
: The publish mode of the stream. Publish mode can be'live
orrecord
orappend
.
You can check out the complete example demonstrating publish security on github.
Subscriber security
To add subscriber security, you need to create an implementation of IStreamPlaybackSecurity and register it with your application adapter using the registerStreamPlaybackSecurity method.
When you have multiple IStreamPlaybackSecurity implementations, even a single rejection (returning false) will override the results of other implementations.
Let us see how the IStreamPlaybackSecurity
implementation works.
When you create an implementation of the IStreamPlaybackSecurity
interface you must implement the isPlaybackAllowed method.
@Override
public boolean isPlaybackAllowed(IScope scope, String name, int start, int length, boolean flushPlaylist)
{
return false;
}
This method hooks us to the flow of the subscribe session initialization event chain. Whenever a client tries to subscribe
to a stream, this method gets invoked. The method returns a boolean value. Returning a true
allows the session initialization chain to continue whereas returning a false
breaks the chain and causes the subscribe request to be rejected.
The method provides five parameters which can be used for authorizing/rejecting the subscribe request:
scope
: The scope (location) in the application where the stream is going to be subscribed from.name
: Name of the streamstart
: Requested start position for playback (not applicable to live streams)*length
: Requested stream duration for playback (not applicable to live streams)flushPlaylist
: Flush the playlist
You can check out the complete example demonstrating playback security on github.
Suggested Reading: