User Guide

Channels

Channel creation

In general, the Virtual Channel workflow starts with the creation of a channel using the PUT /channels/{channel} endpoint. Two things are needed to generate such a request:

  • you must choose a channel name and use it to form the URL you will PUT to (i.e. create a rock_concert event by PUTting to http://localhost:8000/channels/rock_concert)

  • an appropriate SMIL playlist must be provided as an application/xml request body (see SMIL creation for instructions on SMIL creation).

The name you have chosen for your channel will reflect in the playout URL: i.e. for the previous example's rock_concert name, the playout URL will be available at http://localhost/rock_concert.isml.

Note

As opposed to a classic Origin setup, an http://localhost/rock_concert.isml playout URL does not mean that the name of the corresponding server manifest file on disk is rock_concert.isml. Instead, on channel creation, a UUID is computed based on the full content of the SMIL playlist; that UUID is used as the server manifest's filename.

The creation of a live channel can be a long-running operation. For this reason, it's important to understand that its actual creation is performed by a job that Virtual Channel schedules for background execution after returning from the PUT operation.

In other words, a PUT operation does not create a new channel immediately and does not guarantee that the channel will be effectively created without errors. Instead, a variable amount of time (depending by various factors, such as playlist complexity and network speed) is required before the channel creation jobs terminates.

In order to understand if your channel is live, you have to check your channel creation status.

Note

Once a certain playlist has been used to create a channel for the first time, the job duration for any further channels that uses the exact same playlist will be almost instantaneous. In fact, all channels using the exact same SMIL playlist will completely reuse the related isml server manifest as well as media segments.

Checking channel creation job status

As a user, you can monitor at any time the status of your channel by using the GET /channels/{channel}/status endpoint. The possible statuses are:

  • Pending: your channel is scheduled to be created soon. At this time, no modifications to the channel are allowed.

  • In Progress: a job to create your channel is still running. Additional details are provided by the status endpoint. At this time, no modifications to the channel are allowed.

  • Success: the job was successful and your channel is live and accessible at the relative playout URL.

  • Failed: the channel was not created because of an error. In this case, refer to the API endpoints allowing you to retrieve the task's logs, which include details on the outcome of the remix and mp4split commands.

When your channel has reached the Success status, it will be available for playout at the corresponding origin_url provided by the status endpoint.

If the status is Pending or In Progress, just wait until the system has finished the job execution.

If the status is Failed, it means something went wrong at playlist processing time and you should check the remix or mp4split logs using the dedicated endpoints.

Amending/modifying channels

If the channel's status is either "Success" or "Failure", performing another PUT operation (usually with a modified SMIL playlist) will overwrite the existing channel.

Note

➡️ this is not the endpoint allowing channel "transitions"! This is mostly dedicated to "overwrite and forget" channels that have been created with a certain playlist but have not yet started playing. In fact, attempting a PUT on a channel that has started playout already will just fail.

Listing and deleting channels

You can get a list of the existing channels with the /channel endpoint.

To remove a channel, perform a DELETE operation. This will be allowed only if the channel creation job is in either one of the Success or Failed statuses.

Warning

the DELETE operation does not perform any check and will successfully delete also channels that are playing already.

Transitions

Once you have created at least one channel, you can proceed to add transitions.

Transitions allow you to seamlessly update a running virtual channel to switch to either a new VOD2Live playlist or an external live source. When transitioning to a VOD2Live playlist it is possible to start the playlist at the beginning, or to switch in to an already running playlist.

These options give you the flexibility to run your channel exactly as required.

For a visual example of how the output of Virtual Channel maps to the sources, whether VOD2Live playlists or live, see the following diagrams.

This shows a Virtual Channel which starts with a VOD2Live playlist A, switches to a live source X for a set duration, then switches to a new VOD2Live playlist B.

Virtual Channel transitioning to live source then new VOD2Live

This shows a Virtual Channel which starts with a VOD2Live playlist A, switches to a live source X for a set duration, then switches back to the same VOD2Live playlist A. In this example the time block for the live source in playlist A should include some filler content to ensure that the switch back to VOD2Live works as expected.

Virtual Channel transitioning to live source then back to the existing VOD2Live playlist

Transition creation

It is possible to "transition" an existing channel from its current playlist to another at a given date/time by means of the dedicated endpoint PUT /channels/{channel}/transitions/{transition}. The operation is similar to what is required to create a channel and it requires two things:

  • knowing the name of the channel you want to "transition" and the time you want the transition to happen. This information is used to form the URL to PUT to (i.e. to transition the rock_concert event to another playlist at 2022-07-18T20:00:00Z, you should PUT to http://localhost:8000/channels/rock_concert/2022-07-18T20:00:00Z)

  • an appropriate SMIL playlist, provided as an application/xml request body, describing what the channel should transition to. (the same SMIL instructions SMIL creation apply).

Warning

always use transition times expressed in UTC, using one of the two allowed time formats 2022-04-14T06:00:00Z or 2022-04-14T06:00:00.000Z

As it happens for channels, creating a transition may be a long-running operation and as such is executed in the background. For this reason, you should always check the transition creation status after using this endpoint.

Note

Once a certain playlist has been used to create a transition for the first time, the job duration for any further transition that uses the exact same playlist will be almost instantaneous. In fact, all transitions using the exact same SMIL playlist will completely reuse the related isml server manifest as well as media segments.

The transition creation endpoint will error out immediately if certain conditions are failed. Those are:

  • Transitions will be refused if the provided transition time is earlier than the vod2live_start_time specified in the SMIL playlist. Allowing such transitions would essentially mean allowing switching to a presentation that hasn't yet started. This would generate a gap in the presentation and for this reason it is always considered an error.

  • Transitions will be refused if their transition time is in the past. Allowing such transitions would effectively break all players that have already started playing back the channel.

If you understand the consequences and know what you are doing, you can force the API to skip the above checks by appending a ?force query parameter to the API endpoint.

Checking transition creation job status

As a user, you can monitor at any time the status of your transition creation job by using the GET /channels/{channel}/transitions/{transition}/status endpoint. The possible statuses are:

  • Pending: your transition is scheduled to be created soon. At this time, no modifications to the channel or the transition are allowed.

  • In Progress: a job to create your transition is still running. Additional details are provided by the status endpoint. At this time, no modifications to the transition are allowed.

  • Success: the job was successful and your transition is active. At the scheduled time the channel will switch to the provided playlist.

  • Failed: the transition was not created because of an error. In this case, refer to the API endpoints allowing you to retrieve the task's logs, which include details on the outcome of the remix and mp4split commands. No modifications have been done to the channel.

If the status is Pending or In Progress, just wait until the system has finished the job execution.

If the status is Failed, it means something went wrong at playlist processing time and you should check the remix or mp4split logs using the dedicated endpoints.

If the remix and mp4split steps were successful but took a long time to complete, the job can fail as well. In fact, once a working isml has been produced, Virtual Channel checks if the scheduled transition time has passed. If it has, the job is considered aborted. Allowing such transitions would effectively break all players that have already started playing back the channel.

Warning

If the transition was created using the ?force parameter (see previous section), the above check will be skipped.

Amending/modifying transitions

If the transition's status is either "Success" or "Failure", performing another PUT operation (usually with a modified SMIL playlist) will overwrite the existing transition.

Warning

this endpoint is dedicated to modify/overwrite transitions that have been scheduled but are not active yet (i.e. their transition time is in the future ). If the transition is active (i.e. transition time is in the past), the endpoint will fail and will not perform any modifications to the channel. If you want to modify the playlist that is currently playing in the channel, the right thing to do is just to create another transition at some point in the future.

Listing and deleting transitions

You can get a list of the existing transitions on a given channels with the /channels/{channel}/transitions endpoint. This will return a dictionary where, for each transition ever submitted, details on the job status and the related smil will be provided.

If you wish to only retrieve those transitions whose job was successful (and thus actually affecting your channel), you can filter the results via query parameter, i.e. /channels/{channel}/transitions?status=Success. Similarly, you may filter for unsuccessful transition jobs using the filter /channels/{channel}/transitions?status=Failed.

Time-based queries are supported for this endpoint. If you need to retrieve the list of transitions of a given channel, in a specific time range, you can do so by using the begin and end query parameters, e.g.

GET /channels/{channel}/transitions?begin=2022-10-21T07:03:41Z&end=2022-10-22T07:03:41Z

As usual, an UTC time in ISO-8601 format is required.

To remove a transition, perform a DELETE operation. This will be allowed only if the transition creation job is in either one of the Success or Failed statuses.

Warning

the DELETE operation does not perform any check and will successfully delete also active transitions (i.e. with transition time in the past). In this case, any device/player that is actively reproducing content related to the playlist being deleted will stop playback and hang. Hoewer, the underlying channel will still be operational and will just "revert" to the content of the base channel or of any transition prior to the one that was deleted.

Note

remember that automatic deletion of old, unused transitions is enabled in Virtual Channel (see Automatic transition deletion) and as such, after a certain time (default is 7 days), transitions may be automatically deleted.

SMIL creation

SMIL playlists are the primary way in Virtual Channel to:

  • specify the content of a channel/transition (generally accomplished in the <body> section)

  • pass options to remix/mp4split at channel/transition creation time (generally accomplished in the <head> section)

At this purpose, two kinds of SMIL playlists exists:

  • VOD2Live SMIL playlist: this is the kind of playlist you may be already familiar with if you have already used Unified Remix-VOD2Live. It allows you to define content by stitching together existing VOD assets and timed metadata, as well as to pass options to Remix/mp4split at channel/transition creation time.

  • LIVE SMIL playlist: much simpler, it does not allow any stitching per se, but is used to add existing, external Origin Live sources to a Virtual Channel.

Each one will be addressed in detail in the following sections.

VOD2Live SMIL

For a VOD2Live playlist, an <head> section with two mandatory options, vod2live and vod2live_start_time is required.

Additional Origin output configuration options can also be set in the <head>. To check how they should be formatted you can use mp4split to generate an example .isml like so: mp4split -o stdout:.isml --hls.client_manifest_version=5.

Here is an example: VOD2Live Smil:

<?xml version='1.0' encoding='UTF-8'?>
<smil xmlns="http://www.w3.org/2001/SMIL20/Language">
  <head>
    <meta name="vod2live" content="true" />
    <meta name="vod2live_start_time" content="2022-04-14T06:00:00Z" />
    <meta name="hls_client_manifest_version" content="5" />
    <meta name="hls_minimum_fragment_length" content="48/25" />
    <meta name="mpd_minimum_fragment_length" content="48/25" />
    <meta name="mpd_segment_template" content="time" />
    <meta name="timed_metadata" content="true" />
    <meta name="splice_media" content="true" />
  </head>
  <body>
    <seq>
      <par clipEnd="wallclock(1970-01-01T00:00:44.160Z)">
        <audio src="https://usp-vod2live.s3.amazonaws.com/Promo_Learning-aac-128k.mp4"/>
        <video src="https://usp-vod2live.s3.amazonaws.com/Promo_Learning-avc1-400k.mp4"/>
        <video src="https://usp-vod2live.s3.amazonaws.com/Promo_Learning-avc1-750k.mp4"/>
        <video src="https://usp-vod2live.s3.amazonaws.com/Promo_Learning-avc1-1000k.mp4"/>
        <video src="https://usp-vod2live.s3.amazonaws.com/Promo_Learning-avc1-1500k.mp4"/>
      </par>
    </seq>
  </body>
</smil>

Warning

You can use the provided example for your tests, because it is based on media stored on a publicly accessible s3 bucket. As such though, it will only work if you have not set any S3 authentication environmental variables.

You can set a desired channel start time by respecting the ISO-8601 datetime format and expressing time as UTC. Make sure to keep the value of vod2live to true.

You can find additional examples of valid SMIL playlists in Virtual Channel's repository , in the example folder.

SCTE 35 for ad insertion

Due to the flexibility of both SCTE 35 and DASH EventStreams there are many options for scheduling SCTE 35 events to enable ad insertion in Virtual Channel, but the most straightforward and recommended method is to schedule separate cue out and cue in events on the first element of the break and the return to main content respectively.

Scheduling these events without a duration on the DASH Event in the SMIL playlist will trigger Virtual Channel to calculate the actual duration and ensure everything is signalled appropriately in the output.

An example showing this with two sets of SCTE 35 events for two breaks with spliceEventId 1001 and 1002:

<?xml version='1.0' encoding='UTF-8'?>
<smil xmlns="http://www.w3.org/2001/SMIL20/Language">
  <!--
    Example playlist with SCTE 35 cues to signal ad breaks
  -->
  <head>
    <meta name="vod2live" content="true"/>
    <meta name="vod2live_start_time" content="2023-01-01T00:00:00Z"/>
    <meta name="hls_client_manifest_version" content="5"/>
    <meta name="dvr_window_length" content="600"/>
    <meta name="timed_metadata" content="true"/>
    <meta name="splice_media" content="true"/>
  </head>
  <body>
    <seq>
      <par>
        <!-- Start of ad break CUE OUT - SCTE 35 event ID 1001 -->
        <video src="http://s3.internal.unified-streaming.com/vod2live/Unified_Astronaut_A_v2-avc1-400k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Unified_Astronaut_A_v2-avc1-750k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Unified_Astronaut_A_v2-avc1-1000k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Unified_Astronaut_A_v2-avc1-1500k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Unified_Astronaut_A_v2-avc1-2200k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Unified_Astronaut_A_v2-aac-128k.mp4"/>
        <EventStream xmlns="urn:mpeg:dash:schema:mpd:2011" schemeIdUri="urn:scte:scte35:2014:xml+bin">
          <Event id="1">
            <Signal xmlns="http://www.scte.org/schemas/35/2016">
              <SpliceInfoSection>
                <SpliceInsert spliceEventId="1001" outOfNetworkIndicator="1" spliceImmediateFlag="1">
                  <Program/>
                </SpliceInsert>
              </SpliceInfoSection>
            </Signal>
          </Event>
        </EventStream>
      </par>
      <par>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Toothpaste_Glitch_v2-avc1-400k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Toothpaste_Glitch_v2-avc1-750k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Toothpaste_Glitch_v2-avc1-1000k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Toothpaste_Glitch_v2-avc1-1500k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Toothpaste_Glitch_v2-avc1-2200k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Toothpaste_Glitch_v2-aac-128k.mp4"/>
      </par>
      <par clipEnd="wallclock(1970-01-01T00:01:00Z)" >
        <!-- End of ad break CUE IN - SCTE 35 event ID 1001 -->
        <video src="http://s3.internal.unified-streaming.com/vod2live/What_is_SCTE35_Jamie-avc1-400k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/What_is_SCTE35_Jamie-avc1-750k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/What_is_SCTE35_Jamie-avc1-1000k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/What_is_SCTE35_Jamie-avc1-1500k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/What_is_SCTE35_Jamie-avc1-2200k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/What_is_SCTE35_Jamie-aac-128k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/What_is_SCTE35_Jamie.ismt"/>
        <EventStream xmlns="urn:mpeg:dash:schema:mpd:2011" schemeIdUri="urn:scte:scte35:2014:xml+bin">
          <Event id="2">
            <Signal xmlns="http://www.scte.org/schemas/35/2016">
              <SpliceInfoSection>
                <SpliceInsert spliceEventId="1001" outOfNetworkIndicator="0" spliceImmediateFlag="1">
                  <Program/>
                </SpliceInsert>
              </SpliceInfoSection>
            </Signal>
          </Event>
        </EventStream>
      </par>
      <par>
        <!-- Start of ad break CUE OUT - SCTE 35 event ID 1002 -->
        <video src="http://s3.internal.unified-streaming.com/vod2live/Cycle_Unified_v2-avc1-400k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Cycle_Unified_v2-avc1-750k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Cycle_Unified_v2-avc1-1000k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Cycle_Unified_v2-avc1-1500k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Cycle_Unified_v2-avc1-2200k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Cycle_Unified_v2-aac-128k.mp4"/>
        <EventStream xmlns="urn:mpeg:dash:schema:mpd:2011" schemeIdUri="urn:scte:scte35:2014:xml+bin">
          <Event id="3">
            <Signal xmlns="http://www.scte.org/schemas/35/2016">
              <SpliceInfoSection>
                <SpliceInsert spliceEventId="1002" outOfNetworkIndicator="1" spliceImmediateFlag="1">
                  <Program/>
                </SpliceInsert>
              </SpliceInfoSection>
            </Signal>
          </Event>
        </EventStream>
      </par>
      <par>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Unified_Astronaut_A_v2-avc1-400k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Unified_Astronaut_A_v2-avc1-750k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Unified_Astronaut_A_v2-avc1-1000k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Unified_Astronaut_A_v2-avc1-1500k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Unified_Astronaut_A_v2-avc1-2200k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/Unified_Astronaut_A_v2-aac-128k.mp4"/>
      </par>
      <par clipEnd="wallclock(1970-01-01T00:01:00Z)">
        <!-- End of ad break CUE IN - SCTE 35 event ID 1002 -->
        <video src="http://s3.internal.unified-streaming.com/vod2live/ManifestEdit_Lightboard_V4_Linzi-avc1-400k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/ManifestEdit_Lightboard_V4_Linzi-avc1-750k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/ManifestEdit_Lightboard_V4_Linzi-avc1-1000k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/ManifestEdit_Lightboard_V4_Linzi-avc1-1500k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/ManifestEdit_Lightboard_V4_Linzi-avc1-2200k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/ManifestEdit_Lightboard_V4_Linzi-aac-128k.mp4"/>
        <video src="http://s3.internal.unified-streaming.com/vod2live/ManifestEdit_Lightboard_V4_Linzi.ismt"/>
        <EventStream xmlns="urn:mpeg:dash:schema:mpd:2011" schemeIdUri="urn:scte:scte35:2014:xml+bin">
          <Event id="4">
            <Signal xmlns="http://www.scte.org/schemas/35/2016">
              <SpliceInfoSection>
                <SpliceInsert spliceEventId="1002" outOfNetworkIndicator="0" spliceImmediateFlag="1">
                  <Program/>
                </SpliceInsert>
              </SpliceInfoSection>
            </Signal>
          </Event>
        </EventStream>
      </par>
    </seq>
  </body>
</smil>

Live SMIL

For a Live playlist, an empty <body> and a <head> section with two mandatory options, live_source and dvr_window_length , are required.

In HLS ad insertion use cases it's also important to set two additional options to ensure that media segmentation and segment duration is signalled correctly. These options are hls_minimum_fragment_length and splice_media, they should be set to the same values used in the source live stream.

Here is an example: Live Smil

<?xml version='1.0' encoding='UTF-8'?>
<smil xmlns="http://www.w3.org/2001/SMIL20/Language">
  <head>
    <meta name="live_source" content="https://demo.unified-streaming.com/k8s/vc-perm-live-source/trunk/colourbars/colourbars.isml" />
    <meta name="dvr_window_length" content="30" />
    <meta name="hls_minimum_fragment_length" content="48/25" />
    <meta name="splice_media" content="true" />
  </head>
  <body/>
</smil>

Notice that live_source must refer to an existing Live Origin instance and that dvr_window_length is expressed in seconds.

A live SMIL must only refer to one existing live source, i.e. it is not possible to "stitch" multiple live sources together in a single playlist. For this purpose, you will have to use multiple Live playlists and use transitions.

Handling live source latency

VOD2Live outputs from Origin use the server wallclock time to determine the "live edge", which can cause players to buffer or stall when transitioning to a live source which has some delay due to contribution and encoding adding latency.

To counteract this live stream latency there is an option to delay all of the VOD2Live outputs for a channel.

This is configured on a per-channel basis as different channels might use live sources with different latency.

Find your live stream latency

You can use the /archive or /statistics endpoints on your live stream to check approximately how much latency there is on the stream itself. We do not need to check any latency added downstream of the Origin by CDN or player, as that does not impact the Virtual Channel transitioning process.

For example, checking the latency of one of our test live streams:

#!/bin/bash

curl --silent https://demo.unified-streaming.com/k8s/vc-perm-live-source/trunk/colourbars/colourbars.isml/archive | grep -E "content|end"

Which should look something like:

content="2022-11-22T16:37:13.335659Z">
<c start="2022-11-22T14:00:00Z" end="2022-11-22T16:37:03.360000Z" />
<c start="2022-11-22T14:00:00Z" end="2022-11-22T16:37:03.360000Z" />
<c start="2022-11-22T14:00:00Z" end="2022-11-22T16:37:03.360000Z" />
<c start="2022-11-22T14:00:00Z" end="2022-11-22T16:37:03.360000Z" />
<c start="2022-11-22T14:00:00Z" end="2022-11-22T16:37:03.360000Z" />

This shows the request was made at 16:37:13, and the live edge of all the media streams is 16:37:03, so there is approximately 10 seconds encoding latency.

Set a VOD2Live delay

Using the API you can configure a delay to be applied to all VOD2Live outputs for the channel. Do this by simplying PUTting the integer number of seconds to delay to the /channels/{channel_name}/delay endpoint.

For example:

#!/bin/bash

curl -X PUT -d 10 http://localhost:8000/channels/test_channel/delay

The API will respond with the set delay:

{"delay":10}

You can also use GET and DELETE verbs on the same endpoint to get or unset the delay for a channel respectively.

Content matching

HLS does not allow ABR ladders, tracks and encoding profiles to change at all mid-stream, and while DASH technically allows it in practice it doesn't work reliably.

This means it is important for all content being used for a Virtual Channel to match as closely as possible.

Normal encoder variations or intentional per-title encoding can cause your VOD content to vary in ways that make it hard to match.

However, because of the way Virtual Channel processes VOD playlists with Unified Remix it is possible to specify a desired output profile and pick the best fitting tracks from each source media.

Remix will use a set of heuristics to find the best possible fit for each track given the source media. For the best output it is best for the tracks to be fairly similar, for example, matching a single 30MBit 4K video track to other content using a full ABR ladder is unlikely to give the desired client experience.

By default, matching will be done using the first entry in any given SMIL playlist as the target profile, but best practice is to separately define a desired target profile and have every playlist processed to match it.

If you are using live sources, the best way to do this is to Capture a short clip from the live stream and use that as the target profile.

Otherwise, encode a short clip with the desired profile and use it as a reference.

Setting a target profile

Set the outputDescription meta element in the head of the SMIL playlist to a URL pointing to an ISOBMFF file of the desired target profile.

For example:

<?xml version='1.0' encoding='UTF-8'?>
<smil xmlns="http://www.w3.org/2001/SMIL20/Language">
  <head>
    <meta name="outputDescription"
      content="https://usp-vod2live.s3.amazonaws.com/Promo_Learning-ad-dref.mp4" />
      ...
  </head>
  <body>
    ...
  </body>
</smil>

Limitations

At the moment, the limitations mentioned for VOD2Live in the chapter Limitations, Scaling, Caching and DRM also apply to Virtual Channel's VOD2Live playlists.

If one or more of your VOD2Live playlist contain SCTE35 events and you are using transitions, you will have to manually take care of avoiding scheduling a transition at a time when a SCTE35 opportunity is programmed. In other words, if after a "CUE-OUT" event a transition happens, the corresponding "CUE-IN" event will be lost and this can lead to unexpected behaviour downstream.

Manifest Edit pipelines

Virtual Channel integrates Manifest Edit functionalities. It is suggested that you read the chapter Manifest Edit if you are not familiar with it, where you can find a general description as well as detailed instructions on how to write your own pipeline configuration files, with examples.

Briefly, Manifest Edit allows you to create customized versions of DASH and HLS manifests, by applying editing pipelines that combine one or more plugins from its Plugins Library.

Users define editing pipelines by means of yaml pipeline configuration files. The same pipeline configuration files used for the Origin can be used, with no changes, with Virtual Channel.

Virtual Channel's API includes specific endpoints to associate a pipeline configuration file (and thus a Manifest Edit use case) to a channel's manifest URI.

The simplest possibility is to associate a pipeline to the "default" channel's manifest URI (e.g. [...]/channel.isml/.mpd for DASH or [...]/channel.isml/.m3u8 for HLS). In this case, the channel's manifest will always be modified by the Use Case specified by the pipeline.

A more flexible alternative is to associate a pipeline to a channel's "variant" manifest URI. This works as a sort of "alias" that allows you to maintain separate URIs for the "original" unedited manifest and the edited one. An example of such "variant" may be to associate an mpd_use_case to the URI [...]/channel.isml/.mpd?python_pipeline_config=mpd_use_case. This URI will return a manifest modified by the mpd_use_case Manifest Edit pipeline, while the base URI [...]/channel.isml/.mpd would still return the original manifest.

This will be clarified further in the next sections.

Adding a pipeline to the base channel

You can associate a Manifest Edit use case to the base channel via the PUT /channels/{channel}/pipelines/{format} endpoint. Make sure that:

  • {channel} is the name of the channel you want to associate a pipeline to.

  • {format} specifies one of the supported formats (i.e. mpd, m3u8_main or m3u8_media).

  • the request body is a valid yaml configuration file

  • the Content-Type html header is set to one of the supported values (i.e. "text/yaml", "text/x-yaml" or "application/x-yaml")

Normally, {channel} would refer to an existing channel. Using a non-existing channel name is possible though. The operation would be successful but will have no effect. If and when the referred channel will be created, the pipeline will be associated with it.

This endpoints performs pipeline validation by checking that:

  • the yaml is syntactically valid

  • the format specified in the pipeline is coherent with the {format} string specified in the endpoint path (e.g. PUTting an m3u8 pipeline to an mpd endpoint would result in an error)

  • plugins mentioned in the pipeline are valid

  • each plugin has a correct related configuration section

415 or 422 are returned in case one or more of the above checks are not passed. On success, the endpoint returns 200 OK and the playout URI of the channel.

Notice that the PUT operation does not perform any check on previously existing pipelines for the same channel and will silently overwrite any existing ones.

Adding a pipeline to a channel "variant"

If you want to keep the chance to access both the original and an edited version of your channel's manifest, then you should use a channel variant.

Channel variants are also the right choice in case you need even more flexibility and be able to have access to several different versions of edited manifests at the same time through as many variants.

Associating a Manifest Edit use case to a channel variant with the PUT /channels/{channel}/pipelines/{format}/variants/{variant} endpoint. Make sure that:

  • {channel} is the name of the channel you want to associate a pipeline to.

  • {format} specifies one of the supported formats (i.e. mpd, m3u8_main or m3u8_media).

  • the request body is a valid yaml configuration file

  • the Content-Type html header is set to one of the supported values (i.e. "text/yaml", "text/x-yaml" or "application/x-yaml")

  • {variant} is a variant name of your choice. It will directly affect the playout URI, which is obtained by adding the query parameter python_pipeline_config={variant} to the base channel playout URI.

The same set of checks will be performed by this endpoint than in the case of a pipeline associated to the base channel.

You can create as many variants as needed. Notice that the PUT operation does not perform any check on previously existing pipelines for the same variant and will silently overwrite any existing ones.

Keeping track of pipelines and variants

You can retrieve at any time the pipeline configuration files associated to a given base channel or variant, for any specific format, through the endpoints

  • GET /channels/{channel}/pipelines/{format} (default pipeline)

  • GET /channels/{channel}/pipelines/{format}/variants/{variant}

To retrieve a list of all the variants for a specific channel and format and their associated pipeline configuration files, use the endpoint

  • GET /channels/{channel}/pipelines/{format}/variants

To get a comprehensive view of all pipelines (default and variant) and related pipeline configuration files for a channel and for all formats, use the endpoint

  • GET /channels/{channel}/pipelines

Deleting pipelines

The base channel's pipelines for a specific format can be deleted with the endpoint

  • DELETE /channels/{channel}/pipelines/{format}

A channel variant for a specific format can be deleted with the endpoint

  • DELETE /channels/{channel}/pipelines/{format}/variants/{variant}

When you delete a channel variant pipeline, the related playout URI simply disappears and returns 404.

When you delete the base channel pipeline, the related playout URI keeps working and just returns the original, unedited manifest.

Troubleshooting

Channel endpoints

Channel Endpoint

Status Code

Meaning

How to fix

PUT /channels/{channel}

415

Wrong body mime type.

Please provide an application/xml Content-Type header.

PUT /channels/{channel}

422

Your SMIL has a syntax error.

Check your XML syntax

PUT /channels/{channel}

400

Your SMIL is not valid.

Check the options in the head section. Check your body sectio

PUT /channels/{channel}

400

a channel with that name is Live already

Add a transition or use the force query parameter (running streams will break!!!).

PUT /channels/{channel}

503

There may be a running job already for the same channel

Wait for the job to reach the Success or Failed status and retry

DELETE /channels/{channel}

404

You are trying to delete a non-existing channel.

Check the channel name

DELETE /channels/{channel}

503

a channel creation/update job is running. Cannot delete right now.

Wait for the job to reach the Success or Failed status and retry

GET /channels/{channel}/status

404

The specified channel could not be found

Double-check the channel name

GET /channels/{channel}/smil

404

The specified channel could not be found

Double-check the channel name

GET /channels/{channel}/isml

404

The specified channel could not be found

Double-check the channel name

GET /channels/{channel}/logs/remix

404

The specified channel could not be found

Double-check the channel name

GET /channels/{channel}/logs/mp4split

404

The specified channel could not be found

Double-check the channel name

GET /channels/{channel}/logs

404

The specified channel could not be found

Double-check the channel name

GET /channels/{channel}

404

The specified channel could not be found

Double-check the channel name

GET /channels/

404

No channels have ever been created or they all have been deleted

Create a new channel

Transition endpoints

Transition Endpoint

Status Code

Meaning

How to fix

PUT /channels/{channel}/transitions/{transition}

415

Wrong body mime type.

Please provide an application/xml Content-Type header.

PUT /channels/{channel}/transitions/{transition}

422

Your SMIL has a syntax error.

Check your XML syntax

PUT /channels/{channel}/transitions/{transition}

400

Your SMIL is not valid.

Check the options in the head section. Check your body sectio

PUT /channels/{channel}/transitions/{transition}

400

a transition at the same time is Live already

Create a new transition instead or use the force query parameter (running streams will break!!!).

PUT /channels/{channel}/transitions/{transition}

400

Cannot process transition playlist, transition time <time> is in the past.

Choose a new transition time or use the force query parameter (running streams will break!!!).

PUT /channels/{channel}/transitions/{transition}

400

[...] vod2live_start_time=<time> is after the scheduled transition time <time>

Choose a new vod2live_start_time or transition time or use the force query parameter (running streams will break!!!).

PUT /channels/{channel}/transitions/{transition}

503

There may be a running job already for the same transition

Wait for the job to reach the Success or Failed status and retry

DELETE /channels/{channel}/transitions/{transition}

404

You are trying to delete a non-existing transition.

Check the transition name

DELETE /channels/{channel}/transitions/{transition}

503

a transition creation/update job is running. Cannot delete right now.

Wait for the job to reach the Success or Failed status and retry

GET /channels/{channel}/transitions/{transition}/status

404

The specified transition could not be found

Double-check the transition name

GET /channels/{channel}/transitions/{transition}/smil

404

The specified transition could not be found

Double-check the transition name

GET /channels/{channel}/transitions/{transition}/isml

404

The specified transition could not be found

Double-check the transition name

GET /channels/{channel}/transitions/{transition}/logs/remix

404

The specified transition could not be found

Double-check the transition name

GET /channels/{channel}/transitions/{transition}/logs/mp4split

404

The specified transition could not be found

Double-check the transition name

GET /channels/{channel}/transitions/{transition}/logs

404

The specified transition could not be found

Double-check the transition name

GET /channels/{channel}/transitions

404

The specified transition could not be found

Double-check the transition name

Manifest Edit endpoints

Manifest Edit Endpoint

Status Code

Meaning

How to fix

PUT /channels/{channel}/pipelines/{format}

415

Wrong body mime type.

Use Content-Type headers with values "text/yaml", "text/x-yaml" or "application/x-yaml"

PUT /channels/{channel}/pipelines/{format}/variants/{variant}

415

Wrong body mime type.

Use Content-Type headers with values "text/yaml", "text/x-yaml" or "application/x-yaml"

PUT /channels/{channel}/pipelines/{format}

422

Invalid yaml pipeline configuration.

Check the error's response body for further details of what needs fixing

PUT /channels/{channel}/pipelines/{format}/variants/{variant}

422

Invalid yaml pipeline configuration.

Check the error's response body for further details of what needs fixing

GET /channels/{channel}/pipelines/{format}

404

Cannot find pipeline for channel/format

Double-check the provided {channel} and {format}-yaml

GET /channels/{channel}/pipelines/{format}/variants/{variant}

404

Cannot find pipeline for channel/format/variant

Double-check the provided {channel}, {format} and {variant}.

GET /channels/{channel}/pipelines/{format}/variants

404

Cannot find pipeline for channel/format

Double-check the provided {channel} and {format}

GET /channels/{channel}/pipelines

404

Cannot find pipeline for channel

Double-check the provided {channel}.

DELETE /channels/{channel}/pipelines/{format}

404

Cannot find pipeline for channel/format

Double-check the provided {channel} and {format}

DELETE /channels/{channel}/pipelines/{format}/variants/{variant}

404

Cannot find pipeline for channel/format/variant

Double-check the provided {channel}, {format} and {variant}.