August 11, 2015

Using SMIL for adaptive bitrate VOD via MPEG-DASH

Nimble Streamer has an excellent MP4 to MPEG-DASH VOD transmuxing feature set. As an addition to this scenario, our customers were asking if we plan supporting multi-bitrate (adaptive bitrate) support for VOD. The de-facto standard for this kind of tasks is the Synchronized Multimedia Integration Language, or SMIL.

Nimble now has SMIL support for MPEG-DASH VOD just as it has for VOD HLS. Let's see how it's set up and how a user may stream ABR VOD.
Before moving forward, you need to make sure that the files which you'd like to make SMIL for are key-frame aligned. In any other case ABR will not work.

Nimble Streamer setup


First, you need to install Nimble Streamer if you haven't done it yet.

Now, having the content located in a local directory - e.g. /var/www/video/ - you need to define a streaming route for Nimble Streamer so the user could access the content via HLS or progressive download with appropriate player. Read how to setup VOD streaming using WMSPanel.
You should try playing the uploaded files via HLS before going to the next step to avoid any permissions or other related problems on your server.
You may also use VOD files from remote location as a source.

Creating SMIL file


Now when Nimble is able to stream your single-bitrate files, let's compose sample SMIL file. For this example we assume you have /var/www/video/ directory with bigbuckbunny_450.mp4, bigbuckbunny_750.mp4, bigbuckbunny_1100.mp4 and bigbuckbunny_1500.mp4 files for respective bitrates.

Here's a SMIL for those.
<?xml version="1.0" encoding="UTF-8"?>
<smil title="">
        <body>
                <switch>
                        <video src="bigbuckbunny_450.mp4" systemLanguage="eng">
                                <param name="videoBitrate" value="450000" valuetype="data"></param>
                                <param name="audioBitrate" value="44100" valuetype="data"></param>
                        </video>
                        <video src="bigbuckbunny_750.mp4" systemLanguage="eng">
                                <param name="videoBitrate" value="750000" valuetype="data"></param>
                                <param name="audioBitrate" value="44100" valuetype="data"></param>
                        </video>
                        <video src="bigbuckbunny_1100.mp4" systemLanguage="eng">
                                <param name="videoBitrate" value="1100000" valuetype="data"></param>
                                <param name="audioBitrate" value="44100" valuetype="data"></param>
                        </video>
                        <video src="bigbuckbunny_1500.mp4" systemLanguage="eng">
                                <param name="videoBitrate" value="1500000" valuetype="data"></param>
                                <param name="audioBitrate" value="44100" valuetype="data"></param>
                        </video>
                </switch>
        </body>
</smil>

As an output, you'll get a manifest like this:
<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" type="static" xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT9M56.375S" minBufferTime="PT1.0S">
  <Period id="0" start="PT0.0S">
    <AdaptationSet id="0" mimeType="audio/mp4" lang="eng" segmentAlignment="true" startWithSAP="1">
      <SegmentTemplate timescale="48000" media="$RepresentationID$_$Time$.m4s?nimblesessionid=39" initialization="$RepresentationID$.m4a?nimblesessionid=39">
        <SegmentTimeline>
          <S t="0" d="144384" />
          <S d="192512" />
          <S d="288768" r="96" />
          <S d="281600" />
        </SegmentTimeline>
      </SegmentTemplate>
      <Representation id="bigbuckbunny_1100.mp4/s_0" codecs="mp4a.40.2" audioSamplingRate="48000" bandwidth="134917">
        <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
      </Representation>
    </AdaptationSet>
    <AdaptationSet id="1" mimeType="video/mp4" segmentAlignment="true" startWithSAP="1" maxWidth="1080" maxHeight="608">
      <SegmentTemplate timescale="100000" media="$RepresentationID$_$Time$.m4s?nimblesessionid=39" initialization="$RepresentationID$.m4v?nimblesessionid=39">
        <SegmentTimeline>
          <S t="0" d="300000" />
          <S d="600000" r="97" />
          <S d="537500" />
        </SegmentTimeline>
      </SegmentTemplate>
      <Representation id="bigbuckbunny_1100.mp4/v_0" codecs="avc1.4d401e" width="640" height="360" bandwidth="3751397" />
      <Representation id="bigbuckbunny_1500.mp4/v_0" codecs="avc1.4d401f" width="1080" height="608" bandwidth="5522714" />
      <Representation id="bigbuckbunny_450.mp4/v_0" codecs="avc1.4d400c" width="320" height="180" bandwidth="563137" />
      <Representation id="bigbuckbunny_750.mp4/v_0" codecs="avc1.4d4015" width="476" height="268" bandwidth="2390945" />
    </AdaptationSet>
  </Period>
</MPD>

There are case when you have several video or audio tracks in your MP4 file. This can also be handled by SMIL in order to give a player and a viewer some choice.

The following SMIL file should be created to enable adaptive bitrate streaming with several audio channels:

