Live API: Creating VOD Clips

Product(s)
Live
Role(s)
API Developer
Topic(s)
Live Streaming
API(s)
Live API

This topic shows you how to create video-on-demand (VOD) clips from your live streams.

Overview

Clips are videos extracted from a live stream. They can be sent to an S3 bucket, an FTP site, or a Video Cloud account. The clip is created as an MP4 video, and that is what is sent to the destination in all cases. In the case of Video Cloud, the MP4 will be transcoded by the ingest system, and what kinds of renditions are created for the video will depend on the ingest profile used.

Definitions for clips are created using the /vods endpoint.

Clips can be created in several ways:

  • With stream_start_timecode and/or stream_end_timecode defined in SMPTE timecodes for the live stream event - note that this requires that the encoder be sending timecode information
  • With start_time and/or end_time defined relative to the start time ( stream_start_time) of the whole live stream event
  • With start_time and/or end_time defined in Epoch (Unix) time (in seconds)
  • With duration
  • The VOD API cannot be used with encrypted jobs.
  • Clips of live streams using SSAI will not include ads.

Notes

  1. If you specify duration, the resulting clip will be as follows:
    • If the job is active and still live: (request time - duration) to (request time)
    • If the job is finished: ( finished_at - duration) to ( finished_at)
  2. If you specify both start_time AND end_time:
    • If the job is active and still live: as long as the Epoch time window falls entirely within created_at and the request time, the clip will be made
    • If the job is finished: as long as the Epoch time window falls entirely within created_at and finished_at, the clip will be made
  3. Clips can be created up to 24 hours after an event. For SEP, they can be created up until the next activation or 24 hours (whichever is shorter).
  4. The VOD API will not add any content outside of what is present in the stream. If you specify 350 on a 300 seconds long live stream, the output will be 300 seconds long.
  5. You do not have to use a DVR-enabled live stream for clipping to work, because the live stream is stored as it is broadcast and is available immediately and for 24 hours after the event is over.
  6. Brightcove Live clipping will only produce a clip that is the same resolution as the highest resolution output. It will not match the source input resolution (unless that is the same as the highest resolution output).

Clips can also be sent to multiple destinations:

  • A Video Cloud account
  • An FTP server
  • An S3 bucket

When you specify a clip output either in the live job creation, or using the /vod endpoint, the output must contain either a url destination or a videocloud object to detail the creation of the video and ingestion of the clip in Video Cloud.

Note: clips can be created while the live stream is running. To do this, you will need to define the start and end times of the clip in Epoch time or relative to start time of the live stream.

Credentials

If the destination you are sending the clip to requires credentials to access, you can create these using the credentials operations of the Live API. See Managing Credentials for the Live API for more details.

Endpoint

Clips are created by sending a POST request to:

https://api.bcovlive.io/v1/vods

Request body - Video Cloud

Example 1: start/end times relative to stream start

The request body includes start and end times, and details about where to send the clip. Here is a sample request body that creates a clip of the third minute of a stream and sends it to a Video Cloud account:

{
  "live_job_id":"PUT-LIVE-JOB-ID-HERE",
  "outputs":[
    {
      "label": "60 secs by stream from min 2 to min 3",
      "stream_start_time": 120,
      "stream_end_time": 180,
      "credentials": "USER_VIDEOCLOUD_CREDENTIAL_LABEL",
      "videocloud": {
        "video": {
        "name": "One Minute Clip",
        "tags": ["live", "clip"]
        },
          "ingest": {
            "capture-images": true
        }
      }
    }
  ]
}

In this example, we are creating a clip of one-minute duration and sending it to Video Cloud . We're giving the clip a name and a couple of tags, not specifying the ingest profile for retranscoding, so that the account default will be used, and instructing Video Cloud to capture thumbnail and poster images from the clip during transcoding.

Example 2: start/end times in Epoch time

The request body includes start and end times in Epoch time, and details about where to send the clip. Here is a sample request body that creates a clip of the third minute of a stream and sends it to a Video Cloud account:

