Contact Support | System Status
Page Contents

    Generic Stream Concurrency

    This document describes how to limit stream concurrency to end-viewers with a heartbeat mechanism and without DRM.

    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, and it’s an alternative to stream concurrency with DRM, which is an alternative solution.

    When to use GSC

    Brightcove offers two solutions for managing concurrency:

    The table below offers a comparison of the two to help you decide which is more appropriate for your situation.

    Stream Concurrency Solutions
    Generic Stream Concurrency Stream Concurrency with DRM
    Advantages:
    • Does not require DRM
    • Active stream sessions can be listed via the API
    Advantages
    • There is no way to disable it from the client-side
    • Renewal mechanism is transparent on custom implementations
    • More secure
    Disadvantages
    • Heartbeat runs from client-side
    • Custom implementations require integrating the heartbeat mechanism
    Disadvantages
    • It requires many DRM licenses
    • no way to list all active sessions of a specific user

    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 of the heartbeat defines how often the player makes mid-stream checks to see if the conditions for playback are still met. By default the frequency is set to 1 minute, but this can be changed.

    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

    1. If you wish to change the heartbeat frequency from the default (1 minute) contact Support.
    2. Create a JWT for playback restrictions. (Only the climit, sid, and uid claims are required.)
      • You must set the concurrency limit (climit) and viewer identifier (uid)
      • You must also include a correlator identifier (sid) that defines the streaming locations for a viewer. The correlator identifier is typically a device name, possibly combined with a client app name, such as:
        • Chrome MAC (Cadmium) HTML 5
        • Apple iPad 7th Gen 10.2 (Wi-Fi)
        • Apple Apple TV TBD Apple TV
        • Android DefaultWidevineL3Phone Android Phone
        • Firefox MAC (Cadmium) HTML 5
        • Google Chromecast streaming stick
    3. Register the public key for the JWT with Brightcove. See Using Authentication APIs for details.
    4. 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"
    }
    }

    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 to connect to the server, it will re-try three times. If it still cannot connect, playback will continue, but concurrency limits will no longer be enforced.

    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('');
    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('');
      
      // 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);

    For more details, see the Generic Stream Concurrency (GSC) with the Native SDK for Android document.

    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 code translate="No">/code>t

    The basic logic your player/app needs to perform is shown in the diagram below:

    Logic for Concurrency
    Logic for Concurrency

    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: POST

    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


    Page last updated on 22 Nov 2021