<?xml version="1.0" encoding="UTF-8"?>
<smil title="">
    <body>
        <switch>
            <video height="180" src="sample.mp4" systemLanguage="eng" width="320">
                <param name="videoBitrate" value="152000" valuetype="data"></param>
                <param name="audioBitrate" value="126000" valuetype="data"></param>
                <param name="audioIndex" value="0" valuetype="data"></param>
                <param name="videoIndex" value="1" valuetype="data"></param>
            </video>
            <video height="360" src="sample.mp4" systemLanguage="chi" width="640">
                <param name="videoBitrate" value="434000" valuetype="data"></param>
                <param name="audioBitrate" value="88000" valuetype="data"></param>
                <param name="audioIndex" value="1" valuetype="data"></param>
                <param name="videoIndex" value="0" valuetype="data"></param>
            </video>
           <video height="360" src="sample.mp4" systemLanguage="eng" width="640">
                <param name="videoBitrate" value="434000" valuetype="data"></param>
                <param name="audioBitrate" value="126000" valuetype="data"></param>
                <param name="audioIndex" value="0" valuetype="data"></param>
                <param name="videoIndex" value="0" valuetype="data"></param>
            </video>
            <video height="180" src="sample.mp4" systemLanguage="chi" width="320">
                <param name="videoBitrate" value="152000" valuetype="data"></param>
                <param name="audioBitrate" value="88000" valuetype="data"></param>
                <param name="audioIndex" value="1" valuetype="data"></param>
                <param name="videoIndex" value="1" valuetype="data"></param>
            </video>
        </switch>
    </body>
</smil>

And here's the manifest produced by this SMIL:

<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns="urn:mpeg:dash:schema:mpd:2011" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" type="static" xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 DASH-MPD.xsd" profiles="urn:mpeg:dash:profile:isoff-on-demand:2011" mediaPresentationDuration="PT1M12.214S" minBufferTime="PT1.0S">
  <Period id="0" start="PT0.0S">
    <AdaptationSet id="0" mimeType="audio/mp4" lang="chi" segmentAlignment="true" startWithSAP="1">
      <SegmentTemplate timescale="44100" media="$RepresentationID$_$Time$.m4s?nimblesessionid=41" initialization="$RepresentationID$.m4a?nimblesessionid=41">
        <SegmentTimeline>
          <S t="0" d="133120" />
          <S d="177152" />
          <S d="265216" r="9" />
          <S d="223232" />
        </SegmentTimeline>
      </SegmentTemplate>
      <Representation id="sample.mp4/s_1" codecs="mp4a.40.2" audioSamplingRate="44100" bandwidth="128603">
        <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
      </Representation>
    </AdaptationSet>
    <AdaptationSet id="1" mimeType="audio/mp4" lang="eng" segmentAlignment="true" startWithSAP="1">
      <SegmentTemplate timescale="44100" media="$RepresentationID$_$Time$.m4s?nimblesessionid=41" initialization="$RepresentationID$.m4a?nimblesessionid=41">
        <SegmentTimeline>
          <S t="0" d="133120" />
          <S d="177152" />
          <S d="265216" r="9" />
          <S d="222208" />
        </SegmentTimeline>
      </SegmentTemplate>
      <Representation id="sample.mp4/s_0" codecs="mp4a.40.2" audioSamplingRate="44100" bandwidth="135088">
        <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
      </Representation>
    </AdaptationSet>
    <AdaptationSet id="2" mimeType="video/mp4" segmentAlignment="true" startWithSAP="1" maxWidth="640" maxHeight="360">
      <SegmentTemplate timescale="12800" media="$RepresentationID$_$Time$.m4s?nimblesessionid=41" initialization="$RepresentationID$.m4v?nimblesessionid=41">
        <SegmentTimeline>
          <S t="0" d="45568" />
          <S d="128000" r="2" />
          <S d="108032" />
          <S d="128000" />
          <S d="171520" />
          <S d="86528" />
        </SegmentTimeline>
      </SegmentTemplate>
      <Representation id="sample.mp4/v_0" codecs="avc1.64001e" width="640" height="360" bandwidth="703863" />
      <Representation id="sample.mp4/v_1" codecs="avc1.64000c" width="320" height="180" bandwidth="240590" />
    </AdaptationSet>
  </Period>
</MPD>


Now when the SMIL file is ready, you can perform streaming.

Using SMIL for HLS players and devices

You can access VOD stream via URL like this
http://127.0.0.1:8081/vod/smil:sample.smil/manifest.mpd
Just replace "sample.smil" with your file name and local host with your server's public IP address.

You can use DASH-aware players like dash.js or bitdash by bitmovin to get excellent experience of MPEG-DASH playback.

Also check audio-only and video-only transmuxing via SMIL.

Let us know if you need help setting up this scenario.

Related documentation

No comments:

Post a Comment