{
  "live_job_id":"PUT-LIVE-JOB-ID-HERE",
    "outputs":[
      {
        "label": "60 secs - epoch time",
        "start_time": 1516652694,
        "end_time": 1516652754,
        "credentials": "USER_VIDEOCLOUD_CREDENTIAL_LABEL",
        "videocloud": {
          "video": {
          "name": "One Minute Clip",
          "tags": ["live", "clip"]
          },
            "ingest": {
            "capture-images": true
        }
      }
    }
  ]
}

In this example, we are creating a clip of one-minute duration at a specific Epoch time (in this case 22 Jan 2018 at 08:24:54 GMT).

Example 3: duration with start time relative to stream start

The request body includes the duration and stream_start_time, and details about where to send the clip. Here is a sample request body that creates a clip of the third minute of a stream and sends it to a Video Cloud account:

{
  "live_job_id":"PUT-LIVE-JOB-ID-HERE",
  "outputs":[
    {
      "label": "60 secs from start time",
      "stream_start_time": 300,
      "duration": 60,
      "credentials": "USER_VIDEOCLOUD_CREDENTIAL_LABEL",
      "videocloud": {
        "video": {
        "name": "One Minute Clip",
        "tags": ["live", "clip"]
        },
        "ingest": {
        "capture-images": true
        }
      }
    }
  ]
}

In this example, we are creating a clip of one-minute duration starting 5 minutes after the start of the live stream.

Example 4: duration with no start or end time

The request body includes start and end times in Epoch time, and details about where to send the clip. Here is a sample request body that creates a clip of the third minute of a stream and sends it to a Video Cloud account:

{
  "live_job_id":"PUT-LIVE-JOB-ID-HERE",
  "outputs":[
    {
      "label": "60 secs - duration",
      "duration": 60,
      "credentials": "USER_VIDEOCLOUD_CREDENTIAL_LABEL",
      "videocloud": {
        "video": {
        "name": "One Minute Clip",
        "tags": ["live", "clip"]
        },
        "ingest": {
          "capture-images": true
        }
      },
      "notifications": ["http://myserver.com/api/notification_listener?type=jvod"]
    }
  ]
}

In this example, we are creating a clip of one-minute duration. Since we are not specifying a start or end time, the clip will be taken from the last 60 seconds of the live stream.

Example 5: using stream_start_timecode and stream_end_timecode

The request body includes start and end times/frames in HH:MM:SS:FF timecodes, and details about where to send the clip. Note that to use timecodes, the encoder must be sending timecodes. Here is a sample request body that creates a clip of the 50 minutes of a stream and sends it to a Video Cloud account:

{
  "live_job_id":"PUT-LIVE-JOB-ID-HERE",
  "outputs":[
    {
      "label": "Clipping using Timecode from-01:10:18:15 to-01:11:08:15",
      "stream_start_timecode": "01:10:18:15",
      "stream_end_timecode": "01:11:08:15",
      "credentials": "USER_VIDEOCLOUD_CREDENTIAL_LABEL",
      "videocloud": {
        "video": {
          "name": "Fifty Minute Clip",
          "tags": ["live", "clip"]
        },
        "ingest": {
        "capture-images": true
        }
      }
    },
    "notifications": ["http://myserver.com/api/notification_listener?type=jvod"]
  ]
}

General information about sending clips to Video Cloud

To see what fields can be included in the video and ingest objects, see the Dynamic Ingest API Reference.

Request body - S3

The request body includes start and end times, and details about where to send the clip. Here is a sample request body that creates a clip of the third minute of a stream and sends it to an S3 bucket:

{
  "live_job_id":"{{job_id}}",
  "outputs":[
    {
      "label": "last_30",
      "duration": 30,
      "url": "s3://YOUR_BUCKET_NAME/file_name.mp4",
      "credentials": "s3-credentials",
      "notifications": ["http://myserver.com/api/notification_listener?type=jvod"]
    }
  ],
}

