Remix VOD2Live

Overview

Remix VOD2Live allows you to schedule a rotating / looping playlist of VOD content to deliver it as a linear livestream. From a client perspective there is no difference between an Unified Origin delivered livestream that was generated through a Live encoder and one that was scheduled using Remix VOD2Live, with Origin offering the same features for delivering VOD2Live as it does for 'regular' livestreams. When clients request and play back a Remix VOD2Live scheduled livestream, they will join the stream at the live edge.

Use cases

  • One-off event channel (e.g., town hall meeting, pre-recorded product launch or concert)
  • Niche channel (e.g., rotating playlists of documentaries, gardening or home improvement TV)
  • Premium codec channel (Easily live stream Dolby VOD, or AV1)
  • Brand or product channel (e.g., example BMW channel with BMW sponsored movies and ads)
  • Trailer or barker channel (i.e., previews of newly released series/movies to entice people to start watching your VOD assets)
  • Advertising channel (e.g., TelSell)
  • Info channel (e.g., rotating presentation of current offers from service provider)
  • Test channel (e.g., for SCTE 35 testing purposes a VOD2Live channel with markers added provides a very stable and easy to manipulate testing environment)

Workflow

The solution makes use of the following two Unified Streaming Platform products:

  • Unified Remix to create a single presentation from multiple on-demand input sources, with a playlist that defines these sources serving as the input
  • Unified Origin - LIVE to deliver the stream in all supported output formats using just-in-time packaging, with support for on-the-fly encryption and DRM

A general Remix VOD2Live setup looks like below, with the SMIL Origin being a point of integration that's responsible for generating the playlists that schedule the livestream and serve as input for Remix:

../../../_images/vod2live.svg

Assuming you have a server with Origin Live set up and already running, the entire VOD2Live workflow consists of three relatively straightforward steps:

  • Create a SMIL playlist with VOD content that you want to livestream (the recommended maximum length is 24 hours)
  • Process the playlist using Remix, which will read all the source content and output a remixed MP4 that references the source content on a new, continuous timeline
  • Create a Live server manifest (.isml) with the remixed MP4 as input and the --vod2live option enabled to start delivery of the scheduled livestream through Origin

Create a looping / rotating playlist for VOD2Live

There is nothing specific about a SMIL playlist intended for VOD2Live purposes compared to playlists for other Remix use cases. The only difference being quantitative and not qualitative in kind: in many cases a playlist for VOD2Live is significantly longer (although a relatively short playlist for something like a prerecorded one-off livestreaming event makes sense, too).

The maximum recommended length of a playlist for VOD2Live purposes is 24 hours. For more detailed information on creating SMIL playlists for Remix, including how to add SCTE 35 markers, please refer to SMIL Playlists - Timed Metadata - SCTE 35.

Length of playlist

The recommended maximum length of the playlist is 24 hours. Longer playlists can be created but 24 hours provides a good balance between maintenance, user experience and performance expectations.

Improve playlist processing efficiency by using dref MP4's

The speed at which a playlist is processed by Remix can be increased significantly by using dref MP4's. In short, this means the workflow of creating a playlist will be as follows:

  • Prepare source content (align bit rate ladders across different assets and make sure their encoding profiles match as much as possible)
  • Create dref MP4's that reference source content, using --use_dref_no_subs
  • Create SMIL playlist that points to dref MP4's (instead of source content directly) that reference the source

Live edge within playlist

Remix VOD2Live is set up in such a way that it will loop the playlist. Which point in the playlist is considered the live edge at a given point in time depends on the start time and length of the playlist. The live edge is the point in the playlist within the current loop (with the first loop starting at the s specified start time of the livestream).

Or, take the example of a playlist of 10 hours with a start time of 9 'o clock in the morning: at noon the live edge will be 3 hours into the playlist, whereas at 9 'o clock in the evening, the live edge of the stream will be 2 hours into the playlist, because the playlist has gone through one full loop already.

Reloading playlist

