Live API: Notifications

Product(s)
Live
Role(s)
API Developer
Topic(s)
Live Streaming
API(s)
Live API
Type
Support Doc

This topic show how to set up notifications for Live API jobs.

Introduction

The Brightcove Live system sends notifications of various events. You can set up listeners for notifications to trigger further actions. The listener(s) can be written in any server-side language you use, and they would look for incoming POST requests, parse the JSON request body, and then take whatever action you want. Below we will see how you can request notifications.

Requesting notifications

You can request notifications by including one or more notifications fields in the outputs your Create Job request.

The value of notifications is an array of notification destination objects. You can use a simple string with a url: "http://httpbin.org/post", or you can use an object with following options: {"url": "http://httpbin.org/post", "credentials": "reference_to_your_credentials"}. A notification will be sent to the destination you specify when the output changes its state. If you apply this parameter to a VOD output the notifications will only be related to that VOD job, not to the live job.

Here is an example

{
    "live_stream": true,
    "region": "us-west-2",
    "reconnect_time": 20,
    "notifications": [
      {"url": "http://httpbin.org/post/URLA",
       "credentials": "reference_to_your_credentials",
       "event": "first_segment_uploaded"},
      {"url": "http://httpbin.org/post/URLB",
      "credentials": "reference_to_your_credentials",
      "event": "state_changed"}
  	],
    "outputs": [
    {
        "label": "hls360p",
        "live_stream": true,
        "height": 360,
        "video_bitrate": 650,
        "segment_seconds": 6
    },
    {
        "url":"s3://YOURBUCKET/path/filename.mp4",
        "credentials": "accConfiguredCredsAWSIdSecret",
        "notifications":    [
        {
            "url": "http://httpbin.org/post?vodStateChange"
        },
        {
            "url": "http://httpbin.org/post?vodFinished",
            "event": "output_finished"
        }
        ]
    }]
}

Retry strategy

In the event of a failed request to send a notification, the default retry strategy is to retry 50 times with an exponential delay between attempts.

max_retry_times = 50
delay_delta_s = 5
next_retry = now_s + retry_count * delay_delta_s

Events

Below are the events of a job lifecycle you can listen for. Note that the event scope is per job, so the event lifecycle for a live job would be separate from the lifecycle for a VOD clipping job based on the same live stream.

  • state_changed
  • first_segment_uploaded
  • output_finished

The state_changed will notify on the following states described in the table below

Live Job States
State Description
JOB States (reported in notifications as state)
error An error has occurred; the job will not be processed.
standby (Only applicable to Static Entry Point [SEP] jobs.) The job is allocated and ready for activation.
waiting The job has been assigned to a streaming worker and ready for the encoder to connect.
processing The encoder is connected and the job is available for playback.
disconnected The encoder has disconnected and the streaming worker is waiting for a reconnection.
cancelling The job has been cancelled and the worker is stopping the job and will NOT process any pending VOD outputs.
finishing The encoder has been disconnected for more than reconnect_time, and streaming worker is stopping the jobs and creating any associated VOD outputs.
cancelled The job has been cancelled successfully.
finished The job has finished successfully.
failed The job has stopped as a result of a system error.
VOD JOB States (reported in notifications as jvod_state)
error An error has occurred; the job will not be processed.
waiting The job waiting for processing.
waiting_finish_live The job waiting for the Live Job to finish (if the clip depends on that).
processing The clip is being processed.
creating_asset A VOD asset is being created.
cancelling The job has been cancelled and the worker is stopping the job and will NOT process any pending VOD outputs.
cancelled The job has been cancelled successfully.
finished The job has finished successfully.
failed The job has stopped as a result of a system error.
SSAI States (reported in notifications as ssai_state)
none The job is not an SSAI job.
waiting_input The streaming worker is waiting for the encoder to connect and provide the stream input information.
start_transcoding The encoder has connected and the SSAI slate has been queued for transcoding based on the stream input data and outputs data.
transcoding The slate is being transcoded.
error The slate could not be downloaded or transcoded.
ready The slate has been generated and the job is ready for SSAI playback.
SEP States (reported in notifications as sep_state)
none The job is not an SEP job.
ready The entry point has been activated and ready for the encoder to connect.
pending_activation The entry point has been queued for streaming worker assignment.
activation_in_progress The entry point is updating to route connections to the streaming worker.
pending_deactivation The entry point has been queued for cleanup from the streaming worker.
deactivation_in_progress The entry point is disconnecting from the streaming worker.
cancelled The entry point has been cancelled.
finished The entry point has completed successfully.

Sample notifications

Live stream notification

Here is a sample notification for a state_changed event for a live job:

