Composite Manifest Support for Rough Cut Editing scenarios in SSME
- I have many clips but want to create a composite clip taking relevant portions from these clips.
- I have a large clip from an NBA game, I want to create a highlight for this game.
Now, let’s expand this simple idea. Not only do I want the above, I also want the ability to present this as a single stream to the user. This means the user can fast forward, rewind across the entire highlights and seek to any points in the highlight. In addition, I can add markers and present useful information to the user watching the stream. Well, this is exactly what we enabled with the Beta 2 release of SSPDK.
Composite Manifest
At the heart of this feature are small updates to the existing IIS Smooth Streaming Client manifest structure and we this new manifest a composite stream manifest (.csm). If you have used Smooth Streaming, you might already be familiar with the client manifest structure. Here is what it looks like before this feature:
- <?xml version="1.0" encoding="utf-16" ?>
- <!-- Created with Expression Encoder version 3.0.1332.0-->
- <SmoothStreamingMedia MajorVersion="2" MinorVersion="0" Duration="300000000">
- <StreamIndex Type="video" Chunks="15" QualityLevels="8" MaxWidth="640" MaxHeight="480" DisplayWidth="640" DisplayHeight="480" Url="QualityLevels({bitrate})/Fragments(video={start time})">
- <QualityLevel Index="0" Bitrate="1644000" FourCC="WVC1" MaxWidth="640" MaxHeight="480" CodecPrivateData="250000010FCBF213F0EF8A13F83BE80C9081B22B6457400000010E5A67F840" />
- <QualityLevel Index="1" Bitrate="1241000" FourCC="WVC1" MaxWidth="640" MaxHeight="480" CodecPrivateData="250000010FCBE613F0EF8A13F83BE80C9081A5DECBBE400000010E5A67F840" />
- <QualityLevel Index="2" Bitrate="937000" FourCC="WVC1" MaxWidth="640" MaxHeight="480" CodecPrivateData="250000010FCBDC13F0EF8A13F83BE80C90811C97F260C00000010E5A67F840" />
- <QualityLevel Index="3" Bitrate="708000" FourCC="WVC1" MaxWidth="428" MaxHeight="320" CodecPrivateData="250000010FCBD60D509F8A0D5827E80C9081159AD66CC00000010E5A67F840" />
- <QualityLevel Index="4" Bitrate="534000" FourCC="WVC1" MaxWidth="428" MaxHeight="320" CodecPrivateData="250000010FCBD00D509F8A0D5827E80C9081104B412F400000010E5A67F840" />
- <QualityLevel Index="5" Bitrate="403000" FourCC="WVC1" MaxWidth="428" MaxHeight="320" CodecPrivateData="250000010FCBCC0D509F8A0D5827E80C90808C4BE263400000010E5A67F840" />
- <QualityLevel Index="6" Bitrate="305000" FourCC="WVC1" MaxWidth="364" MaxHeight="272" CodecPrivateData="250000010FC3C80B50878A0B5821E80C9080894E4A76400000010E5A67F840" />
- <QualityLevel Index="7" Bitrate="230000" FourCC="WVC1" MaxWidth="364" MaxHeight="272" CodecPrivateData="250000010FC3C60B50878A0B5821E80C90800704704DC00000010E5A67F840" />
- <c t="0" />
- <c t="22350000" />
- <c t="42370000" />
- <c t="62390000" />
- <c t="82410000" />
- <c t="102430000" />
- <c t="122450000" />
- <c t="142470000" />
- <c t="162490000" />
- <c t="182510000" />
- <c t="202530000" />
- <c t="222550000" />
- <c t="242570000" />
- <c t="262590000" />
- <c t="282610000" d="17350001" />
- </StreamIndex>
- <StreamIndex Type="audio" Index="0" FourCC="WMAP" Chunks="15" QualityLevels="1" Url="QualityLevels({bitrate})/Fragments(audio={start time})">
- <QualityLevel Bitrate="192000" SamplingRate="44100" Channels="2" BitsPerSample="16" PacketSize="8917" AudioTag="354" CodecPrivateData="1000030000000000000000000000E0000000" />
- <c t="0" />
- <c t="22291156" />
- <c t="40867120" />
- <c t="60371882" />
- <c t="84056235" />
- <c t="100774603" />
- <c t="121208163" />
- <c t="143034920" />
- <c t="160682086" />
- <c t="181580045" />
- <c t="202013605" />
- <c t="221518367" />
- <c t="242880725" />
- <c t="260789115" />
- <c t="282354648" d="17993650" />
- </StreamIndex>
- </SmoothStreamingMedia>
To explain the structure in simpler terms, we have the following relationship: SmoothStreamingMedia contains StreamIndex that contains QualityLevel and ‘c’ elements.
Clip Element
Let’s say, I only want the first 10 seconds of the clip above as one of the clips in the RCE manifest. In the new RCE structure I would represent this as below:
Note: <<source to original manifest>> actually points to the URL for the manifest from which we need to play first 10 seconds.
- <Clip Url="<<source to original manifest>>" ClipBegin="0" ClipEnd="100000000">
- <StreamIndex Type="video" Chunks="5" QualityLevels="8" MaxWidth="640" MaxHeight="480" DisplayWidth="640" DisplayHeight="480" Url="QualityLevels({bitrate})/Fragments(video={start time})">
- <QualityLevel Index="0" Bitrate="1644000" FourCC="WVC1" MaxWidth="640" MaxHeight="480" CodecPrivateData="250000010FCBF213F0EF8A13F83BE80C9081B22B6457400000010E5A67F840" />
- <QualityLevel Index="1" Bitrate="1241000" FourCC="WVC1" MaxWidth="640" MaxHeight="480" CodecPrivateData="250000010FCBE613F0EF8A13F83BE80C9081A5DECBBE400000010E5A67F840" />
- <QualityLevel Index="2" Bitrate="937000" FourCC="WVC1" MaxWidth="640" MaxHeight="480" CodecPrivateData="250000010FCBDC13F0EF8A13F83BE80C90811C97F260C00000010E5A67F840" />
- <QualityLevel Index="3" Bitrate="708000" FourCC="WVC1" MaxWidth="428" MaxHeight="320" CodecPrivateData="250000010FCBD60D509F8A0D5827E80C9081159AD66CC00000010E5A67F840" />
- <QualityLevel Index="4" Bitrate="534000" FourCC="WVC1" MaxWidth="428" MaxHeight="320" CodecPrivateData="250000010FCBD00D509F8A0D5827E80C9081104B412F400000010E5A67F840" />
- <QualityLevel Index="5" Bitrate="403000" FourCC="WVC1" MaxWidth="428" MaxHeight="320" CodecPrivateData="250000010FCBCC0D509F8A0D5827E80C90808C4BE263400000010E5A67F840" />
- <QualityLevel Index="6" Bitrate="305000" FourCC="WVC1" MaxWidth="364" MaxHeight="272" CodecPrivateData="250000010FC3C80B50878A0B5821E80C9080894E4A76400000010E5A67F840" />
- <QualityLevel Index="7" Bitrate="230000" FourCC="WVC1" MaxWidth="364" MaxHeight="272" CodecPrivateData="250000010FC3C60B50878A0B5821E80C90800704704DC00000010E5A67F840" />
- <c t="0" />
- <c t="22350000" />
- <c t="42370000" />
- <c t="62390000" />
- <c t="82410000" d="20020000" />
- </StreamIndex>
- <StreamIndex Type="audio" Index="0" FourCC="WMAP" Chunks="5" QualityLevels="1" Url="QualityLevels({bitrate})/Fragments(audio={start time})">
- <QualityLevel Bitrate="192000" SamplingRate="44100" Channels="2" BitsPerSample="16" PacketSize="8917" AudioTag="354" CodecPrivateData="1000030000000000000000000000E0000000" />
- <c t="0" />
- <c t="22291156" />
- <c t="40867120" />
- <c t="60371882" />
- <c t="84056235" d="16718368" />
- </StreamIndex>
- </Clip>
If you notice carefully, all we have done is changed the relationship above to: SmoothStreamingMedia contains Clip and Clip contains StreamIndex. Finally StreamIndex contains QualityLevel and ‘c’ elements.
While doing this we defined a new element called Clip which has attributes called Url, ClipBegin and ClipEnd.
- Url – this specifies the Url to the original source manifest from which these clips were cut. The value is exactly as you would set on the SmoothStreamingSource property in SSME (e.g., http://abcxyz.com/sample.ism/Manifest).
- ClipBegin – This specifies the time in nanoseconds where to begin the playback for the clip.
- ClipEnd – This specifies time in nanoseconds where to end to end the playback for the clip.
You will also notice that ‘c’ elements are still present in this composite manifest. This is done so that this manifest is self sufficient and you don’t need to download the source manifest. ‘c’ elements are essentially chunk timestamps for the FMP4 chunks the client will download.
Note: Not all ‘c’ elements are included in this manifest. The idea is to include only the ones needed to represent the section of the clip. In this case times are close to the ClipBegin and ClipEnd. They may not exactly match in timestamps as chunks are 2 seconds apart typically while the Clip is cut at finer granularity.
Multiple Clip Elements
In the section above, we saw how to compose a single clip. However, composite manifest promises to have multiple such clips stitched together. All you need to do is to have multiple such Clip elements and that takes care of that. Here is how an example of composite manifest with two clips will will look like:
- <?xml version="1.0" encoding="utf-16"?>
- <SmoothStreamingMedia MajorVersion="2" MinorVersion="0" Duration="200000000">
- <Clip Url="http://abcxyz.com/sample.ism/Manifest" ClipBegin="0" ClipEnd="100000000">
- <StreamIndex Type="video" Chunks="5" QualityLevels="8" MaxWidth="640" MaxHeight="480" DisplayWidth="640" DisplayHeight="480" Url="QualityLevels({bitrate})/Fragments(video={start time})">
- <QualityLevel Index="0" Bitrate="1644000" FourCC="WVC1" MaxWidth="640" MaxHeight="480" CodecPrivateData="250000010FCBF213F0EF8A13F83BE80C9081B22B6457400000010E5A67F840" />
- <QualityLevel Index="1" Bitrate="1241000" FourCC="WVC1" MaxWidth="640" MaxHeight="480" CodecPrivateData="250000010FCBE613F0EF8A13F83BE80C9081A5DECBBE400000010E5A67F840" />
- <QualityLevel Index="2" Bitrate="937000" FourCC="WVC1" MaxWidth="640" MaxHeight="480" CodecPrivateData="250000010FCBDC13F0EF8A13F83BE80C90811C97F260C00000010E5A67F840" />
- <QualityLevel Index="3" Bitrate="708000" FourCC="WVC1" MaxWidth="428" MaxHeight="320" CodecPrivateData="250000010FCBD60D509F8A0D5827E80C9081159AD66CC00000010E5A67F840" />
- <QualityLevel Index="4" Bitrate="534000" FourCC="WVC1" MaxWidth="428" MaxHeight="320" CodecPrivateData="250000010FCBD00D509F8A0D5827E80C9081104B412F400000010E5A67F840" />
- <QualityLevel Index="5" Bitrate="403000" FourCC="WVC1" MaxWidth="428" MaxHeight="320" CodecPrivateData="250000010FCBCC0D509F8A0D5827E80C90808C4BE263400000010E5A67F840" />
- <QualityLevel Index="6" Bitrate="305000" FourCC="WVC1" MaxWidth="364" MaxHeight="272" CodecPrivateData="250000010FC3C80B50878A0B5821E80C9080894E4A76400000010E5A67F840" />
- <QualityLevel Index="7" Bitrate="230000" FourCC="WVC1" MaxWidth="364" MaxHeight="272" CodecPrivateData="250000010FC3C60B50878A0B5821E80C90800704704DC00000010E5A67F840" />
- <c t="0" />
- <c t="22350000" />
- <c t="42370000" />
- <c t="62390000" />
- <c t="82410000" d="20020000" />
- </StreamIndex>
- <StreamIndex Type="audio" Index="0" FourCC="WMAP" Chunks="5" QualityLevels="1" Url="QualityLevels({bitrate})/Fragments(audio={start time})">
- <QualityLevel Bitrate="192000" SamplingRate="44100" Channels="2" BitsPerSample="16" PacketSize="8917" AudioTag="354" CodecPrivateData="1000030000000000000000000000E0000000" />
- <c t="0" />
- <c t="22291156" />
- <c t="40867120" />
- <c t="60371882" />
- <c t="84056235" d="16718368" />
- </StreamIndex>
- </Clip>
- <Clip Url="http://abcxyz.com/sample2.ism/Manifest" ClipBegin="60000000" ClipEnd="160000000">
- <StreamIndex Type="video" Chunks="5" QualityLevels="8" MaxWidth="848" MaxHeight="476" DisplayWidth="848" DisplayHeight="476" Url="QualityLevels({bitrate})/Fragments(video={start time})">
- <QualityLevel Index="0" Bitrate="1644000" FourCC="WVC1" MaxWidth="848" MaxHeight="476" CodecPrivateData="250000010FCBB21A70ED8A1A783B68045081B22B6457400000010E5A67F840" />
- <QualityLevel Index="1" Bitrate="1241000" FourCC="WVC1" MaxWidth="848" MaxHeight="476" CodecPrivateData="250000010FCBA61A70ED8A1A783B68045081A5DECBBE400000010E5A67F840" />
- <QualityLevel Index="2" Bitrate="937000" FourCC="WVC1" MaxWidth="848" MaxHeight="476" CodecPrivateData="250000010FCB9C1A70ED8A1A783B680450811C97F260C00000010E5A67F840" />
- <QualityLevel Index="3" Bitrate="708000" FourCC="WVC1" MaxWidth="568" MaxHeight="320" CodecPrivateData="250000010FCB9611B09F8A11B827E8045081159AD66CC00000010E5A67F840" />
- <QualityLevel Index="4" Bitrate="534000" FourCC="WVC1" MaxWidth="568" MaxHeight="320" CodecPrivateData="250000010FCB9011B09F8A11B827E8045081104B412F400000010E5A67F840" />
- <QualityLevel Index="5" Bitrate="403000" FourCC="WVC1" MaxWidth="568" MaxHeight="320" CodecPrivateData="250000010FCB8C11B09F8A11B827E80450808C4BE263400000010E5A67F840" />
- <QualityLevel Index="6" Bitrate="305000" FourCC="WVC1" MaxWidth="480" MaxHeight="272" CodecPrivateData="250000010FCB880EF0878A0EF821E8045080894E4A76400000010E5A67F840" />
- <QualityLevel Index="7" Bitrate="230000" FourCC="WVC1" MaxWidth="480" MaxHeight="272" CodecPrivateData="250000010FCB860EF0878A0EF821E80450800704704DC00000010E5A67F840" />
- <c t="60000000" />
- <c t="80000000" />
- <c t="100000000" />
- <c t="120000000" />
- <c t="140000000" d="20000000"/>
- </StreamIndex>
- <StreamIndex Type="audio" Index="0" FourCC="WMAP" Chunks="6" QualityLevels="1" Url="QualityLevels({bitrate})/Fragments(audio={start time})">
- <QualityLevel Bitrate="192000" SamplingRate="44100" Channels="2" BitsPerSample="16" PacketSize="8917" AudioTag="354" CodecPrivateData="1000030000000000000000000000E0000000" />
- <c t="42724716" />
- <c t="61082992" />
- <c t="80341043" />
- <c t="103096598" />
- <c t="120279365" />
- <c t="142570521" d="21362358" />
- </StreamIndex>
- </Clip>
- </SmoothStreamingMedia>
With this, you can now upload this manifest along with the original manifests and content used by them to a HTTP accessible location. Next, set the SmoothStreamingSource property to the URL to this composite manifest and SSME should take care of the rest. Here is how it will look like in XAML:
- <UserControl x:Class="SilverlightApplication6.MainPage"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:SSME="clr-namespace:Microsoft.Web.Media.SmoothStreaming;assembly=Microsoft.Web.Media.SmoothStreaming"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
- <Grid x:Name="LayoutRoot">
- <SSME:SmoothStreamingMediaElement SmoothStreamingSource="http://abcxyz.com/SampleRCEManifest.csm" x:Name="SmoothPlayer" />
- </Grid>
- </UserControl>
We will have more detailed documentation up on iis.net very soon.In the meantime, let me know if you have any questions.