Remix VOD2Live does not support updating the scheduled livestream while it is being delivered. A restart of the stream (with an updated or completely new playlist) is required. There are two methods to initiate such a channel update that we recommend.

Choice switch of channel

As a VOD2Live scheduled livestream does not generate load when there are no viewers, one approach to updating a channel is to create a new one next to the one that already exists and simply let viewers jump over to the new channel by choice.

Forced switch of channel

The second approach to updating a channel is to force viewers to move to the new channel. The options for forcing viewers depend on your level of control over your infrastructure and player. Our suggestion is to simply (re)move the Live server manifest (.isml) that serves as the endpoint for Origin to stream from. This will cause Origin to serve a 410 (Gone) on any subsequent requests for the stream. As part of this approach the player should be configured in such a way that it will respond to the 410 by asking the CMS for an updated URL to the channel.

More complex implementations of the 'forced switch' scenario may be implemented given enough control environment, e.g., SCTE 35 markers may be used to signal a player to move/jump to an updated channel, or the revision parameter on the location header may be changed for a similar instruction.

Process a VOD2Live playlist with Remix

Like creating the playlist, processing it with Remix isn't any different for VOD2Live purposes either:

#!/bin/bash

unified_remix -o remixed.mp4 vod2live.smil

Note

Frame accurate clipping of source material is supported as well, as explained in Requirements - Conditioning Media (but note that Intel Media SDK is a requirement).

Set up a VOD2Live channel with Origin

--vod2live

To set up a VOD2Live channel from a remixed MP4 instead of VOD server manifest (.ism) you need to create a Live server manifest (.isml), and make sure to specify --dvr_window_length and add the --vod2live option (all other Live ingest options, such as those related to archiving, are irrelevant):

 #!/bin/bash

 mp4split -o vod2live.isml \
   --vod2live \
   --dvr_window_length=600 \
   --hls.client_manifest_version=4 \
   --hls.no_multiplex \
   remixed.mp4

That's it, you have now set up a VOD2Live channel. If your Live server manifest is available as an endpoint through Origin, and Origin has access to both the remixed MP4 and the source media that it references, a livestream is generated by Origin in the desired output format, when requested by client (see Player URLs for more info).

Note

When using a remixed MP4 as source, Unified Origin automatically signals DASH AVC content with a codec ID of avc3 (i.e., using in-band parameter sets).

If this does not meet your requirements the --no_inband_parameter_sets option can be used to switch the codec ID to avc1 (i.e., using out-of-band parameter sets).

This is often a requirement for SSAI workflows or legacy playback devices where the handing of or creation of media with in-band codec parameters is not fully supported.

Scheduling a start time

One of the fundamental concepts of a live linear channel is the capabilty to schedule content for playout at a specific point in time. A use case could be owning the exclusive rights to premier a new movie and wish to schedule this at a time when the most viewers can watch it, like 9 'o clock on a Friday night.

When generating your server manifest you schedule the start time using the option --vod2live_start_time.

--vod2live_start_time

Warning

Currently, this option only sets the time at which a stream becomes available (i.e., before the specified time any request will be responded to with a 404). It does not ensure that the stream will start at the beginning of the playlist at the specified time.

Using this option when creating your server manifest restricts the availability time of the channel. Defaults to the time at which the Live server manifest is created.

If the VOD2Live channel has been set up and a request is made to Origin before the specified start time, the client receives a 404 and a log message (FMP4_404 VOD2Live starts at 2021-03-22T21:00:00Z) is written to the Apache error log.

The given time must be formatted as either ISO 8601 (2021-03-22T21:00:00Z) or seconds since Unix epoch (1616446800):

 #!/bin/bash

 mp4split -o vod2live.isml \
   --vod2live \
   --vod2live_start_time=2021-03-22T21:00:00Z \
   --dvr_window_length=600 \
   --hls.client_manifest_version=4 \
   --hls.no_multiplex \
   remixed.mp4

Attention

It is important to note that timing is specified in UTC (Universal Time). Do not forget to convert local times to UTC.