{
    "outputs": [
        {
            "rfc_6381_video_codec": null,
            "finished_at": "2017-10-19T20:08:11.115Z",
            "segment_seconds": 4,
            "created_at": "2017-10-19T19:47:04.534Z",
            "privacy": false,
            "md5_checksum": null,
            "audio_codec": "AAC",
            "error_class": null,
            "updated_at": "2017-10-19T20:08:11.115Z",
            "video_bitrate_in_kbps": 2150.4,
            "id": "0-621669558be84a7da4ff20bccb9a6a1a",
            "state": "cancelled",
            "playback_url": "http:\/\/bcovlive-a.akamaihd.net\/621669558be84a7da4ff20bccb9a6a1a\/us-west-2\/NA\/profile_0\/chunklist.m3u8",
            "duration_in_ms": 1156873,
            "file_size_bytes": null,
            "height": 720,
            "playback_url_dvr": "http:\/\/bcovlive-a.akamaihd.net\/621669558be84a7da4ff20bccb9a6a1a\/us-west-2\/NA\/profile_0\/chunklist_dvr.m3u8",
            "error_message": null,
            "video_codec": "H.264",
            "audio_bitrate_in_kbps": 196.608,
            "fragment_duration_in_ms": null,
            "test": false,
            "playback_url_vod": "http:\/\/bcovlive-a.akamaihd.net\/621669558be84a7da4ff20bccb9a6a1a\/us-west-2\/NA\/profile_0\/chunklist_vod.m3u8",
            "total_bitrate_in_kbps": 2347.008,
            "format": null,
            "label": "hls720p",
            "frame_rate": null,
            "video_codec_profile": "high",
            "keyframe_interval": 60,
            "keyframe_interval_follow_source": false,
            "live_stream": true,
            "channels": null,
            "playback_added_cdns": [

            ],
            "width": 1280,
            "rfc_6381_audio_codec": null,
            "audio_sample_rate": null
        },
        {
            "rfc_6381_video_codec": null,
            "finished_at": "2017-10-19T20:08:11.115Z",
            "segment_seconds": 4,
            "created_at": "2017-10-19T19:47:04.534Z",
            "privacy": false,
            "md5_checksum": null,
            "audio_codec": "AAC",
            "error_class": null,
            "updated_at": "2017-10-19T20:08:11.115Z",
            "video_bitrate_in_kbps": 1536,
            "id": "1-621669558be84a7da4ff20bccb9a6a1a",
            "state": "cancelled",
            "playback_url": "http:\/\/bcovlive-a.akamaihd.net\/621669558be84a7da4ff20bccb9a6a1a\/us-west-2\/NA\/profile_1\/chunklist.m3u8",
            "duration_in_ms": 1156873,
            "file_size_bytes": null,
            "height": 540,
            "playback_url_dvr": "http:\/\/bcovlive-a.akamaihd.net\/621669558be84a7da4ff20bccb9a6a1a\/us-west-2\/NA\/profile_1\/chunklist_dvr.m3u8",
            "error_message": null,
            "video_codec": "H.264",
            "audio_bitrate_in_kbps": 196.608,
            "fragment_duration_in_ms": null,
            "test": false,
            "playback_url_vod": "http:\/\/bcovlive-a.akamaihd.net\/621669558be84a7da4ff20bccb9a6a1a\/us-west-2\/NA\/profile_1\/chunklist_vod.m3u8",
            "total_bitrate_in_kbps": 1732.608,
            "format": null,
            "label": "hls540p",
            "frame_rate": null,
            "video_codec_profile": "main",
            "keyframe_interval": 60,
            "keyframe_interval_follow_source": false,
            "live_stream": true,
            "channels": null,
            "playback_added_cdns": [

            ],
            "width": 960,
            "rfc_6381_audio_codec": null,
            "audio_sample_rate": null
        },
        {
            "rfc_6381_video_codec": null,
            "finished_at": "2017-10-19T20:08:11.115Z",
            "segment_seconds": 4,
            "created_at": "2017-10-19T19:47:04.534Z",
            "privacy": false,
            "md5_checksum": null,
            "audio_codec": "AAC",
            "error_class": null,
            "updated_at": "2017-10-19T20:08:11.115Z",
            "video_bitrate_in_kbps": 819.2,
            "id": "2-621669558be84a7da4ff20bccb9a6a1a",
            "state": "cancelled",
            "playback_url": "http:\/\/bcovlive-a.akamaihd.net\/621669558be84a7da4ff20bccb9a6a1a\/us-west-2\/NA\/profile_2\/chunklist.m3u8",
            "duration_in_ms": 1156873,
            "file_size_bytes": null,
            "height": 360,
            "playback_url_dvr": "http:\/\/bcovlive-a.akamaihd.net\/621669558be84a7da4ff20bccb9a6a1a\/us-west-2\/NA\/profile_2\/chunklist_dvr.m3u8",
            "error_message": null,
            "video_codec": "H.264",
            "audio_bitrate_in_kbps": 196.608,
            "fragment_duration_in_ms": null,
            "test": false,
            "playback_url_vod": "http:\/\/bcovlive-a.akamaihd.net\/621669558be84a7da4ff20bccb9a6a1a\/us-west-2\/NA\/profile_2\/chunklist_vod.m3u8",
            "total_bitrate_in_kbps": 1015.808,
            "format": null,
            "label": "hls360p",
            "frame_rate": null,
            "video_codec_profile": "main",
            "keyframe_interval": 60,
            "keyframe_interval_follow_source": false,
            "live_stream": true,
            "channels": null,
            "playback_added_cdns": [

            ],
            "width": 640,
            "rfc_6381_audio_codec": null,
            "audio_sample_rate": null
        },
        {
            "playlist_type": "defaultS3",
            "dvr_filename": "playlist_dvr.m3u8",
            "filename": "playlist.m3u8",
            "playback_url": "http:\/\/bcovlive-a.akamaihd.net\/621669558be84a7da4ff20bccb9a6a1a\/us-west-2\/NA\/playlist.m3u8",
            "type": "playlist",
            "playback_url_dvr": "http:\/\/bcovlive-a.akamaihd.net\/621669558be84a7da4ff20bccb9a6a1a\/us-west-2\/NA\/playlist_dvr.m3u8"
        }
    ],
    "input": {
        "finished_at": "2017-10-19T20:08:11.115Z",
        "created_at": "2017-10-19T19:47:04.534Z",
        "privacy": false,
        "md5_checksum": null,
        "audio_codec": null,
        "error_class": null,
        "updated_at": "2017-10-19T20:08:11.115Z",
        "video_bitrate_in_kbps": null,
        "id": "input-621669558be84a7da4ff20bccb9a6a1a",
        "state": "cancelled",
        "duration_in_ms": 1156873,
        "file_size_bytes": null,
        "audio_tracks": null,
        "height": null,
        "error_message": null,
        "video_codec": null,
        "audio_bitrate_in_kbps": null,
        "test": false,
        "total_bitrate_in_kbps": null,
        "format": null,
        "frame_rate": null,
        "url": null,
        "channels": null,
        "width": null,
        "audio_sample_rate": null
    },
    "event": "state_changed",
    "job": {
        "event_length": 0,
        "static": false,
        "finished_at": "2017-10-19T20:08:11.115Z",
        "test": false,
        "submitted_at": "2017-10-19T19:47:04.534Z",
        "created_at": "2017-10-19T19:47:04.534Z",
        "privacy": false,
        "out_worker_bytes_rate": 0,
        "ad_insertion": false,
        "metadata_passthrough": false,
        "live_stream": true,
        "out_worker_bytes": 147114065,
        "live_dvr_sliding_window_duration_ms": 57600000,
        "updated_at": "2017-10-19T20:08:11.115Z",
        "encryption": [

        ],
        "live_dvr_sliding_window_duration_ms": 57600000,
        "ssai_state": "none",
        "id": "621669558be84a7da4ff20bccb9a6a1a",
        "state": "cancelled",
        "playback_url": "http:\/\/bcovlive-a.akamaihd.net\/621669558be84a7da4ff20bccb9a6a1a\/us-west-2\/NA\/playlist.m3u8",
        "region": "us-west-2",
        "reconnect_time": 1800,
        "playback_url_dvr": "http:\/\/bcovlive-a.akamaihd.net\/621669558be84a7da4ff20bccb9a6a1a\/us-west-2\/NA\/playlist_dvr.m3u8"
    }
}

