This page describes how to create video on demand (VOD) clips from a live stream using the Live Stream API. VOD clips are made up of HLS manifest files and segment files that have been saved from a live stream. Only HLS manifests are supported.
Differences between VOD clips and DVR sessions
VOD clips (also known as channel clips) are similar to DVR sessions with the following key differences:
- DVR sessions:
- The API saves the DVR manifest in the same location as the live stream segments so there is no additional copying to Cloud Storage. The DVR manifest is similar to the live stream manifest but longer. When the retention window expires, the manifest is deleted along with the segment files.
- You can create a DVR session for past, current, and future content. For example, a DVR session can follow a live stream, or you can schedule a DVR session to start and stop at a future time.
- A typical use case for DVR sessions is to support DVR capabilities for live streaming events. For example, a viewer can join the live stream one hour after it begins and view the content with a one hour lag (or skip parts of it).
- Channel clips:
- The Live Stream API copies the clip manifest and the associated segment files to a user-specified directory so they are not deleted when the retention window expires. You have complete control of the clip.
- Only past content can be clipped. Live clips and scheduling future clips are not supported.
- A typical use case for clips is to archive a live stream, making the live stream available as a VOD file indefinitely.
For more information on DVR sessions, see Create a DVR session.
Set up your Google Cloud project and authentication
If you have not created a Google Cloud project and credentials, see Before you begin.Create an input endpoint
To create an input endpoint, use the
projects.locations.inputs.create
method.
Before using any of the request data, make the following replacements:
PROJECT_NUMBER
: your Google Cloud project number; this is located in the Project number field on the IAM Settings pageLOCATION
: the location in which to create the input endpoint; use one of the supported regionsShow locationsus-central1
us-east1
us-east4
us-west1
us-west2
northamerica-northeast1
southamerica-east1
asia-east1
asia-east2
asia-south1
asia-northeast1
asia-southeast1
australia-southeast1
europe-north1
europe-west1
europe-west2
europe-west3
europe-west4
INPUT_ID
: a user-defined identifier for the new input endpoint to create (to which you send your input stream). This value must be 1-63 characters, begin and end with[a-z0-9]
, and can contain dashes (-) between characters. For example,my-input
.
To send your request, expand one of these options:
You should receive a JSON response similar to the following:
{ "name": "projects/PROJECT_NUMBER/locations/LOCATION/operations/OPERATION_ID", "metadata": { "@type": "type.googleapis.com/google.cloud.video.livestream.v1.OperationMetadata", "createTime": CREATE_TIME, "target": "projects/PROJECT_NUMBER/locations/LOCATION/inputs/INPUT_ID", "verb": "create", "requestedCancellation": false, "apiVersion": "v1" }, "done": false }
This command creates a long-running operation (LRO) that you can use to track the progress of your request. See Manage long-running operations for more information.
Get input endpoint details
To get the details of the input endpoint, use the
projects.locations.inputs.get
method.
Before using any of the request data, make the following replacements:
PROJECT_NUMBER
: your Google Cloud project number; this is located in the Project number field on the IAM Settings pageLOCATION
: the location where your input endpoint is located; use one of the supported regionsShow locationsus-central1
us-east1
us-east4
us-west1
us-west2
northamerica-northeast1
southamerica-east1
asia-east1
asia-east2
asia-south1
asia-northeast1
asia-southeast1
australia-southeast1
europe-north1
europe-west1
europe-west2
europe-west3
europe-west4
INPUT_ID
: the user-defined identifier for the input endpoint
To send your request, expand one of these options:
You should receive a JSON response similar to the following:
{ "name": "projects/PROJECT_NUMBER/locations/LOCATION/inputs/INPUT_ID", "createTime": CREATE_TIME, "updateTime": UPDATE_TIME, "type": "RTMP_PUSH", "uri": "INPUT_STREAM_URI", # For example, "rtmp://1.2.3.4/live/b8ebdd94-c8d9-4d88-a16e-b963c43a953b", "tier": "HD" }
Find the uri
field and copy the returned
INPUT_STREAM_URI to use later
in the Send the input stream section.
Create a channel
To create a channel, use the
projects.locations.channels.create
method. The following samples create a channel that generates an HLS live
stream. The live stream consists of a single, high-definition (1280x720)
rendition.
To enable the creation of VOD clips, add the
retentionConfig
object to the channel configuration.
"retentionConfig": {
"retentionWindowDuration": {
"seconds": 86400
}
},
When retention is enabled for a live stream channel, the live stream segments
and manifest are retained in order to create VOD clips. The
retentionWindowDuration
object specifies the
length of time for which the live stream output is saved after being uploaded to
Cloud Storage. The retention window begins at the time the segment is
created in Cloud Storage.
The retention window is limited to 30 days. After the retention window has passed, the live stream segment files and manifest file are automatically deleted from Cloud Storage. (The VOD clip manifest and its associated segment files are not automatically deleted.) You can't create VOD clips using deleted segments. The deletion process is asynchronous and may take up to 24 hours to complete.
Specify a key for the manifest to enable VOD clip creation. You refer to this key when actually creating the clip. Only HLS manifests are supported.
"manifests": [
{
...
"key": "manifest_hls"
}
Before using any of the request data, make the following replacements:
PROJECT_NUMBER
: your Google Cloud project number; this is located in the Project number field on the IAM Settings pageLOCATION
: the location in which to create the channel; use one of the supported regionsShow locationsus-central1
us-east1
us-east4
us-west1
us-west2
northamerica-northeast1
southamerica-east1
asia-east1
asia-east2
asia-south1
asia-northeast1
asia-southeast1
australia-southeast1
europe-north1
europe-west1
europe-west2
europe-west3
europe-west4
CHANNEL_ID
: a user-defined identifier for the channel to create; this value must be 1-63 characters, begin and end with[a-z0-9]
, and can contain dashes (-) between charactersINPUT_ID
: the user-defined identifier for the input endpointBUCKET_NAME
: the name of the Cloud Storage bucket you created to hold the live stream manifest and segment files
To send your request, expand one of these options:
You should receive a JSON response similar to the following:
{ "name": "projects/PROJECT_NUMBER/locations/LOCATION/operations/OPERATION_ID", "metadata": { "@type": "type.googleapis.com/google.cloud.video.livestream.v1.OperationMetadata", "createTime": CREATE_TIME, "target": "projects/PROJECT_NUMBER/locations/LOCATION/channels/CHANNEL_ID", "verb": "create", "requestedCancellation": false, "apiVersion": "v1" }, "done": false }
This command creates a long-running operation (LRO) that you can use to track the progress of your request. See Manage long-running operations for more information.
Start the channel
To start a channel, use the
projects.locations.channels.start
method.
Before using any of the request data, make the following replacements:
PROJECT_NUMBER
: your Google Cloud project number; this is located in the Project number field on the IAM Settings pageLOCATION
: the location where your channel is located; use one of the supported regionsShow locationsus-central1
us-east1
us-east4
us-west1
us-west2
northamerica-northeast1
southamerica-east1
asia-east1
asia-east2
asia-south1
asia-northeast1
asia-southeast1
australia-southeast1
europe-north1
europe-west1
europe-west2
europe-west3
europe-west4
CHANNEL_ID
: a user-defined identifier for the channel
To send your request, expand one of these options:
You should receive a JSON response similar to the following:
{ "name": "projects/PROJECT_NUMBER/locations/LOCATION/operations/OPERATION_ID", "metadata": { "@type": "type.googleapis.com/google.cloud.video.livestream.v1.OperationMetadata", "createTime": CREATE_TIME, "target": "projects/PROJECT_NUMBER/locations/LOCATION/channels/CHANNEL_ID", "verb": "start", "requestedCancellation": false, "apiVersion": "v1" }, "done": false }
This command creates a long-running operation (LRO) that you can use to track the progress of your request. See Manage long-running operations for more information.
Send the input stream
Open a new terminal window. Run the following command, using INPUT_STREAM_URI from the Get input endpoint details section:
ffmpeg -re -f lavfi -i "testsrc=size=1280x720 [out0]; sine=frequency=500 [out1]" \
-acodec aac -vcodec h264 -f flv INPUT_STREAM_URI
Create a VOD clip
To create a VOD clip, use the
projects.locations.channels.clips.create
method.
Use the outputUri
field to specify the location in which to save
the clips and clip manifest file in Cloud Storage. You can use the same
bucket you created for the live stream manifest or a different bucket. You can
also append a directory name to the bucket name (for example,
my-bucket/vod-clip
).
Use the manifestKey
field in the
clipManifests
array to specify the manifest to save clips
from. In the example channel configuration on this page, this
key is set to manifest_hls
.
You can combine multiple time sections from the live stream into a single clip
by adding timeSlice
objects to the slices
array.
"outputUri": "gs://my-bucket",
"clipManifests":[
{
"manifestKey": "manifest_hls"
}
],
"slices":[
{
"timeSlice": {
"markinTime": "2022-07-08T23:03:20.000Z",
"markoutTime": "2022-07-08T23:04:20.000Z"
}
},
{
"timeSlice": {
"markinTime": "2022-07-08T23:05:20.000Z",
"markoutTime": "2022-07-08T23:06:20.000Z"
}
}
]
Note the following:
- Each clip must contain at least one
timeSlice
inslices
. - The
clipManifests.manifestKey
field must refer to a defined HLS manifest in the clip's parent channel. If the clip job creation request succeeds, then the URI of the generated clip manifest is returned in theclipManifests.outputUri
field. This URI is in the path specified by the clip'soutputUri
field. - The
clipManifests
array supports only one manifest per request. If you want to generate multiple manifests for the same clip job, then you need to split the manifests into multiple clip job requests. - Clip slices must be homogenous; every element must be of type
timeSlice
. - The set of
timeSlice
objects must be non-overlapping and in chronological order. ThemarkinTime
must be earlier than themarkoutTime
in everytimeSlice
. - If the latest
markinTime
of a clip is earlier than the channel start time or the start of the retention window, then the mark-in time is set to the later of the two. - If the latest
markoutTime
of a clip is later than the channel stop time, then it is set to the channel stop time. If the latestmarkoutTime
of a clip is later than the current system wall clock time, then it is set to the time that the API actually starts the clipping task. - The maximum duration for a clip is 24 hours.
Before using any of the request data, make the following replacements:
PROJECT_NUMBER
: your Google Cloud project number; this is located in the Project number field on the IAM Settings pageLOCATION
: the location where your channel is located; use one of the supported regionsShow locationsus-central1
us-east1
us-east4
us-west1
us-west2
northamerica-northeast1
southamerica-east1
asia-east1
asia-east2
asia-south1
asia-northeast1
asia-southeast1
australia-southeast1
europe-north1
europe-west1
europe-west2
europe-west3
europe-west4
CHANNEL_ID
: a user-defined identifier for the channelCLIP_ID
: a user-defined identifier for the VOD clipMARK_IN_TIME
: the mark-in Unix epoch time in the original live stream manifest; uses a timestamp in RFC3339 UTC "Zulu" format (for example,2014-10-02T15:01:23Z
)MARK_OUT_TIME
: the mark-out Unix epoch time in the original live stream manifest; uses a timestamp in RFC3339 UTC "Zulu" format (for example,2014-10-02T15:01:23Z
)BUCKET_NAME
: the name of the Cloud Storage bucket you created to hold the VOD clip manifest and segment files; you can use the same bucket you created for the live stream manifest or a different bucket; you can also append a directory name to the bucket name (for examplemy-bucket/vod-clip
)
To send your request, expand one of these options:
You should receive a JSON response similar to the following:
{ "name": "projects/PROJECT_NUMBER/locations/LOCATION/operations/OPERATION_ID", "metadata": { "@type": "type.googleapis.com/google.cloud.video.livestream.v1.OperationMetadata", "createTime": CREATE_TIME, "target": "projects/PROJECT_NUMBER/locations/LOCATION/channels/CHANNEL_ID/clips/CLIP_ID", "verb": "create", "requestedCancellation": false, "apiVersion": "v1" }, "done": false }
This command creates a long-running operation (LRO) that you can use to track the progress of your request. See Manage long-running operations for more information.
Get the VOD clip
To get a VOD clip, use the projects.locations.channels.clips.get
method.
Before using any of the request data, make the following replacements:
PROJECT_NUMBER
: your Google Cloud project number; this is located in the Project number field on the IAM Settings pageLOCATION
: the location where your channel is located; use one of the supported regionsShow locationsus-central1
us-east1
us-east4
us-west1
us-west2
northamerica-northeast1
southamerica-east1
asia-east1
asia-east2
asia-south1
asia-northeast1
asia-southeast1
australia-southeast1
europe-north1
europe-west1
europe-west2
europe-west3
europe-west4
CHANNEL_ID
: a user-defined identifier for the channelCLIP_ID
: a user-defined identifier for the VOD clip
To send your request, expand one of these options:
You should receive a JSON response similar to the following:
{ "name": "projects/PROJECT_NUMBER/locations/LOCATION/channels/CHANNEL_ID/clips/CLIP_ID", "createTime": CREATE_TIME, "startTime": START_TIME, "updateTime": UPDATE_TIME, "state": "SUCCEEDED", "outputUri": "gs://BUCKET_NAME", "slices": [ { "timeSlice": { "markinTime": "MARK_IN_TIME", "markoutTime": "MARK_OUT_TIME" } } ], "features": {}, "clipManifests": [ { "manifestKey": "manifest_hls", "outputUri": "gs://BUCKET_NAME/main.m3u8" } ] }
The generated manifest is located at the URI specified in the
clipManifests.outputUri
field. The manifest
filename is the same as the parent channel's
manifests.fileName
field value.
The response should contain the following:
{
...
"state": "SUCCEEDED"
...
}
Only the most recent 1000 clip job records per channel are available
using the
projects.locations.channels.clips.get
method. Any clip job records older than the limit are removed. You must manage the generated clip
files specified by the
outputUri
;
the Live Stream API does not delete these files from Cloud Storage.
Verify bucket contents
Open the Cloud Storage bucket as specified in the clip's
outputUri
field. Verify that it contains the following files and
directories:
- A top-level manifest for the clip with the same name as the
manifests.fileName
specified in the channel configuration (for example,main.m3u8
); you can play this manifest using an online media player - A directory for each
muxStreams.key
specified in the channel (for example,mux_video_ts
)- A playlist for the clip (for example,
index-1.m3u8
) - A directory named using the format
YYYYMMDDTHHMMSSZ
(for example,20220708T203309Z/
); this directory holds the VOD clip segments- Multiple segment
segment-number.ts
files that make up the VOD clip
- Multiple segment
- A playlist for the clip (for example,
Play the VOD clip
To play the generated media file in Shaka Player, complete the following steps:
- Make the Cloud Storage bucket you created publicly readable.
- To enable cross-origin resource
sharing (CORS) on a Cloud Storage bucket, do the following:
- Create a JSON file that contains the following:
[ { "origin": ["https://shaka-player-demo.appspot.com/"], "responseHeader": ["Content-Type", "Range"], "method": ["GET", "HEAD"], "maxAgeSeconds": 3600 } ]
-
Run the following command after replacing
JSON_FILE_NAME
with the name of the JSON file you created in the previous step:gcloud storage buckets update gs://BUCKET_NAME --cors-file=JSON_FILE_NAME.json
- Create a JSON file that contains the following:
- In the Cloud Storage bucket, find the generated file. Click Copy URL in the file's Public access column.
- Navigate to Shaka Player, an online live stream player.
- Click Custom Content in the top navigation bar.
- Click the + button.
Paste the public URL of the file into the Manifest URL box.
Type a name in the Name box.
Click Save.
Click Play.
You should see a test pattern play as the live stream.
Ad break and slate events
If you created an ad break event for the live stream, the VOD clips won't contain the ads. The API generates a playlist with the ad breakpoints replaced by the following tags:
#EXT-X-CUE-OUT: AD_BREAK_DURATION
#EXT-X-CUE-IN
Slates that appear at the start or the end of the VOD clip are automatically removed. Slates that appear within the stream, surrounded by the live stream content, are retained in the generated VOD clip.