Insert SCTE 35 for Dynamic Ad Replacement

For ad supported delivery of content you can simply include ads in the playlist that you use for your VOD2Live workflow.

If you would like to integrate with a third-party ad service for dynamic ad replacement, then Remix VOD2Live also supports inserting SCTE 35 markers. This works similarly to Remix AVOD. For Remix VOD2Live the SCTE 35 markers define the content to be replaced in the playlist.

Keep in mind that both the --timed_metadata and --splice_media need to be enabled when creating the Live server manifest from the remixed MP4. Otherwise, Origin will not include the SCTE 35 Timed Metadata in its output and not slice media segments to align segment boundaries with SCTE 35 cue points either:

 #!/bin/bash

 mp4split -o vod2live.isml \
   --vod2live \
   --dvr_window_length=600 \
   --hls.client_manifest_version=4 \
   --hls.no_multiplex \
   --splice_media \
   --timed_metadata \
   remixed.mp4

The SCTE 35 markers are defined in the playlist. Depending on which part of the playlist you would like to mark as a content replacement opportunity there are two ways of specifying the markers.

Marking a full clip for content replacement

If the content you want replaced is a full clip, then the recommended way is to add two SCTE 35 splice_insert() markers. This pair of markers must share the same spliceEventId.

The first marker has the SpliceInsert@outOfNetworkIndicator field set to 1 (CUE-OUT) and is defined in the clip that is replaced (the start of the slate). The optional field BreakDuration is not used. The second marker has the SpliceInsert@outOfNetworkIndicator field set to 1 (CUE-IN) and is defined in the next clip (the return to the main content).

There is no need to specify the Event@presentation_time for either marker, since both default to the beginning of the clip. The Event@duration shouldn't be specified. When the duration field is unspecified, then Remix calculates the duration of the break. This is important, since Remix aligns the clips for concatenating and this may alter the durations slightly.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<?xml version='1.0' encoding='UTF-8'?>
<smil
  xmlns="http://www.w3.org/2001/SMIL20/Language">
  <head />
  <body>
    <seq>
      <par>
        <video src="asset1.mp4" />
      </par>
      <par>
        <video src="slate_30_seconds.mp4" />
        <EventStream
          xmlns="urn:mpeg:dash:schema:mpd:2011"
          schemeIdUri="urn:scte:scte35:2014:xml+bin">
          <Event>
            <Signal
              xmlns="http://www.scte.org/schemas/35/2016">
              <SpliceInfoSection>
                <SpliceInsert
                  spliceEventId="4157"
                  outOfNetworkIndicator="1"
                  spliceImmediateFlag="1">
                  <Program />
                </SpliceInsert>
              </SpliceInfoSection>
            </Signal>
          </Event>
        </EventStream>
      </par>
      <par>
        <video src="asset2.mp4" />
        <EventStream
          xmlns="urn:mpeg:dash:schema:mpd:2011"
          schemeIdUri="urn:scte:scte35:2014:xml+bin">
          <Event>
            <Signal
              xmlns="http://www.scte.org/schemas/35/2016">
              <SpliceInfoSection>
                <SpliceInsert
                  spliceEventId="4157"
                  outOfNetworkIndicator="0"
                  spliceImmediateFlag="1">
                  <Program />
                </SpliceInsert>
              </SpliceInfoSection>
            </Signal>
          </Event>
        </EventStream>
      </par>
    </seq>
  </body>
</smil>

Marking a part of a clip for content replacement

If the content you want replaced is only a segment of the full clip, then an Auto Return Mode break is signaled using a single SCTE 35 splice_insert() marker.

The marker has the SpliceInsert@outOfNetworkIndicator field set to 1 (CUE-OUT) and the BreakDuration@autoReturn field is set to 1 (CUE-IN).