Clipping to S3 sample

Below is a sample state_changed event for creating a clip and sending it to an S3 bucket. Note that it includes the S3 address of the clip as jvod_url.

{
    "jvod_id": "b750cce9e21a4cc894c4507208495b0c",
    "jvod_url": "s3:\/\/learning-services-media.brightcove.com\/test_dur60.mp4",
    "jvod_created_at": 1517520650785,
    "jvod_duration_s": 30,
    "jvod_cancelling_flag": false,
    "label": "last_30",
    "jvod_reported_duration_s": null,
    "jvod_finished_at": 0,
    "jvod_type": "s3",
    "account_id": "a95ac581551b4478b27910e5675db1f8",
    "jvod_worker_id": "b55b6fec738e4d2788544d3233b5ecf6",
    "user_id": "c2691d4d039040be96c190a949d754a7",
    "job_id": "7005c6e07bc24ca7b69b6b9d24052720",
    "jvod_last_state_change_at": 1517520652312,
    "jvod_region": "us-west-2",
    "cloud_id": "301c91a5d9254b5d944b108c355f12be",
    "event": "state_changed",
    "jvod_state": "processing"
}

Handling notifications

To receive notifications, you simply need an app that can receive HTTP/HTTPS POST requests. The app can then parse the JSON notifications and do whatever you want based on their contents.

As a simple example, here is a PHP app we use in Brightcove Learning Services to receive notifications and write them to a text file.

getMessage();
      $notification = $json;
  }

  // $notification = $json;



  $logEntry = $notification."\n \n";

  // Lastly, tell PHP where it can find the log file and tell PHP to open it
  // and add the string we created earlier to it.
      $logFileLocation = "live-log.txt";
      $fileHandle      = fopen($logFileLocation, 'a') or die("-1");
      fwrite($fileHandle, $logEntry);
      fclose($fileHandle);

  // line below is displayed when you browse the app directly
  echo "Live callback app is running";