MPEG-DASH Manifest Merging

My goal is to stream VOD parts of different videos as 1 entity having 1 combined timeline, just as if those videos were one single unified video (which is what I actually want to prevent - merging those videos on the filesystem, as they’re pretty heavy).

Therefore, I’m combining the MPDs of the videos in my server.

More precisely, when I want to stream a “unified” video composed of several small videos, upon an MPD request of the client’s player, behind the scenes in the server I request the small videos’ MPDs from Wowza, extract their periods* and combine them into one unified MPD which I return to the player.

Diagram:

Client performs a GET operation from the server in order to receive an MPD to supply to the client’s player.

The server recieves the request, and then:

  1. Recognize the requested video is composed from serveal small videos.

  2. Request the videos MPDs from Wowza.

  3. Make a unified MPD*.

  4. Return the MPD to the player.

  • I had to change some additional parameters in the mpd, except from combining periods, to match to my videos length and start time of each period.

mediaPresentationDuration

The above technique WORKS.

My question is, is it ok to manipulate mpd files return from wowza? I know each MPD requests from Wowza generates a session for the client which in this case is my backend server… however I’m not sure how it fits in the whole picture…

Am I abusing Wowza or any other common standards in the VOD world?

What are the risks/ features I lose using this method? (i thought about mabye token security playback).

thanks ahead.

mpd file that looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xmlns="urn:mpeg:dash:schema:mpd:2011"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
     profiles="urn:mpeg:dash:profile:isoff-live:2011"
     type="static"
     publishTime="2016-11-02T12:42:53Z"
     mediaPresentationDuration="PT11M34.633S"
     minBufferTime="PT2S">
    <Period id="0" start="PT0.0S">
    	<BaseURL>http://myWowzaServer:1935/vod/vod/sample.mp4/</BaseURL>
        <AdaptationSet id="0" mimeType="video/mp4" width="512" height="288" par="16:9" frameRate="30" segmentAlignment="true" startWithSAP="1" subsegmentAlignment="true" subsegmentStartsWithSAP="1">
            <SegmentTemplate presentationTimeOffset="0" timescale="90000" media="chunk_ctvideo_cfm4s_rid$RepresentationID$_cs$Time$_w1769213771_mpd.m4s" initialization="chunk_ctvideo_cfm4s_rid$RepresentationID$_cinit_w1769213771_mpd.m4s">
                <SegmentTimeline>
                    <S t="0" d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="416970"/>
                </SegmentTimeline>
            </SegmentTemplate>
            <Representation id="p0a0r0" codecs="avc1.42c015" sar="1:1" bandwidth="640000">
            </Representation>
        </AdaptationSet>
        <AdaptationSet id="1" mimeType="audio/mp4" lang="eng" segmentAlignment="true" startWithSAP="1" subsegmentAlignment="true" subsegmentStartsWithSAP="1">
            <Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
            <SegmentTemplate presentationTimeOffset="0" timescale="48000" media="chunk_ctaudio_cfm4s_rid$RepresentationID$_cs$Time$_w1769213771_mpd.m4s" initialization="chunk_ctaudio_cfm4s_rid$RepresentationID$_cinit_w1769213771_mpd.m4s">
                <SegmentTimeline>
                    <S t="0" d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="222384"/>
                </SegmentTimeline>
            </SegmentTemplate>
            <Representation id="p0a1r0" codecs="mp4a.40.2" audioSamplingRate="48000" bandwidth="96000">
                <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
            </Representation>
        </AdaptationSet>
    </Period>
    <Period id="1" start="PT633S">
    	<BaseURL>http://myWowzaServer:1935/vod/vod/sample1.mp4/</BaseURL>
        <AdaptationSet id="0" mimeType="video/mp4" width="512" height="288" par="16:9" frameRate="30" segmentAlignment="true" startWithSAP="1" subsegmentAlignment="true" subsegmentStartsWithSAP="1">
            <SegmentTemplate presentationTimeOffset="2700000" timescale="90000" media="chunk_ctvideo_cfm4s_rid$RepresentationID$_cs$Time$_w1849515868_ps30000_pd60000_mpd.m4s" initialization="chunk_ctvideo_cfm4s_rid$RepresentationID$_cinit_w1849515868_ps30000_pd60000_mpd.m4s">
                <SegmentTimeline>
                    <S t="2700000" d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                    <S d="900000"/>
                </SegmentTimeline>
            </SegmentTemplate>
            <Representation id="p0a0r0" codecs="avc1.42c015" sar="1:1" bandwidth="640000" />
        </AdaptationSet>
        <AdaptationSet id="1" mimeType="audio/mp4" lang="eng" segmentAlignment="true" startWithSAP="1" subsegmentAlignment="true" subsegmentStartsWithSAP="1">
            <Role schemeIdUri="urn:mpeg:dash:role:2011" value="main"/>
            <SegmentTemplate presentationTimeOffset="1440000" timescale="48000" media="chunk_ctaudio_cfm4s_rid$RepresentationID$_cs$Time$_w1849515868_ps30000_pd60000_mpd.m4s" initialization="chunk_ctaudio_cfm4s_rid$RepresentationID$_cinit_w1849515868_ps30000_pd60000_mpd.m4s">
                <SegmentTimeline>
                    <S t="1440000" d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                    <S d="480000"/>
                </SegmentTimeline>
            </SegmentTemplate>
            <Representation id="p0a1r0" codecs="mp4a.40.2" audioSamplingRate="48000" bandwidth="96000">
                <AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2"/>
            </Representation>
        </AdaptationSet>
    </Period>
</MPD>

bump?

Hello oldwisenir,

You might be able to achieve the sequential playback of VOD assets by using a Wowza module called StreamPublisher.

The basic idea, is to use smil files and in them list off the assets you want to show, the start time and how long they will go for. These are called playlists.

There are examples of how to create these smil files in the article, but this is how a playlist in a smil file would potentially look like for your workflow.

I would recommend installing this module and playing around with it to see if it will suite your needs and allow for easier way of doing this.

Regards,

Alex

Thanks.

However, I understand that it would force me to stream as live video, but I want to stream VOD.

I have more concrete questions for you:

  1. Is the solution I suggested (which works fine) not recommended for some reason? Is it an abuse of Wowza or it’s ok?

  2. Do I break any mechanism by doing this? (e.g. sessions, etc).

Because if everything is ok I might keep working in the manner I suggested.

Hello oldwisenir,

You might be able to achieve the sequential playback of VOD assets by using a Wowza module called StreamPublisher.

The basic idea, is to use smil files and in them list off the assets you want to show, the start time and how long they will go for. These are called playlists.

There are examples of how to create these smil files in the article, but this is how a playlist in a smil file would potentially look like for your workflow.

I would recommend installing this module and playing around with it to see if it will suite your needs and allow for easier way of doing this.

Regards,

Alex

The initial workflow you outlined is perfectly fine if it does the job.

The StreamPublisher was just another way of achieving on the fly combination of VOD content.

Regards,

Alex

Thanks for wonderful information.

Hi! How did you manipulate your MPD to get you unified MPD?

Are there any api tools to change the behavior if a stream get called with …/manifest.mpd ?

regards,

Tom

@nir_klinger I am doing a similar thing but I’m finding that the playback pauses slightly when it hits the next period - I have all the timing props adjusted correctly, the video plays through except for a slight perceivable pause at the period joins.

Did you experience that behaviour?