The Event@presentation_time specifies the start time of the break in the clip. The Event@duration must be set to the duration of the break.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?xml version='1.0' encoding='UTF-8'?>
<smil
  xmlns="http://www.w3.org/2001/SMIL20/Language">
  <head />
  <body>
    <seq>
      <par>
        <video src="asset1.mp4" />
      </par>
      <par>
        <video src="asset2_including_30_second_preroll.mp4" />
        <EventStream
          xmlns="urn:mpeg:dash:schema:mpd:2011"
          schemeIdUri="urn:scte:scte35:2014:xml+bin">
          <Event
            presentationTime="0"
            duration="30">
            <Signal
              xmlns="http://www.scte.org/schemas/35/2016">
              <SpliceInfoSection>
                <SpliceInsert
                  spliceEventId="4157"
                  outOfNetworkIndicator="1"
                  spliceImmediateFlag="1">
                  <Program />
                  <BreakDuration
                    autoReturn="1"
                    duration="2700000" />
                </SpliceInsert>
              </SpliceInfoSection>
            </Signal>
          </Event>
        </EventStream>
      </par>
    </seq>
  </body>
</smil>

Re-use SCTE-35 events from a live stream

Unified Remix benefits from not only being able to create new SCTE-35 events (as described above) but also re-use any SCTE-35 events in your source media.

Remix VOD2Live can be incorporated into any existing Remix nPVR workflow where normally the remixed asset would be presented as a VOD clip, instead now can be presented "as-live".

An nPVR archive would store multiple clips over a given time-range that's been captured from a live channel. If the live channel is already conditioned with SCTE-35 based ad replacement opportunities, these would be present within the source clips when captured using unified_capture against the DASH presentation.

Below is an example of how existing SCTE-35 events can be re-used.

Capture the source stream

With a live stream running, we're identified a portion of the live event we'd like to capture between 11:59:50 and 12:00:30. This existing live stream contains a SCTE-35 ad-replacement opportinity at 12:00:00.

So we capture the clip using unified_capture.

1
2
3
4
unified_capture \
--remix \
-o captured-clip.mp4 \
"http://live.unified-streaming.com/scte35/scte35.isml/.mpd?vbegin=2021-04-07T11:59:50Z&vend=2021-04-07T12:00:30Z"

The SCTE-35 event capture can then be verified using mp4split.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
$ mp4split -v0 -o stdout:.xml captured-clip.mp4
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Unified Streaming Platform  (version=1.11.0-24004) -->
<smil
  xmlns="http://www.w3.org/2001/SMIL20/Language">
  <body>
    <seq>
      <par>
        <EventStream
          xmlns="urn:mpeg:dash:schema:mpd:2011"
          schemeIdUri="urn:scte:scte35:2013:xml"
          timescale="1">
          <!-- 2021-04-07T12:00:00Z -->
          <Event
            presentationTime="1617796800"
            duration="19"
            id="917">
            <Signal
              xmlns="http://www.scte.org/schemas/35/2016">
              <SpliceInfoSection>
                <SpliceInsert
                  spliceEventId="917"
                  outOfNetworkIndicator="1"
                  spliceImmediateFlag="1"
                  uniqueProgramId="49152"
                  availNum="0"
                  availsExpected="0">
                  <Program>
                  </Program>
                  <BreakDuration
                    autoReturn="1"
                    duration="1710000" />
                </SpliceInsert>
              </SpliceInfoSection>
            </Signal>
          </Event>
        </EventStream>
      </par>
    </seq>
  </body>
</smil>

Remix the captured clip

We can now use captured-clip.mp4 as an input to unified_remix using a SMIL file below to create a new remixed-clip.mp4. The stdout messaging from unifed_remix will signal the presence of a SCTE-35 with a statement Event Messages received.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$ cat remixed-clip.smil
<?xml version="1.0" encoding="UTF-8"?>
<smil xmlns="http://www.w3.org/2001/SMIL20/Language">
  <body>
    <seq>
        <video src="capture-clip.mp4" />
    </seq>
  </body>
</smil>

