Hands-on and Demos

Preparing Content

We need some VOD content to use for the VOD2Live stream, for this tutorial we will use the Tears of Steel video which can be downloaded from from the following URL:

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

and should be unzipped to /var/www/tears-of-steel.

SMIL Playlist

We need to create a SMIL playlist that can be used by Unified Remix.

The playlist we will use just lists the different video, audio, and subtitle tracks of Tears of Steel.

<?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>

This file can be created like so:

#!/bin/bash

cat <<EOF > /var/www/tears-of-steel/vod2live_hands_on.smil
<?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>
EOF

Note

You can use your own content from S3 by referring to it by URL. See Remote manifests for more details.

Create Remix MP4

The SMIL file is used by Unified Remix to create a reference MP4 that can be used by Unified Origin to produce the output streams.

#!/bin/bash

unified_remix -o /var/www/tears-of-steel/vod2live_hands_on.mp4 \
  /var/www/tears-of-steel/vod2live_hands_on.smil

Which should give output looking like:

unified_remix version=1.11.3 (24483)    Copyright 2015-2021 CodeShop B.V.

I0.000 input: file:///var/www/tears-of-steel/vod2live_hands_on.smil
I0.000 output: file:///var/www/tears-of-steel/vod2live_hands_on.mp4
I0.018 Target track selection set:
I0.018 [1/8]: id=1 timescale=48000 lang=en
I0.018 soun/mp4a dref=1 bitrate=64000/64000 tag=255 samplerate=48000 channels=2 sample_size=16 packet_size=4
I0.018 [2/8]: id=2 timescale=48000 lang=en
I0.018 soun/mp4a dref=1 bitrate=128000/128000 tag=255 samplerate=48000 channels=2 sample_size=16 packet_size=4
I0.018 [3/8]: id=3 timescale=1000 lang=en
I0.018 subt/stpp dref=1 bitrate=1000/0 codecs=stpp.ttml.im1t
I0.018 [4/8]: id=4 timescale=1000 lang=zh-Hans
I0.018 subt/stpp dref=1 bitrate=1000/0 codecs=stpp.ttml.im1t
I0.018 [5/8]: id=5 timescale=12288 lang=en
I0.018 vide/avc1 dref=1 bitrate=400000/1008000 size=224x100 sar=1:1 dar=56:25 codecs=avc1.42C014
I0.018 [6/8]: id=6 timescale=12288 lang=en
I0.018 vide/avc1 dref=1 bitrate=751000/2190000 size=448x200 sar=1:1 dar=56:25 codecs=avc1.42C016
I0.018 [7/8]: id=7 timescale=12288 lang=en
I0.018 vide/avc1 dref=1 bitrate=1001000/3581000 size=784x350 sar=1:1 dar=56:25 codecs=avc1.4D401F
I0.018 [8/8]: id=8 timescale=12288 lang=en
I0.018 vide/avc1 dref=1 bitrate=1501000/6642000 size=1680x750 sar=1:1 dar=56:25 codecs=avc1.640028
I0.018 skipped matching of tracks (use 1:1 mapping)
I0.018 [1/8]: id=1 timescale=48000 lang=en
I0.018 soun/mp4a dref=1 (tears-of-steel-aac-64k.mp4) bitrate=64000/64000 tag=255 samplerate=48000 channels=2 sample_size=16 packet_size=4
I0.018   file:///var/www/tears-of-steel/tears-of-steel-aac-64k.mp4
I0.019 [2/8]: id=1 timescale=48000 lang=en
I0.019 soun/mp4a dref=1 (tears-of-steel-aac-128k.mp4) bitrate=128000/128000 tag=255 samplerate=48000 channels=2 sample_size=16 packet_size=4
I0.019   file:///var/www/tears-of-steel/tears-of-steel-aac-128k.mp4
I0.021 [3/8]: id=1 timescale=1000 lang=en
I0.021 scheme_id=http://unified-streaming.com/ns/2019/ttml#no-timing
I0.021 subt/stpp dref=1 bitrate=1000/0 codecs=stpp.ttml.im1t
I0.021   file:///var/www/tears-of-steel/tears-of-steel-en.cmft
I0.021 [4/8]: id=1 timescale=1000 lang=zh-Hans
I0.021 scheme_id=http://unified-streaming.com/ns/2019/ttml#no-timing
I0.021 subt/stpp dref=1 bitrate=1000/0 codecs=stpp.ttml.im1t
I0.021   file:///var/www/tears-of-steel/tears-of-steel-zh-hans.cmft
I0.021 [5/8]: id=1 timescale=12288 lang=en
I0.021 vide/avc1 dref=1 (tears-of-steel-avc1-400k.mp4) bitrate=400000/1008000 size=224x100 sar=1:1 dar=56:25 codecs=avc1.42C014
I0.021   file:///var/www/tears-of-steel/tears-of-steel-avc1-400k.mp4
I0.022 [6/8]: id=1 timescale=12288 lang=en
I0.022 vide/avc1 dref=1 (tears-of-steel-avc1-750k.mp4) bitrate=751000/2190000 size=448x200 sar=1:1 dar=56:25 codecs=avc1.42C016
I0.022   file:///var/www/tears-of-steel/tears-of-steel-avc1-750k.mp4
I0.023 [7/8]: id=1 timescale=12288 lang=en
I0.023 vide/avc1 dref=1 (tears-of-steel-avc1-1000k.mp4) bitrate=1001000/3581000 size=784x350 sar=1:1 dar=56:25 codecs=avc1.4D401F
I0.023   file:///var/www/tears-of-steel/tears-of-steel-avc1-1000k.mp4
I0.024 [8/8]: id=1 timescale=12288 lang=en
I0.024 vide/avc1 dref=1 (tears-of-steel-avc1-1500k.mp4) bitrate=1501000/6642000 size=1680x750 sar=1:1 dar=56:25 codecs=avc1.640028
I0.024   file:///var/www/tears-of-steel/tears-of-steel-avc1-1500k.mp4
I0.026 [1/8]: movie=00:00:00.000000
I0.026 [2/8]: movie=00:00:00.000000
I0.026 [3/8]: movie=00:00:00.000000
I0.026 [4/8]: movie=00:00:00.000000
I0.026 [5/8]: movie=00:00:00.000000
I0.026 [6/8]: movie=00:00:00.000000
I0.026 [7/8]: movie=00:00:00.000000
I0.026 [8/8]: movie=00:00:00.000000
I0.045 [1/8]: movie=00:12:13.979000
I0.045 [2/8]: movie=00:12:13.979000
I0.045 [3/8]: movie=00:09:27.000000
I0.045 [4/8]: movie=00:09:27.000000
I0.045 [5/8]: movie=00:12:14.000000
I0.045 [6/8]: movie=00:12:14.000000
I0.045 [7/8]: movie=00:12:14.000000
I0.045 [8/8]: movie=00:12:14.000000
I0.045 stat: url=file:///var/www/tears-of-steel/vod2live_hands_on.smil, reads=1, size=602 bytes
I0.045 stat: url=file:///var/www/tears-of-steel/tears-of-steel-avc1-1000k.mp4, reads=3, size=262 KB
I0.045 stat: url=file:///var/www/tears-of-steel/tears-of-steel-avc1-1500k.mp4, reads=3, size=271 KB
I0.045 stat: url=file:///var/www/tears-of-steel/tears-of-steel-avc1-750k.mp4, reads=3, size=144 KB
I0.045 stat: url=file:///var/www/tears-of-steel/tears-of-steel-avc1-400k.mp4, reads=3, size=145 KB
I0.045 stat: url=file:///var/www/tears-of-steel/tears-of-steel-aac-128k.mp4, reads=3, size=208 KB
I0.045 stat: url=file:///var/www/tears-of-steel/tears-of-steel-aac-64k.mp4, reads=3, size=211 KB
I0.045 stat: url=file:///var/www/tears-of-steel/tears-of-steel-en.cmft, reads=1, size=17 KB
I0.045 stat: url=file:///var/www/tears-of-steel/tears-of-steel-zh-hans.cmft, reads=1, size=17 KB
I0.047 writing 291 buckets for a total of 965 KB
I0.048 total running time is 0.048882 seconds
Status: 200 FMP4_OK