In this example, we are creating a clip of 30 second duration and sending it to an S3 bucket. We provide the bucket URL including the file name for clip, and a string that is the name of saved S3 bucket credentials - the credentials can be set up for your account by Brightcove Support.

Request body fields

Here is a full table of the request body fields.

Request Body Fields
Field Type Description
live_job_id String

The id of Live Stream job to create the VOD clip from.

outputs Object[]

Array of VOD outputs

outputs.label String

Label for the output

outputs.duration Number

Duration of the clip in seconds. The duration can be used alone to define a clip that will be made of the final {duration} seconds of the stream. duration can also be use with any one of stream_start_time, stream_end_time, start_time, end_time, stream_end_timecode, or stream_start_timecode.

outputs.stream_start_time Number

Start time in seconds for the clip relative to the start time of the live stream, stream_start_time must be used with either stream_end_time or duration.

outputs.stream_end_time Number

End time in seconds for the clip relative to the start time of the live stream, stream_end_time must be used with either stream_start_time or duration.

outputs.start_time Number

Start time for the clip in Epoch (Unix) time (seconds), start_time must be used with either end_time or duration.

outputs.end_time Number

End time for the clip in Epoch (Unix) time (seconds), end_time must be used with either start_time or duration.

outputs.stream_start_timecode Number

Start time for the clip in an SMPTE-formatted (HH:MM:SS:FF) timecode from the start of the stream, stream_start_timecode must be used with either stream_end_timecode or duration.

outputs.stream_end_timecode Number

End time for the clip in an SMPTE-formatted (HH:MM:SS:FF) timecode from the end of the stream, outputs.stream_end_timecode must be used with either stream_start_timecode or duration.

outputs.url String

Destination URL for the clip, note that the output must contain either this url field or a videocloud object defining the video properties and ingest options for Video Cloud.

outputs.credentials String

The name of the credentials configured in your account for this address

outputs.videocloud Object

An object containing inputs for Video Cloud ingestion

outputs.videocloud.video Object

An object containing inputs for Video Cloud video object creation - see the CMS API Reference for creating a video

outputs.videocloud.ingest Object

An object containing inputs for Video Cloud video ingestion - see the Dynamic Ingest Reference - do not include the master field, as that information will be provided by the Live API. If no ingest profile is specified, the account default profile will be used.

Video fields for Video Cloud ingestion

See the CMS API Reference for more details.

Video Fields
Field Type Description
ad_keys String String representing the ad key/value pairs assigned to the video. Key/value pairs are formatted as key=value and are separated by ampersands. For example: "adKeys": "category=sports&live=true"
cue_points Array of Maps array of cue point maps
custom_fields Map of field-value pairs (Strings) Custom fieldname:value sets for the video - note that custom field that do not have a value for this video are not included in this map; custom field values have a maximum length of 1024 single-byte characters
description String; takes the place of the old shortDescription Short description of the video (maximum length: 248 single-byte characters)
economics String, must be one of valid enum values either "AD_SUPPORTED" (default) or "FREE"
geo Map of property-value pairs Geo-restriction properties for the video
link Map of property-value pairs Map of related link properties
long_description String Long description (up to 5000 characters)
name String The name of the video (maximum length: 248 single-byte characters) required
offline_enabled Boolean Whether the video is enabled for offline playback
projection String The mapping projection for 360° videos, e.g. "equirectangular"
reference_id String A user-specified id that uniquely identifies the video, limited to 150 characters. A referenceId can be used as a foreign-key to identify this video in another system. The reference id should not contain spaces, commas, or special characters.
schedule Map of property-value pairs Map of start and end date-times for the video availability
state String ACTIVE, INACTIVE
tags Array of tags (Strings) Array of tags assigned to the video
text_tracks Array of HTML5-style text tracks Array of text tracks (WebVTT files) assigned to the video

Video cuepoint fields

The table below shows fields for video.cuepoints.