$ unified_remix -o remixed-clip.mp4 remixed-clip.smil
unified_remix version=1.11.0 (24004)    Copyright 2015-2021 CodeShop B.V.

I0.000 input: file:///data/remixed-clip.smil
I0.000 output: file:///data/remixed-clip.mp4
I0.027 Target track selection set:
I0.027 [1/2]: id=1 timescale=48000 lang=und
I0.027 soun/mp4a dref=1 bitrate=69000/69000 tag=255 samplerate=48000 channels=1 sample_size=16 packet_size=2
I0.027 [2/2]: id=2 timescale=90000 lang=und
I0.027 vide/avc1 dref=1 bitrate=700000/493000 size=1280x720 sar=1:1 dar=16:9 codecs=avc1.64001F
I0.028 event id=917 (scheme_id=urn:scte:scte35:2013:bin): presentationTime=00:00:10.000000(10/1) -> 00:00:08.405333(756480/90000)
I0.028 event id=917 (scheme_id=urn:scte:scte35:2013:bin): duration=00:00:19.000000(19/1) -> 00:00:19.200000(96/5)
I0.028 [1/2]: movie=00:00:00.000000
I0.028 [2/2]: movie=00:00:00.005333
I0.029 [1/2]: movie=00:00:40.000000
I0.029 [2/2]: movie=00:00:40.005333
I0.029 emsg[917] presentation_time=756480 duration=1728000/90000
I0.029 1 Event Messages received of which 1 are unique.
I0.029 stat: url=file:///data/remixed-clip.smil, reads=1, size=197 bytes
I0.029 stat: url=file:///data/captured-clip.mp4, reads=3, size=91 KB
I0.029 writing 5 buckets for a total of 21 KB
I0.067 total running time is 0.067135 seconds
Status: 200 FMP4_OK

Generate the server manifest

Next we create a vod2Live server manifest with the required --timed_metadata and --splice_media options to support the signalling of SCTE-35 events in the client manifests.

The stdout from mp4split will signal the presence of a meta track contained in the source.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
$ mp4split -o vod2live-remixed-clip.isml \
--vod2live \
--dvr_window_length=30 \
--archiving=false \
--hls.client_manifest_version=4 \
--hls.minimum_fragment_length=48/25 \
--timed_metadata --splice_media \
remixed-clip.mp4

mp4split version=1.11.0 (24004)    Copyright 2007-2021 CodeShop B.V.

I0.015 Manifest file:///data/vod2live-remixed-clip.isml
I0.030 Track 1:
I0.030 src=remixed-clip.mp4
I0.030 audio bitrate=69000 name=audio
I0.030 id=1 timescale=48000 lang=und
I0.030 soun/mp4a dref=1 bitrate=69000/69000 tag=255 samplerate=48000 channels=1 sample_size=16 packet_size=2
I0.030 soun/mp4a dref=2 (captured-clip.mp4) bitrate=69000/69000 tag=255 samplerate=48000 channels=1 sample_size=16 packet_size=2
I0.030 Track 2:
I0.030 src=remixed-clip.mp4
I0.030 video bitrate=700000/493000 name=video
I0.030 id=2 timescale=90000 lang=und
I0.030 vide/avc1 dref=1 bitrate=700000/493000 size=1280x720 sar=1:1 dar=16:9 codecs=avc1.64001F
I0.030 vide/avc1 dref=2 (captured-clip.mp4) bitrate=700000/493000 size=1280x720 sar=1:1 dar=16:9 codecs=avc1.64001F
I0.030 Track 3:
I0.030 src=remixed-clip.mp4
I0.030 meta bitrate=1000 name=meta
I0.030 id=3 timescale=375 lang=und
I0.030 scheme_id=urn:scte:scte35:2013:bin
I0.030 meta/urim dref=1 bitrate=1000/0
I0.032 writing 1 buckets for a total of 2390 bytes
I0.060 stat: url=file:///data/remixed-clip.mp4, reads=1, size=21 KB
I0.060 stat: url=file:///data/captured-clip.mp4, reads=1, size=20 KB
Status: 200 FMP4_OK

