Create a DVR session

This page shows you how to create a digital video recorder (DVR) session from a live stream using the Live Stream API. You can view a DVR session during a live stream as well as after it ends.

Differences between DVR sessions and channel clips

DVR sessions are similar to channel clips (also known as VOD clips) 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 channel clips, see Create VOD clips from a live stream.

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 page
  • LOCATION: the location in which to create the input endpoint; use one of the supported regions
    Show locations
    • us-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 page
  • LOCATION: the location where your input endpoint is located; use one of the supported regions
    Show locations
    • us-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 test 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 DVR sessions, 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 DVR sessions. 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 segment files, live stream manifest, and DVR manifest are automatically deleted from Cloud Storage. You can't create DVR sessions 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 DVR session creation. You refer to this key when actually creating the session. 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 page
  • LOCATION: the location in which to create the channel; use one of the supported regions
    Show locations
    • us-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 characters
  • INPUT_ID: the user-defined identifier for the input endpoint
  • BUCKET_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 page
  • LOCATION: the location where your channel is located; use one of the supported regions
    Show locations
    • us-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 test 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 DVR session

To create a DVR session, use the projects.locations.channels.dvrSessions.create method.

Use the manifestKey field in the dvrManifests array to specify the manifest to save content 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 DVR session by adding timeInterval objects to the dvrWindows array.

"dvrManifests": [
  {
    "manifestKey": "manifest_hls"
  }
],
"dvrWindows": [
  {
    "timeInterval": {
      "startTime": "2022-07-08T23:03:20.000Z",
      "endTime": "2022-07-08T23:04:20.000Z"
    }
  },
  {
    "timeInterval": {
      "startTime": "2022-07-08T23:05:20.000Z",
      "endTime": "2022-07-08T23:06:20.000Z"
    }
  }
]

Note the following:

  • Each DVR session must contain at least one timeInterval in dvrWindows.
  • The dvrManifests.manifestKey field must refer to a defined HLS manifest in the DVR session's parent channel. If the DVR session creation request succeeds, then the URI of the generated DVR manifest is returned in the dvrManifests.outputUri field. This URI is in the path specified by the channel's outputUri field.
  • The dvrManifests array supports only one manifest per request. If you want to generate multiple manifests for the same DVR windows, then you need to split the manifests into multiple DVR sessions.
  • The set of timeInterval objects must be non-overlapping and in chronological order. The startTime must be earlier than the endTime in every timeInterval.
  • The startTime and endTime refer to the live stream timeline. If embedded timecode is enabled for the manifest, this timeline is based on the embedded timecode provided in the input stream and may differ from the wall clock.
  • The maximum total duration for the DVR window is 24 hours.
  • The endTime of the last timeInterval in dvrWindows can be left empty. In this case, the endTime is automatically calculated to maximize the DVR session duration (that is, a total duration of 24 hours).
  • The DVR windows can cover any time range, including those in the future. However, the number of DVR sessions with dvrWindows extending to a future time is limited to one.
  • There is no limit on the number of DVR sessions where all DVR windows are strictly in the past.

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 page
  • LOCATION: the location where your channel is located; use one of the supported regions
    Show locations
    • us-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
  • DVR_SESSION_ID: a user-defined identifier for the DVR session
  • INTERVAL_START_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)
  • INTERVAL_END_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)

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/dvrSessions/DVR_SESSION_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 DVR session

To get a DVR session, use the projects.locations.channels.dvrSessions.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 page
  • LOCATION: the location where your channel is located; use one of the supported regions
    Show locations
    • us-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
  • DVR_SESSION_ID: a user-defined identifier for the DVR session

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/dvrSessions/DVR_SESSION_ID",
  "createTime": CREATE_TIME,
  "startTime": START_TIME,
  "updateTime": UPDATE_TIME,
  "state": "SUCCEEDED",
  "dvrManifests": [
    {
      "manifestKey": "manifest_hls",
      "outputUri": "gs://BUCKET_NAME/dvr/DVR_SESSION_ID/main.m3u8"
    }
  ],
  "dvrWindows": [
    {
      "timeInterval": {
        "startTime": "INTERVAL_START_TIME",
        "endTime": "INTERVAL_END_TIME"
      }
    }
  ]
}

The response should contain a state field that indicates the state of the session:

{
  ...
  "state": "PENDING" // DVR session is waiting to be processed (for example, it is waiting for the channel to start)
  ...
}

See the state reference documentation for the list of states and their descriptions.

Verify bucket contents

Open the Cloud Storage bucket as specified in the DVR session's dvrManifests.outputUri field. Verify that it contains the following files and directories:

  • A top-level manifest for the DVR session 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 subdirectory for each muxStreams.key specified in the channel (for example, mux_video_ts). Each subdirectory contains a playlist for the DVR session (for example, index-1.m3u8).

Play the DVR session

To play the generated media file in Shaka Player, complete the following steps:

  1. Make the Cloud Storage bucket you created publicly readable.
  2. To enable cross-origin resource sharing (CORS) on a Cloud Storage bucket, do the following:
    1. Create a JSON file that contains the following:
      [
        {
          "origin": ["https://shaka-player-demo.appspot.com/"],
          "responseHeader": ["Content-Type", "Range"],
          "method": ["GET", "HEAD"],
          "maxAgeSeconds": 3600
        }
      ]
    2. 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
  3. In the Cloud Storage bucket, find the generated file. Click Copy URL in the file's Public access column.
  4. Navigate to Shaka Player, an online live stream player.
  5. Click Custom Content in the top navigation bar.
  6. Click the + button.
  7. Paste the public URL of the file into the Manifest URL box.

  8. Type a name in the Name box.

  9. Click Save.

  10. Click Play.

You should see a test pattern play as the live stream.

Test pattern video

Ad break events

If you created an ad break event for the live stream, the DVR session contains the ad segments as they appear in the live stream.