Cuepoint Fields
Field Type Description
id String System id for the cue point
force_stop Boolean Whether the video should be stopped at the cue point
metadata String; code point only A metadata string associated with the cue point
name String The cue point name
time Float Time of the cue point in seconds measured from the start of the video
type String The cue point type ( AD or DATA)

Video geo fields

The table below shows the video.geo object fields.

Geo-Filtering Fields
Field Type Description
countries Array of country code Strings Array of ISO 3166 list of 2- or 4-letter codes (https://www.iso.org/obp/ui/) for countries in which the video is allowed or not allowed to play
exclude_countries Boolean If true, country array is treated as a list of countries excluded from viewing
restricted Boolean Whether geo-filtering is enabled for this video

The table below shows the video.link object fields.

Link Fields
Field Type Description
url String Related link URL
text String Related link text

Video schedule fields

The table below shows the fields for the video.schedule object

video.schedule Fields
Field Type Description
ends_at String in ISO-8601 date format Date-time when the video becomes unavailable for viewing
starts_at String in ISO-8601 date format Date-time when the video becomes available for viewing

Video Cloud Ingest fields

Video Cloud Ingest Fields
Field Type Description
audio_tracks optional Dynamic Delivery only Object[]

array of audio track objects - see Implementing Multiple Audio Tracks Using the APIs for more information.

audio_tracks.merge_with_existing optional Boolean

whether to replace existing audio tracks or add the new ones (currently only false is supported) Dynamic Delivery only

Default value: false

audio_tracks.masters optional Object[]

array of audio track objects Dynamic Delivery only

audio_tracks.masters.url optional String

URL for the audio file Dynamic Delivery only

audio_tracks.masters.language optional String

Language code for the audio track from the subtags in https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry (default can be set for the account by contacting Brightcove Support) Dynamic Delivery only

audio_tracks.masters.variant optional String

the type of audio track (default can be set for the account by contacting Brightcove Support) Dynamic Delivery only

Allowed values: "main", "alternate", "commentary", "dub", "descriptive"

profile optional String

ingest profile to use for transcoding; if absent, the default profile will be used

text_tracks optional Object[]

array of text_tracks objects - see Ingesting WebVTT Files (Text Tracks)

text_tracks.url Url

URL for a WebVTT file

text_tracks.srclang String

ISO 639 2-letter (alpha-2) language code for the text tracks

text_tracks.kind optional String

how the vtt file is meant to be used

Default value: captions

Allowed values: "captions", "subtitles", "chapters", "metadata"

text_tracks.label optional String

user-readable title

text_tracks.default optional Boolean

sets the default language for captions/subtitles

capture-images optional Boolean

whether poster and thumbnail should be captured during transcoding; defaults to true if the profile has image renditions, false if it does not - see Images and the Dynamic Ingest API for more information

poster optional Object

the video poster to be ingested - see Images and the Dynamic Ingest API for more information

poster.url Url

URL for the video poster image

poster.height optional Integer

pixel height of the image

poster.width optional Integer

pixel width of the image

thumbnail optional Object

the video thumbnail to be ingested - see Images and the Dynamic Ingest API for more information

thumbnail.url Url

URL for the video thumbnail image

thumbnail.height optional Integer

pixel height of the image

thumbnail.width optional Integer

pixel width of the image

callbacks optional String[] Array of URLs that notifications should be sent to

 

API response

The response to a create clip request includes an id for the job and the label you set in the request body, as well as the live job id:

{
  "vod_jobs": [
    {
      "jvod_id": "9582606c50d84be5ad4bc104f2aa3360",
      "label": "last 60 secs of live job"
    }
  ],
  "live_job_id": "88ba5d87b61a4ef3a6dddabd0c38d319"
}

Response fields

Response Body Fields
Field Type Description
vod_jobs Object

The clip response object

jvod_id String

The clip job id

label String

The clip label (from the input)

live_job_id String

The live job id (from the input)