Request the 'as-live' client manifest

The 30second captured clip containing the existing SCTE-35 ad-replacement opporunities can now be played out 'as-live' in a continuous loop.

The example manifest below shows the previous SCTE-35 event being re-used as part of the 'as-live' stream. Where the necessary timing information for both the source clip and required presentationTime of the event have been realigned as part of the live stream.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
$ mp4split -v0 -o stdout:.xml vod2live-remixed-clip.isml/.mpd
<?xml version="1.0" encoding="utf-8"?>
<!-- Created with Unified Streaming Platform  (version=1.11.0-24004) -->
<MPD
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns="urn:mpeg:dash:schema:mpd:2011"
  xsi:schemaLocation="urn:mpeg:dash:schema:mpd:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
  type="dynamic"
  availabilityStartTime="1970-01-01T00:00:00Z"
  publishTime="2021-04-07T13:02:43.874153Z"
  minimumUpdatePeriod="PT2S"
  timeShiftBufferDepth="PT30S"
  maxSegmentDuration="PT3S"
  minBufferTime="PT10S"
  profiles="urn:mpeg:dash:profile:isoff-live:2011,urn:hbbtv:dash:profile:isoff-live:2012">
  <Period
    id="1"
    start="PT0S">
    <BaseURL>dash/</BaseURL>
    <EventStream
      schemeIdUri="urn:scte:scte35:2014:xml+bin"
      timescale="720000">
      <!-- 2021-04-07T13:02:06.384000Z -->
      <Event
        presentationTime="1164816378996480"
        duration="13824000"
        id="353014667">
        <Signal
          xmlns="http://www.scte.org/schemas/35/2016">
          <Binary>/DAgAAAAAAAAAP/wDwUAAAOVf//+ABoXsMAAAAAAACt+1iQ=</Binary>
        </Signal>
      </Event>
    </EventStream>
    <AdaptationSet
      id="1"
      group="1"
      contentType="audio"
      segmentAlignment="true"
      audioSamplingRate="48000"
      mimeType="audio/mp4"
      codecs="mp4a.40.2"
      startWithSAP="1">
      <AudioChannelConfiguration
        schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011"
        value="1" />
      <InbandEventStream
        schemeIdUri="urn:scte:scte35:2014:xml+bin">
      </InbandEventStream>
      <Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
      <SegmentTemplate
        timescale="48000"
        initialization="vod2live-remixed-clip-$RepresentationID$.dash"
        media="vod2live-remixed-clip-$RepresentationID$-$Time$.dash">
        <!-- 2021-04-07T13:02:13.978666Z / 1617800533 - 2021-04-07T13:02:44Z -->
        <SegmentTimeline>
          <S t="77654425630976" d="96256" r="2" />
          <S d="95232" />
          <S d="96256" />
          <S d="76800" />
          <S d="115712" />
          <S d="95232" />
          <S d="96256" r="2" />
          <S d="95232" />
          <S t="77654426783232" d="96256" r="2" />
        </SegmentTimeline>
      </SegmentTemplate>
      <Representation
        id="audio=69000"
        bandwidth="69000">
      </Representation>
    </AdaptationSet>
    <AdaptationSet
      id="2"
      group="2"
      contentType="video"
      par="16:9"
      segmentAlignment="true"
      width="1280"
      height="720"
      sar="1:1"
      frameRate="25"
      mimeType="video/mp4"
      codecs="avc3.64001F"
      startWithSAP="1">
      <InbandEventStream
        schemeIdUri="urn:scte:scte35:2014:xml+bin">
      </InbandEventStream>
      <Role schemeIdUri="urn:mpeg:dash:role:2011" value="main" />
      <SegmentTemplate
        timescale="600"
        initialization="vod2live-remixed-clip-$RepresentationID$.dash"
        media="vod2live-remixed-clip-$RepresentationID$-$Time$.dash">
        <!-- 2021-04-07T13:02:14.063333Z / 1617800534 - 2021-04-07T13:02:44.468333Z -->
        <SegmentTimeline>
          <S t="970680320438" d="1152" r="11" />
          <S d="528" />
          <S t="970680334793" d="1584" />
          <S d="1152" r="1" />
        </SegmentTimeline>
      </SegmentTemplate>
      <Representation
        id="video=700000"
        bandwidth="700000"
        scanType="progressive">
      </Representation>
    </AdaptationSet>
  </Period>
  <UTCTiming
    schemeIdUri="urn:mpeg:dash:utc:http-iso:2014"
    value="https://time.akamai.com/?iso" />
