Introduction
Generic Stream Concurrency lets you define the number of video streams that a specific user can watch concurrently. Limiting stream concurrency helps you prevent content being stolen or illegally watched through the theft or inappropriate sharing of credentials.
This feature is part of Playback Restrictions. It is an alternative to stream concurrency with DRM.
When to use GSC
Brightcove offers two solutions for managing concurrency:
- Generic Stream Concurrency (covered in this topic)
- Stream Concurrency with DRM
The table below offers a comparison of the two to help you decide which is more appropriate for your situation.
Generic Stream Concurrency | Stream Concurrency with DRM |
---|---|
Advantages:
|
Advantages
|
Disadvantages
|
Disadvantages
|
How it works
Heartbeat
The heartbeat is a mechanism that requests on a frequency base the active sessions for a specific user, to enforce that it is a valid session through the entire playback. The heartbeat can be enabled for the Brightcove web player and the native SDK players.
The frequency is set to one minute by default, which is the minimum value. It can be changed to a higher duration, but it cannot be lowered to under one minute.
Blocking streams
When the maximum number of concurrent streams is reached and the viewer, or someone with their account credentials, tries to open an additional stream, any new stream from that user identified as a different streaming location will be blocked.
Correlator identifier
A correlator identifier is used to define viewer streaming locations. The characteristics of this identifier are:
- It should be specific enough to correlate all requests from the same Viewer. If the correlator is too generic it will bucket multiple viewers with the same viewer ID together and group them all into the same slot.
- It should be consistent across all video views for the same Viewer.
When the "correlator" is different, it will try to fill a "slot" for the viewer id, which means if that value changes during the same viewing, it will be treated as if it were a different viewer and prevent playback.
The correlator is set in the JWT using the sid
claim
Implementation
Using Brightcove web or SDK players
- If you wish to change the heartbeat frequency from the default (1 minute) contact Support.
-
Create a JWT for playback restrictions.
The following claims are required:
-
climit
- The concurrency limit claim indicates how many watchers or streams can play at the same time -
uid
- The viewer identifier is used to correlate multiple sessions to enforce Stream Concurrency -
Examples:sid
- Correlator identifier defines the streaming locations for a viewer.- Chrome MAC (Cadmium) HTML 5 - 1112223334
- Apple iPad 7th Gen 10.2 (Wi-Fi) - 2223334444
- Apple Apple TV TBD Apple TV - 3334445555
- Android DefaultWidevineL3Phone Android Phone - 1112224567
- Firefox MAC (Cadmium) HTML 5 - 1112226754
- Google Chromecast streaming stick - 1112346677
-
- Register the public key for the JWT with Brightcove. See Using Authentication APIs for details.
- Enable Generic Stream Concurrency on client players: see Implementation in players below
Sample JSON Web Token (JWT) claims
{
// account id: JWT is only valid for this account
"accid":"4590388311111",
// limit of concurrent users
"climit": 3,
// user id
"uid": "108.26.184.3_1634052241",
// correlator identifier
"sid": "Firefox MAC (Cadmium) HTML 5 - 1112346677"
}
Notes
- When the maximum number of sessions is exceeded for a viewer, a session will be stopped. It may take as long as the heartbeat frequency for the session to be stopped.
- If the client player cannot connect to the server, it will re-try three times. If it still cannot connect, playback will stop.
Implementation in players
Requirements
- Generic Stream Concurrency requires the Brightcove web player 6.63.2 or later.
- Generic Stream Concurrency requires the Brightcove iOS SDK player 6.10.1, or later.
- Generic Stream Concurrency requires the Brightcove Android SDK player 6.17.2 or later.
Brightcove web player
Generic stream concurrency in the Brightcove Player can be enabled using the video_cloud.stream_concurrency
player configuration.
At this time, there is no dedicated UI for this feature in Studio, so the JSON editor must be used. The configuration will look something like this:
"stream_concurrency" : true
...
"video_cloud": {
"stream_concurrency": true,
"policy_key": "BCpk..."
},
"player": {
"template": {
"name": "single-video-template",
"version": "6.63.1"
}
},
...
If this key/value pair is not present in JSON or the value is false, GSC feature would not be enabled for the player.
Setting the JWT at Runtime
Similar to the EPA stream concurrency limiting feature, generic stream concurrency depends on a JSON Web Token.
Once the player is configured for generic stream concurrency, as above, the remaining step is to provide a JWT to the player at runtime. This is the same process as when using EPA:
player.catalog.setBcovAuthToken('your token');
Example
After adding a JWT token, the final step is to request data from the Playback API and load it into the player. This example demonstrates fetching a single video:
// Set the authorization token.
player.catalog.setBcovAuthToken('your token');
// Initiate a catalog request. API selection will occur each time this
// is called.
player.catalog.get({id: '1', type: 'video'}).
then(function(data) {
// When the request is complete, you must load the returned metadata
// and sources into the player.
player.catalog.load(data);
}).
catch(function(error) {
throw new Error(error);
});
iOS
To enable the Generic Stream Concurrency feature for iOS SDK, you need to enable the option streamConcurrencyEnabled
in your playbackController
.
Optionally, you can send the value for sid
. If the sid
is
empty, this value will not be sent as header.
Objective-C
self.playbackController.streamConcurrencyEnabled = YES;
// Optional. Set custom sid
self.playbackController.options ■ (?{ kBCOVAuthHeartbeatPropertyKeySessionld: G'sessionld" };
Swift
self.playbackController.streamConcurrencyEnabled ■ true
// Optional. Set custom sid
self.playbackController.options = [ kBCOVAuthHeartbeatPropertyKeySessionld: "sessionld" ]
For more details, see the Brightcove Native Player for iOS Reference.
Android
In your player Activity’s onCreate method, add this line:
brightcoveVideoView.setStreamConcurrencyEnabled(true);
In the onCreate
method add an event listener for the DID_SET_VIDEO
event, with this code to set heartbeat headers. Note that the same JWT used
to retrieve the video is used here, and should include a uid
claim (and optionally, a
sid
claim):
Map<String, String> requestHeaders = new
HashMap<>();
requestHeaders.put(ConcurrencyClient.HEARTBEAT_VIDEO_HEADER_KEY, video.getId());
requestHeaders.put(ConcurrencyClient.HEARTBEAT_ACCOUNTID_HEADER_KEY, accountId);
requestHeaders.put(BrightcoveTokenAuthorizer.BRIGHTCOVE_AUTHORIZATION_HEADER_KEY, jwtToken);
brightcoveVideoView.setStreamConcurrencyRequestHeaders(requestHeaders);
Implementation via API
This feature can be implemented via the Concurrency Service API without using the Brightcove Web Player or SDK players. See the API Reference for additional details.
The base URL for the Concurrency Service API is:
https://edge-gsc.api.brightcove.com
The authorization method is through the JWT sent in an Authorization
header:
Authorization: Bearer {token}
The basic logic your player/app needs to perform is shown in the diagram below:
The API endpoints
- Session
-
This endpoint is used to create new streaming sessions with a heartbeat for concurrency management:
/api/v1/accounts/{{account_id}}/sessions
Method:
POST
Request body:
{ "video": "the_video_id" }
- Active sessions
-
This endpoint allows you to list streaming sessions to keep track of them - mainly useful if you are
implementing logic to decide which session to stop if the concurrency limit is reached:
/api/v1/accounts/{{account_id}}/sessions
Method:
GET
- Stop sessions
-
This endpoint allows you to to stop a streaming session - you would use this if you are implementing logic to
decide which session to stop when a new playback request exceeds the concurrency limit. This endpoint is mostly
for backend use to remove sessions when completed:
/api/v1/accounts/{{account_id}}/sessions
Method:
DELETE