Live API: Creating VOD Clips
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/orstream_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/orend_time
defined relative to the start time (stream_start_time
) of the whole live stream event - With
start_time
and/orend_time
defined in Epoch (Unix) time (in seconds) - With
duration
- The VOD API can be used with encrypted or DRM-protected jobs. Currently the Live Module does not support this, but will in a future release.
Notes
- To make clips available as quickly as possible, a segment-accurate clip is first created, and then replaced by a frame-accurate clip as soon as it is available.
- 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
)
- If you specify both
start_time
ANDend_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
andfinished_at
, the clip will be made
- If the job is active and still live: as long as the Epoch time window falls entirely within
- Clips of live streams using SSAI will not include ads.
- Clips can be created up to 7 days after an event. For SEP, they can be created up until the next activation or 7 days (whichever is shorter).
- 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.
- 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 7 days after the event is over.
- 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, 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":"",
"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.
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 |
outputs.stream_start_time |
Number |
Start time in seconds for the clip relative to the start time of the live stream, |
outputs.stream_end_time |
Number |
End time in seconds for the clip relative to the start time of the live stream, |
outputs.start_time |
Number |
Start time for the clip in Epoch (Unix) time (seconds), |
outputs.end_time |
Number |
End time for the clip in Epoch (Unix) time (seconds), |
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, |
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.url |
String |
Destination URL for the clip, note that the output must contain either this |
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 |
Video fields for Video Cloud ingestion
See the CMS API Reference for more details.
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
.
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.
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 |
Video link fields
The table below shows the video.link
object 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
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
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 Default value: |
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: |
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.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: Allowed values: |
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 |
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
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) |