</MPD>

Note

When capturing and re-using SCTE-35 events as part of an nPVR, AVOD or VOD2Live based workflow the same requirements apply.

Such as ensuring your source SCTE-35 event aligns with IDR video frames and/or segment boundaries. If not, remix will automatically update the desired presentationTime and duration to align the valid boundaries.

If the SCTE-35 event spans 2 archive clips, both clips need to be referenced as sources within the remix smil (necessary clipBegin or clipEnd timing can also be applied).

Limitations, scaling, caching and DRM

As stated before, a VOD2Live produced livestream is functionally the same as a regular livestream.

Scaling and caching of VOD2Live

Scaling the delivery of a VOD2Live produced livestream should be approached in the same way as scaling a regular livestream:

  • Scaling is done through caching (shield cache and CDN)
  • Adding more tracks to a stream (e.g., different video bit rates, different languages) may increase load, as this may generate more unique requests by end users
  • Configuring a longer DVR window may increase load, as this may generate more unique requests by end users

In addition to the above, the use Prefetch headers provided by Origin is recommended to allow caches to prefetch media segments and get them as soon as they're available.

Note

Simply pre-caching of a (big part of a) VOD2Live livestream before you make it available may seem like an attractive option, but is not recommended. For one, simply pulling (part of) the livestream through your caches won't work because the timing information and potential SCTE 35 markers inside those segments won't match those that Origin will generate when the stream will be made available at a later time. Second, if the time of the server would be adjusted to take this into account, there is still the problem of security, as the stream will now be present on a potentially publicly shared location (e.g., a CDN).

Scaling the input of a VOD2Live produced livestream on the other hand, works different than for a regular livestream, as you're working with VOD assets instead of a Live ingest as input. This means that on the storage side, scaling recommendations follow those of a VOD setup (i.e., Unified Origin - Recommendations for VOD).

Considerations on input for VOD2Live

On the input side of things, requirements for VOD2Live are similar as for other Remix use cases. That is: available languages, bit rate ladders and encoding profiles should match as much as possible across the different VOD assets used as input. See also:

DRM protection and VOD2Live

In addition, it is good to know that input of DRM protected content is not supported, but adding DRM protection to a VOD2Live produced livestream is. That is, all of the DRM related functionality supported by Origin is available to use.

Limitations of VOD2Live

On the output side, a VOD2Live produced livestream is functionally the same as a regular livestream. The only two features that are currently not supported Virtual subclips and --time_shift.

Also, as of yet there is no way to specify an end time of a stream and it will keep looping if you leave it running. However, simply removing the Live server manifest (.isml) from the web server will make the stream unavailable and thus have the same effect.

Hands-on

The following demo is based on Your own Video on Demand demo. Getting a working VOD2Live stream up and running using this hands-on requires a few things:

  • A license key that includes VOD2Live, which can be obtained after registration
  • A working copy of Docker, installed on the system that will act as the host for this hands-on
  • Internet access on host through ports 53 and 80; needed to check license key

Downloading VOD demo content

For the demo content, download below file:

http://repository.unified-streaming.com/tears-of-steel.zip

After you have downloaded the file, extract it to a directory with the name tears-of-steel.

You should now have a directory called tears-of-steel, which contains the demo files (see Verify Your Setup for an overview of the media content).

Store SMIL playlist inside directory with the VOD demo content