This information log shows Remix looking at all of the media files referenced in the SMIL playlist, reading all of the relevant metadata, and then creating a new MP4 which references this media in a single stream.

Server Manifest

A server manifest is the file which contains the configuration for the streams that Unified Origin will produce based on the input media.

This is created with the mp4split command line tool.

The options we use will enable VOD2Live output with a short DVR window of 30 seconds, and use FMP4 output for HLS.

#!/bin/bash

mp4split -o /var/www/tears-of-steel/vod2live_hands_on.isml \
  --vod2live \
  --dvr_window_length=30 \
  --hls.fmp4 \
  /var/www/tears-of-steel/vod2live_hands_on.mp4

The command output should look something like:

mp4split version=1.11.3 (24483)    Copyright 2007-2021 CodeShop B.V.

I0.000 Manifest file:///var/www/tears-of-steel/vod2live_hands_on.isml
I0.000 Track 1:
I0.000 src=vod2live_hands_on.mp4
I0.000 audio bitrate=64000 name=audio_eng
I0.000 id=1 timescale=48000 lang=en
I0.000 soun/mp4a dref=1 bitrate=64000/64000 tag=255 samplerate=48000 channels=2 sample_size=16 packet_size=4
I0.000 soun/mp4a dref=2 (tears-of-steel-aac-64k.mp4) bitrate=64000/64000 tag=255 samplerate=48000 channels=2 sample_size=16 packet_size=4
I0.000 Track 2:
I0.000 src=vod2live_hands_on.mp4
I0.000 audio bitrate=128000 name=audio_eng
I0.000 id=2 timescale=48000 lang=en
I0.000 soun/mp4a dref=1 bitrate=128000/128000 tag=255 samplerate=48000 channels=2 sample_size=16 packet_size=4
I0.000 soun/mp4a dref=2 (tears-of-steel-aac-128k.mp4) bitrate=128000/128000 tag=255 samplerate=48000 channels=2 sample_size=16 packet_size=4
I0.000 Track 3:
I0.000 src=vod2live_hands_on.mp4
I0.000 textstream bitrate=1000 name=textstream_eng
I0.000 id=3 timescale=1000 lang=en
I0.000 subt/stpp dref=1 bitrate=1000/0 codecs=stpp.ttml.im1t
I0.000 Track 4:
I0.000 src=vod2live_hands_on.mp4
I0.000 textstream bitrate=1000 name=textstream_zho
I0.000 id=4 timescale=1000 lang=zh
I0.000 subt/stpp dref=1 bitrate=1000/0 codecs=stpp.ttml.im1t
I0.000 Track 5:
I0.000 src=vod2live_hands_on.mp4
I0.000 video bitrate=400000/1008000 name=video_eng
I0.000 id=5 timescale=12288 lang=en
I0.000 vide/avc1 dref=1 bitrate=400000/1008000 size=224x100 sar=1:1 dar=56:25 codecs=avc1.42C014
I0.000 vide/avc1 dref=2 (tears-of-steel-avc1-400k.mp4) bitrate=400000/1008000 size=224x100 sar=1:1 dar=56:25 codecs=avc1.42C014
I0.000 Track 6:
I0.000 src=vod2live_hands_on.mp4
I0.000 video bitrate=751000/2190000 name=video_eng
I0.000 id=6 timescale=12288 lang=en
I0.000 vide/avc1 dref=1 bitrate=751000/2190000 size=448x200 sar=1:1 dar=56:25 codecs=avc1.42C016
I0.000 vide/avc1 dref=2 (tears-of-steel-avc1-750k.mp4) bitrate=751000/2190000 size=448x200 sar=1:1 dar=56:25 codecs=avc1.42C016
I0.000 Track 7:
I0.000 src=vod2live_hands_on.mp4
I0.000 video bitrate=1001000/3581000 name=video_eng
I0.000 id=7 timescale=12288 lang=en
I0.000 vide/avc1 dref=1 bitrate=1001000/3581000 size=784x350 sar=1:1 dar=56:25 codecs=avc1.4D401F
I0.000 vide/avc1 dref=2 (tears-of-steel-avc1-1000k.mp4) bitrate=1001000/3581000 size=784x350 sar=1:1 dar=56:25 codecs=avc1.4D401F
I0.000 Track 8:
I0.000 src=vod2live_hands_on.mp4
I0.000 video bitrate=1501000/6642000 name=video_eng
I0.001 id=8 timescale=12288 lang=en
I0.001 vide/avc1 dref=1 bitrate=1501000/6642000 size=1680x750 sar=1:1 dar=56:25 codecs=avc1.640028
I0.001 vide/avc1 dref=2 (tears-of-steel-avc1-1500k.mp4) bitrate=1501000/6642000 size=1680x750 sar=1:1 dar=56:25 codecs=avc1.640028
I0.001 writing 1 buckets for a total of 5681 bytes
I0.001 stat: url=file:///var/www/tears-of-steel/vod2live_hands_on.mp4, reads=3, size=884 KB
I0.001 stat: url=file:///var/www/tears-of-steel/tears-of-steel-avc1-400k.mp4, reads=1, size=8192 bytes
I0.001 stat: url=file:///var/www/tears-of-steel/tears-of-steel-avc1-750k.mp4, reads=1, size=12 KB
I0.001 stat: url=file:///var/www/tears-of-steel/tears-of-steel-avc1-1000k.mp4, reads=1, size=16 KB
I0.001 stat: url=file:///var/www/tears-of-steel/tears-of-steel-avc1-1500k.mp4, reads=1, size=20 KB
Status: 200 FMP4_OK

That's it!

This is all you need to do to create a working VOD2Live stream.

The output streams will be available at the following URLs:

  • HLS: http://<instance-url>/vod2live_hands_on.isml/.m3u8

  • DASH: http://<instance-url>/vod2live_hands_on.isml/.mpd

  • SmoothStreaming: http://<instance-url>/vod2live_hands_on.isml/Manifest

And they can be tested with a player immediately in your browser at:

  • http://<instance-url>/?http://<instance-url>/vod2live_hands_on.isml/.mpd

Note

Replace <instance-url> with the URL of your instance/server/host, and yes it does need to be replaced twice in the player test URL!

Using Docker

The same steps can also be run using Docker. To do so do the following:

  • 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 UspLicenseKey=<your-actual-license-key>

  • Run ./vod2live_hands_on.sh to actually execute the script

The open 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.

Online Demo