To create a VOD2Live you'll need a playlist. For the purpose of this hands-on, you can use the playlist below, which you'll need to download vod2live_hands_on.smil to the tears-of-steel directory that the VOD demo content resides in:

<?xml version="1.0" encoding="UTF-8"?>
<smil xmlns="http://www.w3.org/2001/SMIL20/Language">
  <head>
  </head>
  <body>
    <seq>
      <par>
        <video src="tears-of-steel-avc1-1000k.mp4" />
        <video src="tears-of-steel-avc1-1500k.mp4" />
        <video src="tears-of-steel-avc1-750k.mp4" />
        <video src="tears-of-steel-avc1-400k.mp4" />
        <video src="tears-of-steel-aac-128k.mp4" />
        <video src="tears-of-steel-aac-64k.mp4" />
        <video src="tears-of-steel-en.cmft" />
        <video src="tears-of-steel-zh-hans.cmft" />
      </par>
    </seq>
  </body>
</smil>

Note

Make sure the name of SMIL playlist file as stored in your tears-of-steel directory is vod2live_hands_on.smil.

Running the demo using Docker

Now that all the prerequisites to run your own VOD2Live stream are in place, the last thing you need to do is running the commands to:

  • Process SMIL playlist with Unified Remix
  • Create VOD2Live enabled Live server manifest with mp4split
  • Spin up a container running Unified Origin to serve VOD2Live stream

To do this, you'll need to:

  • Download vod2live_hands_on.sh to your tears-of-steel directory
  • Run chmod +x vod2live_hands_on.sh in your shell to make it executable
  • Store your USP license key to an environment variable using export USP_LICENSE_KEY=<your-actual-license-key>
  • And, finally: run ./vod2live_hands_on.sh to actually execute the script
#!/bin/bash

# Process SMIL playlist with Unified Remix
docker run --rm --entrypoint unified_remix \
  -v ${PWD}:/var/www/unified-origin \
  -w /var/www/unified-origin \
  unifiedstreaming/packager:1.11.0 \
  --license-key=${USP_LICENSE_KEY} \
  -o remixed.mp4 vod2live_hands_on.smil

if [ $? != 0 ];
then
    echo "Processing of SMIL did not succeed, exiting script."
    exit 1
fi

# Create VOD2Live enabled Live server manifest with mp4split
docker run --rm --entrypoint mp4split \
  -v ${PWD}:/var/www/unified-origin \
  -w /var/www/unified-origin \
  unifiedstreaming/packager:1.11.0 \
  --license-key=${USP_LICENSE_KEY} \
  -o vod2live.isml \
  --vod2live \
  --dvr_window_length=600 \
  --hls.client_manifest_version=4 \
  --hls.no_multiplex \
  remixed.mp4

if [ $? != 0 ];
then
    echo "Creation of Live server manifest did not succeed, exiting script."
    exit 2
fi

# Spin up a container running Unified Origin to serve VOD2Live stream
docker run --rm -d -e USP_LICENSE_KEY \
  -v ${PWD}:/var/www/unified-origin -p ${DOCKER_HOST_PORT:-80}:80 \
  unifiedstreaming/origin:1.11.0

if [ $? == 0 ];
then
    echo "Locally available URL of DASH stream: localhost:${DOCKER_HOST_PORT:-80}/vod2live.isml/.mpd"
    echo "Locally available URL of HLS stream: localhost:${DOCKER_HOST_PORT:-80}/vod2live.isml/.m3u8"
    exit 0
else
    echo "Something went wrong spinning up container running Unified Origin, exiting script."
    exit 3
fi

Now, all you have to do is opening the following URL in your browser to play the VOD2Live stream that you have just set up:

http://localhost/?http://localhost/vod2live.isml/.mpd

Note

Please use a localhost port that is available on your host. The default in the script above is 80, but if you need to adjust that you can do so by setting the DOCKER_HOST_PORT variable to a value of your choice before running the script, e.g., export DOCKER_HOST_PORT=8080.