<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.whatwg.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=JeroenW</id>
	<title>WHATWG Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.whatwg.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=JeroenW"/>
	<link rel="alternate" type="text/html" href="https://wiki.whatwg.org/wiki/Special:Contributions/JeroenW"/>
	<updated>2026-05-25T06:22:02Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.3</generator>
	<entry>
		<id>https://wiki.whatwg.org/index.php?title=Video_Metrics&amp;diff=6346</id>
		<title>Video Metrics</title>
		<link rel="alternate" type="text/html" href="https://wiki.whatwg.org/index.php?title=Video_Metrics&amp;diff=6346"/>
		<updated>2011-03-31T12:54:28Z</updated>

		<summary type="html">&lt;p&gt;JeroenW: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Related HTML WG bug:&#039;&#039;&#039; http://www.w3.org/Bugs/Public/show_bug.cgi?id=12399&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Requirements&#039;&#039;&#039;&lt;br /&gt;
For several reasons, we need to expose the performance of media elements to JavaScript.&lt;br /&gt;
&lt;br /&gt;
One concrete use case is that content publishers want to understand the quality of their content as being played back by their users and how much a user is actually playing back. For example, if a video always goes into buffering mode after 1 min for all users - maybe there is a problem in the encoding, or the video is too big for the typical bandwidth/CPU combination. Also, publishers want to track the metrics of how much of their video and audio files is actually being watched.&lt;br /&gt;
&lt;br /&gt;
A further use case is HTTP adaptive streaming, where an author wants to manually implement an algorithm for switching between different resources of different bandwidth or screen size. For example, if the user goes full screen and the user&#039;s machine and bandwidth allow for it, the author might want to switch to a higher resolution video.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Collection of Proposals/Implementations&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Mozilla have implemented the following [http://blog.pearce.org.nz/2011/03/html5-video-painting-performance.html statistics into Firefox]:&lt;br /&gt;
&lt;br /&gt;
* mozParsedFrames - number of frames that have been demuxed and extracted out of the media.&lt;br /&gt;
* mozDecodedFrames - number of frames that have been decoded - converted into YCbCr.&lt;br /&gt;
* mozPresentedFrames - number of frames that have been presented to the rendering pipeline for rendering - were &amp;quot;set as the current image&amp;quot;.&lt;br /&gt;
* mozPaintedFrames - number of frames which were presented to the rendering pipeline and ended up being painted on the screen. Note that if the video is not on screen (e.g. in another tab or scrolled off screen), this counter will not increase.&lt;br /&gt;
* mozPaintDelay - the time delay between presenting the last frame and it being painted on screen (approximately).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Webkit have [https://bugs.webkit.org/show_bug.cgi?id=53322 implemented] these:&lt;br /&gt;
&lt;br /&gt;
* webkitAudioBytesDecoded&lt;br /&gt;
* webkitVideoBytesDecoded&lt;br /&gt;
* webkitDecodedFrames&lt;br /&gt;
* webkitDroppedFrames&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JW Player (using [http://help.adobe.com/nl_NL/AS3LCR/Flash_10.0/flash/net/NetStreamInfo.html actionscript]) broadcasts the following QOS &#039;&#039;metrics&#039;&#039; for both RTMP dynamic and HTTP adaptive:&lt;br /&gt;
&lt;br /&gt;
* bandwidth: server-client data rate, in kilobytespersecond.&lt;br /&gt;
* latency: client-server-client roundtrip time, in milliseconds.&lt;br /&gt;
* frameDropRate: number of frames not presented to the viewer, in frames per second.&lt;br /&gt;
* screenWidth / screenHeight: dimensions of the video viewport, in pixels. Changes e.g. when the viewer jumps fullscreen.&lt;br /&gt;
* qualityLevel: index of the currently playing quality level (see below).&lt;br /&gt;
&lt;br /&gt;
Bandwidth and droprate are running metrics (averaged out). Latency and dimensions are sampled (taken once). For RTMP dynamic, the metrics are broadcast at a settable interval (default 2s). For HTTP adaptive, metrics are calculated and broadcast upon completion of a fragment load.&lt;br /&gt;
&lt;br /&gt;
Separately, JW Player broadcasts a &#039;&#039;SWITCH&#039;&#039; event at the painting of a frame that has a different qualityLevel than the preceding frame(s). While the &#039;&#039;metrics.qualityLevel&#039;&#039; tells developers the qualityLevel of the currently downloading buffer/fragment, the &#039;&#039;SWITCH&#039;&#039; event tells developers the exact point in time where the viewer experiences a jump in video quality. This event also helps developers correlate the value of &#039;&#039;frameDropRate&#039;&#039; to the currently playing qualityLevel (as opposed to the currently loading one). Depending upon buffer, fragment and GOP size, the time delta between a change in &#039;&#039;metrics.qualityLevel&#039;&#039; and &#039;&#039;SWITCH.qualityLevel&#039;&#039; [http://www.cc.gatech.edu/~sakhshab/Saamer_MMSys11.pdf may vary] from a few seconds to a few minutes. &lt;br /&gt;
&lt;br /&gt;
Finally, JW Player [http://www.longtailvideo.com/support/jw-player/jw-player-for-flash-v5/16012/setting-up-rtmp-dynamic-streaming accepts and exposes] per video an array with quality levels (the distinct streams of a video between which the player can switch). For each quality level, properties like &#039;&#039;bitrate&#039;&#039;, &#039;&#039;framerate&#039;&#039;, &#039;&#039;height&#039;&#039; and &#039;&#039;width&#039;&#039; are available. The plain mapping using &#039;&#039;qualityLevel&#039;&#039; works b/c JW Player to date solely supports single A/V muxed dynamic/adaptive videos - no multi track. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Previously the following statistics have been proposed for [http://wiki.whatwg.org/wiki/Adaptive_Streaming#QOS_Metrics HTTP adaptive streaming]:&lt;br /&gt;
&lt;br /&gt;
* downloadRate: The current server-client bandwidth (read-only).&lt;br /&gt;
* videoBitrate: The current video bitrate (read-only).&lt;br /&gt;
* droppedFrames: The total number of frames dropped for this playback session (read-only).&lt;br /&gt;
* decodedFrames: The total number of frames decoded for this playback session (read-only).&lt;br /&gt;
* height: The current height of the video element (already exists).&lt;br /&gt;
* videoHeight: The current height of the videofile (already exists).&lt;br /&gt;
* width: The current width of the video element (already exists).&lt;br /&gt;
* videoWidth: The current width of the videofile (already exists). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Further, a requirement to expose playback rate statistics has come out of [http://lists.w3.org/Archives/Public/public-html/2011Feb/0113.html issue-147]:&lt;br /&gt;
&lt;br /&gt;
* currentPlaybackRate: the rate at which the video/audio is currently playing back&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://www.quora.com/Video-Analytics/What-are-the-most-valuable-metrics-in-online-video-analytics Here are a few metrics that measure the QoS] that a user receives:&lt;br /&gt;
&lt;br /&gt;
* playerLoadTime&lt;br /&gt;
* streamBitrate&lt;br /&gt;
(user interaction and playthrough can be measured using existing events)&lt;/div&gt;</summary>
		<author><name>JeroenW</name></author>
	</entry>
	<entry>
		<id>https://wiki.whatwg.org/index.php?title=Video_Metrics&amp;diff=6345</id>
		<title>Video Metrics</title>
		<link rel="alternate" type="text/html" href="https://wiki.whatwg.org/index.php?title=Video_Metrics&amp;diff=6345"/>
		<updated>2011-03-31T12:24:51Z</updated>

		<summary type="html">&lt;p&gt;JeroenW: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Related HTML WG bug:&#039;&#039;&#039; http://www.w3.org/Bugs/Public/show_bug.cgi?id=12399&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Requirements&#039;&#039;&#039;&lt;br /&gt;
For several reasons, we need to expose the performance of media elements to JavaScript.&lt;br /&gt;
&lt;br /&gt;
One concrete use case is that content publishers want to understand the quality of their content as being played back by their users and how much a user is actually playing back. For example, if a video always goes into buffering mode after 1 min for all users - maybe there is a problem in the encoding, or the video is too big for the typical bandwidth/CPU combination. Also, publishers want to track the metrics of how much of their video and audio files is actually being watched.&lt;br /&gt;
&lt;br /&gt;
A further use case is HTTP adaptive streaming, where an author wants to manually implement an algorithm for switching between different resources of different bandwidth or screen size. For example, if the user goes full screen and the user&#039;s machine and bandwidth allow for it, the author might want to switch to a higher resolution video.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Collection of Proposals/Implementations&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Mozilla have implemented the following [http://blog.pearce.org.nz/2011/03/html5-video-painting-performance.html statistics into Firefox]:&lt;br /&gt;
&lt;br /&gt;
* mozParsedFrames - number of frames that have been demuxed and extracted out of the media.&lt;br /&gt;
* mozDecodedFrames - number of frames that have been decoded - converted into YCbCr.&lt;br /&gt;
* mozPresentedFrames - number of frames that have been presented to the rendering pipeline for rendering - were &amp;quot;set as the current image&amp;quot;.&lt;br /&gt;
* mozPaintedFrames - number of frames which were presented to the rendering pipeline and ended up being painted on the screen. Note that if the video is not on screen (e.g. in another tab or scrolled off screen), this counter will not increase.&lt;br /&gt;
* mozPaintDelay - the time delay between presenting the last frame and it being painted on screen (approximately).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Webkit have [https://bugs.webkit.org/show_bug.cgi?id=53322 implemented] these:&lt;br /&gt;
&lt;br /&gt;
* webkitAudioBytesDecoded&lt;br /&gt;
* webkitVideoBytesDecoded&lt;br /&gt;
* webkitDecodedFrames&lt;br /&gt;
* webkitDroppedFrames&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JW Player (using [http://help.adobe.com/nl_NL/AS3LCR/Flash_10.0/flash/net/NetStreamInfo.html actionscript]) broadcasts the following QOS metrics for both RTMP dynamic and HTTP adaptive:&lt;br /&gt;
&lt;br /&gt;
* bandwidth: server-client data rate, in kilobytespersecond.&lt;br /&gt;
* latency: client-server-client roundtrip time, in milliseconds.&lt;br /&gt;
* frameDropRate: number of frames not presented to the viewer, in frames per second.&lt;br /&gt;
* screenWidth / screenHeight: dimensions of the video viewport, in pixels.&lt;br /&gt;
* qualityLevel: index of the currently playing quality level (see note).&lt;br /&gt;
&lt;br /&gt;
Bandwidth and droprate are running metrics (averaged out). Latency and dimensions are sampled metrics (taken once). For RTMP dynamic, the metrics are broadcast at a settable interval (default 2s). For HTTP adaptive, metrics are calculate and broadcast for the last fragment that was loaded (for bandwidth/latency/qualityLevel) or presented (for droprate/dimensions).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Next to QOS metrics, JW Player [http://www.longtailvideo.com/support/jw-player/jw-player-for-flash-v5/16012/setting-up-rtmp-dynamic-streaming accepts and exposes] per video an array with quality levels (the distinct streams of a video between which the player can switch). The &#039;&#039;qualityLevel&#039;&#039; metric defines the index in this array of the currently active stream. For each stream, properties like &#039;&#039;bitrate&#039;&#039;, &#039;&#039;framerate&#039;&#039;, &#039;&#039;height&#039;&#039; and &#039;&#039;width&#039;&#039; are available. This basic mapping works b/c JW Player to date solely supports single A/V muxed dynamic/adaptive videos - no multi track. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Previously the following statistics have been proposed for [http://wiki.whatwg.org/wiki/Adaptive_Streaming#QOS_Metrics HTTP adaptive streaming]:&lt;br /&gt;
&lt;br /&gt;
* downloadRate: The current server-client bandwidth (read-only).&lt;br /&gt;
* videoBitrate: The current video bitrate (read-only).&lt;br /&gt;
* droppedFrames: The total number of frames dropped for this playback session (read-only).&lt;br /&gt;
* decodedFrames: The total number of frames decoded for this playback session (read-only).&lt;br /&gt;
* height: The current height of the video element (already exists).&lt;br /&gt;
* videoHeight: The current height of the videofile (already exists).&lt;br /&gt;
* width: The current width of the video element (already exists).&lt;br /&gt;
* videoWidth: The current width of the videofile (already exists). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Further, a requirement to expose playback rate statistics has come out of [http://lists.w3.org/Archives/Public/public-html/2011Feb/0113.html issue-147]:&lt;br /&gt;
&lt;br /&gt;
* currentPlaybackRate: the rate at which the video/audio is currently playing back&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://www.quora.com/Video-Analytics/What-are-the-most-valuable-metrics-in-online-video-analytics Here are a few metrics that measure the QoS] that a user receives:&lt;br /&gt;
&lt;br /&gt;
* playerLoadTime&lt;br /&gt;
* streamBitrate&lt;br /&gt;
(user interaction and playthrough can be measured using existing events)&lt;/div&gt;</summary>
		<author><name>JeroenW</name></author>
	</entry>
	<entry>
		<id>https://wiki.whatwg.org/index.php?title=Video_Metrics&amp;diff=6344</id>
		<title>Video Metrics</title>
		<link rel="alternate" type="text/html" href="https://wiki.whatwg.org/index.php?title=Video_Metrics&amp;diff=6344"/>
		<updated>2011-03-31T12:23:57Z</updated>

		<summary type="html">&lt;p&gt;JeroenW: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Related HTML WG bug:&#039;&#039;&#039; http://www.w3.org/Bugs/Public/show_bug.cgi?id=12399&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Requirements&#039;&#039;&#039;&lt;br /&gt;
For several reasons, we need to expose the performance of media elements to JavaScript.&lt;br /&gt;
&lt;br /&gt;
One concrete use case is that content publishers want to understand the quality of their content as being played back by their users and how much a user is actually playing back. For example, if a video always goes into buffering mode after 1 min for all users - maybe there is a problem in the encoding, or the video is too big for the typical bandwidth/CPU combination. Also, publishers want to track the metrics of how much of their video and audio files is actually being watched.&lt;br /&gt;
&lt;br /&gt;
A further use case is HTTP adaptive streaming, where an author wants to manually implement an algorithm for switching between different resources of different bandwidth or screen size. For example, if the user goes full screen and the user&#039;s machine and bandwidth allow for it, the author might want to switch to a higher resolution video.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Collection of Proposals/Implementations&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Mozilla have implemented the following [http://blog.pearce.org.nz/2011/03/html5-video-painting-performance.html statistics into Firefox]:&lt;br /&gt;
&lt;br /&gt;
* mozParsedFrames - number of frames that have been demuxed and extracted out of the media.&lt;br /&gt;
* mozDecodedFrames - number of frames that have been decoded - converted into YCbCr.&lt;br /&gt;
* mozPresentedFrames - number of frames that have been presented to the rendering pipeline for rendering - were &amp;quot;set as the current image&amp;quot;.&lt;br /&gt;
* mozPaintedFrames - number of frames which were presented to the rendering pipeline and ended up being painted on the screen. Note that if the video is not on screen (e.g. in another tab or scrolled off screen), this counter will not increase.&lt;br /&gt;
* mozPaintDelay - the time delay between presenting the last frame and it being painted on screen (approximately).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Webkit have [https://bugs.webkit.org/show_bug.cgi?id=53322 implemented] these:&lt;br /&gt;
&lt;br /&gt;
* webkitAudioBytesDecoded&lt;br /&gt;
* webkitVideoBytesDecoded&lt;br /&gt;
* webkitDecodedFrames&lt;br /&gt;
* webkitDroppedFrames&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JW Player (using [http://help.adobe.com/nl_NL/AS3LCR/Flash_10.0/flash/net/NetStreamInfo.html actionscript]) broadcasts the following QOS metrics for both RTMP dynamic and HTTP adaptive:&lt;br /&gt;
&lt;br /&gt;
* bandwidth: server-client data rate, in kilobytespersecond.&lt;br /&gt;
* latency: client-server-client roundtrip time, in milliseconds.&lt;br /&gt;
* frameDropRate: number of frames not presented to the viewer, in frames per second.&lt;br /&gt;
* screenWidth / screenHeight: dimensions of the video viewport, in pixels.&lt;br /&gt;
* qualityLevel: index of the currently playing quality level (see note).&lt;br /&gt;
&lt;br /&gt;
Bandwidth and droprate are running metrics (averaged out). Latency and dimensions are sampled metrics (taken once). For RTMP dynamic, the metrics are broadcast at a settable interval (default 2s). For HTTP adaptive, metrics are calculate and broadcast for the last fragment that was loaded (for bandwidth/latency/qualityLevel) or presented (for droprate/dimensions).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Next to QOS metrics, JW Player [http://www.longtailvideo.com/support/jw-player/jw-player-for-flash-v5/16012/setting-up-rtmp-dynamic-streaming accepts and exposes] per video an array with quality levels (the distinct streams of a video between which the player can switch). The &#039;&#039;qualityLevel&#039;&#039; metric defines the index in this array of the currently active stream. For each stream, properties like &#039;&#039;bitrate&#039;&#039;, &#039;&#039;framerate&#039;&#039;, &#039;&#039;height&#039;&#039; and &#039;&#039;width&#039;&#039; are available. This basic mapping works b/c JW Player to date solely supports single A/V muxed dynamic/adaptive videos - no multitracks. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Previously the following statistics have been proposed for [http://wiki.whatwg.org/wiki/Adaptive_Streaming#QOS_Metrics HTTP adaptive streaming]:&lt;br /&gt;
&lt;br /&gt;
* downloadRate: The current server-client bandwidth (read-only).&lt;br /&gt;
* videoBitrate: The current video bitrate (read-only).&lt;br /&gt;
* droppedFrames: The total number of frames dropped for this playback session (read-only).&lt;br /&gt;
* decodedFrames: The total number of frames decoded for this playback session (read-only).&lt;br /&gt;
* height: The current height of the video element (already exists).&lt;br /&gt;
* videoHeight: The current height of the videofile (already exists).&lt;br /&gt;
* width: The current width of the video element (already exists).&lt;br /&gt;
* videoWidth: The current width of the videofile (already exists). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Further, a requirement to expose playback rate statistics has come out of [http://lists.w3.org/Archives/Public/public-html/2011Feb/0113.html issue-147]:&lt;br /&gt;
&lt;br /&gt;
* currentPlaybackRate: the rate at which the video/audio is currently playing back&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://www.quora.com/Video-Analytics/What-are-the-most-valuable-metrics-in-online-video-analytics Here are a few metrics that measure the QoS] that a user receives:&lt;br /&gt;
&lt;br /&gt;
* playerLoadTime&lt;br /&gt;
* streamBitrate&lt;br /&gt;
(user interaction and playthrough can be measured using existing events)&lt;/div&gt;</summary>
		<author><name>JeroenW</name></author>
	</entry>
	<entry>
		<id>https://wiki.whatwg.org/index.php?title=Video_Metrics&amp;diff=6343</id>
		<title>Video Metrics</title>
		<link rel="alternate" type="text/html" href="https://wiki.whatwg.org/index.php?title=Video_Metrics&amp;diff=6343"/>
		<updated>2011-03-31T12:21:12Z</updated>

		<summary type="html">&lt;p&gt;JeroenW: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Related HTML WG bug:&#039;&#039;&#039; http://www.w3.org/Bugs/Public/show_bug.cgi?id=12399&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Requirements&#039;&#039;&#039;&lt;br /&gt;
For several reasons, we need to expose the performance of media elements to JavaScript.&lt;br /&gt;
&lt;br /&gt;
One concrete use case is that content publishers want to understand the quality of their content as being played back by their users and how much a user is actually playing back. For example, if a video always goes into buffering mode after 1 min for all users - maybe there is a problem in the encoding, or the video is too big for the typical bandwidth/CPU combination. Also, publishers want to track the metrics of how much of their video and audio files is actually being watched.&lt;br /&gt;
&lt;br /&gt;
A further use case is HTTP adaptive streaming, where an author wants to manually implement an algorithm for switching between different resources of different bandwidth or screen size. For example, if the user goes full screen and the user&#039;s machine and bandwidth allow for it, the author might want to switch to a higher resolution video.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Collection of Proposals/Implementations&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Mozilla have implemented the following [http://blog.pearce.org.nz/2011/03/html5-video-painting-performance.html statistics into Firefox]:&lt;br /&gt;
&lt;br /&gt;
* mozParsedFrames - number of frames that have been demuxed and extracted out of the media.&lt;br /&gt;
* mozDecodedFrames - number of frames that have been decoded - converted into YCbCr.&lt;br /&gt;
* mozPresentedFrames - number of frames that have been presented to the rendering pipeline for rendering - were &amp;quot;set as the current image&amp;quot;.&lt;br /&gt;
* mozPaintedFrames - number of frames which were presented to the rendering pipeline and ended up being painted on the screen. Note that if the video is not on screen (e.g. in another tab or scrolled off screen), this counter will not increase.&lt;br /&gt;
* mozPaintDelay - the time delay between presenting the last frame and it being painted on screen (approximately).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Webkit have [https://bugs.webkit.org/show_bug.cgi?id=53322 implemented] these:&lt;br /&gt;
&lt;br /&gt;
* webkitAudioBytesDecoded&lt;br /&gt;
* webkitVideoBytesDecoded&lt;br /&gt;
* webkitDecodedFrames&lt;br /&gt;
* webkitDroppedFrames&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JW Player (using [http://help.adobe.com/nl_NL/AS3LCR/Flash_10.0/flash/net/NetStreamInfo.html actionscript]) broadcasts the following QOS metrics for both RTMP dynamic and HTTP adaptive:&lt;br /&gt;
&lt;br /&gt;
* bandwidth: server-client data rate, in kilobytespersecond.&lt;br /&gt;
* latency: client-server-client roundtrip time, in milliseconds.&lt;br /&gt;
* frameDropRate: number of frames not presented to the viewer, in frames per second.&lt;br /&gt;
* screenWidth / screenHeight: dimensions of the video viewport, in pixels.&lt;br /&gt;
* qualityLevel: index of the currently playing quality level (see note).&lt;br /&gt;
&lt;br /&gt;
Bandwidth and droprate are running metrics (averaged out). Latency and dimensions are sampled metrics (taken once). For RTMP dynamic, the metrics are broadcast at a settable interval (default 2s). For HTTP adaptive, metrics are calculate and broadcast for the last fragment that was loaded (for bandwidth/latency/qualityLevel) or presented (for droprate/dimensions).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note:&#039;&#039;&#039; Next to QOS metrics, JW Player [http://www.longtailvideo.com/support/jw-player/jw-player-for-flash-v5/16012/setting-up-rtmp-dynamic-streaming accepts and exposes] per video an array with quality levels (the distinct streams of a video between which the player can adapt). The &#039;&#039;qualityLevel&#039;&#039; metric defines the index in this array of the currently active stream. For each stream, properties like bitrate, dimensions and framerate are available. This basic mapping works b/c JW Player to date solely supports single A/V muxed dynamic/adaptive videos - no multitracks. &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Previously the following statistics have been proposed for [http://wiki.whatwg.org/wiki/Adaptive_Streaming#QOS_Metrics HTTP adaptive streaming]:&lt;br /&gt;
&lt;br /&gt;
* downloadRate: The current server-client bandwidth (read-only).&lt;br /&gt;
* videoBitrate: The current video bitrate (read-only).&lt;br /&gt;
* droppedFrames: The total number of frames dropped for this playback session (read-only).&lt;br /&gt;
* decodedFrames: The total number of frames decoded for this playback session (read-only).&lt;br /&gt;
* height: The current height of the video element (already exists).&lt;br /&gt;
* videoHeight: The current height of the videofile (already exists).&lt;br /&gt;
* width: The current width of the video element (already exists).&lt;br /&gt;
* videoWidth: The current width of the videofile (already exists). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Further, a requirement to expose playback rate statistics has come out of [http://lists.w3.org/Archives/Public/public-html/2011Feb/0113.html issue-147]:&lt;br /&gt;
&lt;br /&gt;
* currentPlaybackRate: the rate at which the video/audio is currently playing back&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://www.quora.com/Video-Analytics/What-are-the-most-valuable-metrics-in-online-video-analytics Here are a few metrics that measure the QoS] that a user receives:&lt;br /&gt;
&lt;br /&gt;
* playerLoadTime&lt;br /&gt;
* streamBitrate&lt;br /&gt;
(user interaction and playthrough can be measured using existing events)&lt;/div&gt;</summary>
		<author><name>JeroenW</name></author>
	</entry>
	<entry>
		<id>https://wiki.whatwg.org/index.php?title=Video_Metrics&amp;diff=6341</id>
		<title>Video Metrics</title>
		<link rel="alternate" type="text/html" href="https://wiki.whatwg.org/index.php?title=Video_Metrics&amp;diff=6341"/>
		<updated>2011-03-31T10:02:57Z</updated>

		<summary type="html">&lt;p&gt;JeroenW: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Related HTML WG bug:&#039;&#039;&#039; http://www.w3.org/Bugs/Public/show_bug.cgi?id=12399&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Requirements&#039;&#039;&#039;&lt;br /&gt;
For several reasons, we need to expose the performance of media elements to JavaScript.&lt;br /&gt;
&lt;br /&gt;
One concrete use case is that content publishers want to understand the quality of their content as being played back by their users and how much a user is actually playing back. For example, if a video always goes into buffering mode after 1 min for all users - maybe there is a problem in the encoding, or the video is too big for the typical bandwidth/CPU combination. Also, publishers want to track the metrics of how much of their video and audio files is actually being watched.&lt;br /&gt;
&lt;br /&gt;
A further use case is HTTP adaptive streaming, where an author wants to manually implement an algorithm for switching between different resources of different bandwidth or screen size. For example, if the user goes full screen and the user&#039;s machine and bandwidth allow for it, the author might want to switch to a higher resolution video.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Collection of Proposals/Implementations&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Mozilla have implemented the following [http://blog.pearce.org.nz/2011/03/html5-video-painting-performance.html statistics into Firefox]:&lt;br /&gt;
&lt;br /&gt;
* mozParsedFrames - number of frames that have been demuxed and extracted out of the media.&lt;br /&gt;
* mozDecodedFrames - number of frames that have been decoded - converted into YCbCr.&lt;br /&gt;
* mozPresentedFrames - number of frames that have been presented to the rendering pipeline for rendering - were &amp;quot;set as the current image&amp;quot;.&lt;br /&gt;
* mozPaintedFrames - number of frames which were presented to the rendering pipeline and ended up being painted on the screen. Note that if the video is not on screen (e.g. in another tab or scrolled off screen), this counter will not increase.&lt;br /&gt;
* mozPaintDelay - the time delay between presenting the last frame and it being painted on screen (approximately).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Webkit have [https://bugs.webkit.org/show_bug.cgi?id=53322 implemented] these:&lt;br /&gt;
&lt;br /&gt;
* webkitAudioBytesDecoded&lt;br /&gt;
* webkitVideoBytesDecoded&lt;br /&gt;
* webkitDecodedFrames&lt;br /&gt;
* webkitDroppedFrames&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JW Player (using [http://help.adobe.com/nl_NL/AS3LCR/Flash_10.0/flash/net/NetStreamInfo.html actionscript]) broadcasts the following QOS metrics for both RTMP dynamic and HTTP adaptive:&lt;br /&gt;
&lt;br /&gt;
* bandwidth: server-client data rate, in kilobytespersecond.&lt;br /&gt;
* latency: client-server-client roundtrip time, in milliseconds.&lt;br /&gt;
* frameDropRate: number of frames not presented to the viewer, in frames per second.&lt;br /&gt;
* screenWidth / screenHeight: dimensions of the video viewport, in pixels.&lt;br /&gt;
* qualityLevel:&lt;br /&gt;
&lt;br /&gt;
Bandwidth and droprate are running metrics (averaged out). Latency and dimensions are sampled metrics (taken once). For RTMP dynamic, the metrics are broadcast at a settable interval (default 2s). For HTTP adaptive, metrics are calculate and broadcast for the last fragment that was loaded (for bandwidth/latency) or presented (for droprate/dimensions).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Previously the following statistics have been proposed for [http://wiki.whatwg.org/wiki/Adaptive_Streaming#QOS_Metrics HTTP adaptive streaming]:&lt;br /&gt;
&lt;br /&gt;
* downloadRate: The current server-client bandwidth (read-only).&lt;br /&gt;
* videoBitrate: The current video bitrate (read-only).&lt;br /&gt;
* droppedFrames: The total number of frames dropped for this playback session (read-only).&lt;br /&gt;
* decodedFrames: The total number of frames decoded for this playback session (read-only).&lt;br /&gt;
* height: The current height of the video element (already exists).&lt;br /&gt;
* videoHeight: The current height of the videofile (already exists).&lt;br /&gt;
* width: The current width of the video element (already exists).&lt;br /&gt;
* videoWidth: The current width of the videofile (already exists). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Further, a requirement to expose playback rate statistics has come out of [http://lists.w3.org/Archives/Public/public-html/2011Feb/0113.html issue-147]:&lt;br /&gt;
&lt;br /&gt;
* currentPlaybackRate: the rate at which the video/audio is currently playing back&lt;/div&gt;</summary>
		<author><name>JeroenW</name></author>
	</entry>
	<entry>
		<id>https://wiki.whatwg.org/index.php?title=Video_Metrics&amp;diff=6340</id>
		<title>Video Metrics</title>
		<link rel="alternate" type="text/html" href="https://wiki.whatwg.org/index.php?title=Video_Metrics&amp;diff=6340"/>
		<updated>2011-03-31T09:58:46Z</updated>

		<summary type="html">&lt;p&gt;JeroenW: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&#039;&#039;&#039;Related HTML WG bug:&#039;&#039;&#039; http://www.w3.org/Bugs/Public/show_bug.cgi?id=12399&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Requirements&#039;&#039;&#039;&lt;br /&gt;
For several reasons, we need to expose the performance of media elements to JavaScript.&lt;br /&gt;
&lt;br /&gt;
One concrete use case is that content publishers want to understand the quality of their content as being played back by their users and how much a user is actually playing back. For example, if a video always goes into buffering mode after 1 min for all users - maybe there is a problem in the encoding, or the video is too big for the typical bandwidth/CPU combination. Also, publishers want to track the metrics of how much of their video and audio files is actually being watched.&lt;br /&gt;
&lt;br /&gt;
A further use case is HTTP adaptive streaming, where an author wants to manually implement an algorithm for switching between different resources of different bandwidth or screen size. For example, if the user goes full screen and the user&#039;s machine and bandwidth allow for it, the author might want to switch to a higher resolution video.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Collection of Proposals/Implementations&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Mozilla have implemented the following [http://blog.pearce.org.nz/2011/03/html5-video-painting-performance.html statistics into Firefox]:&lt;br /&gt;
&lt;br /&gt;
* mozParsedFrames - number of frames that have been demuxed and extracted out of the media.&lt;br /&gt;
* mozDecodedFrames - number of frames that have been decoded - converted into YCbCr.&lt;br /&gt;
* mozPresentedFrames - number of frames that have been presented to the rendering pipeline for rendering - were &amp;quot;set as the current image&amp;quot;.&lt;br /&gt;
* mozPaintedFrames - number of frames which were presented to the rendering pipeline and ended up being painted on the screen. Note that if the video is not on screen (e.g. in another tab or scrolled off screen), this counter will not increase.&lt;br /&gt;
* mozPaintDelay - the time delay between presenting the last frame and it being painted on screen (approximately).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Webkit have [https://bugs.webkit.org/show_bug.cgi?id=53322 implemented] these:&lt;br /&gt;
&lt;br /&gt;
* webkitAudioBytesDecoded&lt;br /&gt;
* webkitVideoBytesDecoded&lt;br /&gt;
* webkitDecodedFrames&lt;br /&gt;
* webkitDroppedFrames&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
JW Player (using [http://help.adobe.com/nl_NL/AS3LCR/Flash_10.0/flash/net/NetStreamInfo.html actionscript]) broadcasts the following QOS metrics for both RTMP dynamic and HTTP adaptive:&lt;br /&gt;
&lt;br /&gt;
* bandwidth: server-client data rate, in kilobytespersecond.&lt;br /&gt;
* latency: client-server-client roundtrip time, in milliseconds.&lt;br /&gt;
* frameDropRate: number of frames not presented to the viewer, in frames per second.&lt;br /&gt;
* screenWidth / screenHeight: dimensions of the video viewport, in pixels.&lt;br /&gt;
* qualityLevel:&lt;br /&gt;
&lt;br /&gt;
Bandwidth and droprate are running metrics (averaged out). Latency and dimensions are sampled metrics (taken once). For RTMP dynamic, the metrics are broadcast at a settable interval (default 2s). For HTTP adaptive, metrics are broadcast after the loading (for bandwidth/latency) or presenting (for droprate/dimensions) of a video fragment.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Previously the following statistics have been proposed for [http://wiki.whatwg.org/wiki/Adaptive_Streaming#QOS_Metrics HTTP adaptive streaming]:&lt;br /&gt;
&lt;br /&gt;
* downloadRate: The current server-client bandwidth (read-only).&lt;br /&gt;
* videoBitrate: The current video bitrate (read-only).&lt;br /&gt;
* droppedFrames: The total number of frames dropped for this playback session (read-only).&lt;br /&gt;
* decodedFrames: The total number of frames decoded for this playback session (read-only).&lt;br /&gt;
* height: The current height of the video element (already exists).&lt;br /&gt;
* videoHeight: The current height of the videofile (already exists).&lt;br /&gt;
* width: The current width of the video element (already exists).&lt;br /&gt;
* videoWidth: The current width of the videofile (already exists). &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Further, a requirement to expose playback rate statistics has come out of [http://lists.w3.org/Archives/Public/public-html/2011Feb/0113.html issue-147]:&lt;br /&gt;
&lt;br /&gt;
* currentPlaybackRate: the rate at which the video/audio is currently playing back&lt;/div&gt;</summary>
		<author><name>JeroenW</name></author>
	</entry>
	<entry>
		<id>https://wiki.whatwg.org/index.php?title=Adaptive_Streaming&amp;diff=5538</id>
		<title>Adaptive Streaming</title>
		<link rel="alternate" type="text/html" href="https://wiki.whatwg.org/index.php?title=Adaptive_Streaming&amp;diff=5538"/>
		<updated>2010-10-28T09:57:44Z</updated>

		<summary type="html">&lt;p&gt;JeroenW: /* API adaptive streaming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here is a (rough and incomplete) proposal for doing adaptive streaming using open video formats. Key components of the proposal:&lt;br /&gt;
&lt;br /&gt;
* Videos are served as separate, small chunks.&lt;br /&gt;
* Accompanying manifest files provide metadata.&lt;br /&gt;
* The user-agent parses manifests and switches between stream levels.&lt;br /&gt;
* An API provides QOS metrics and enables custom switching logic.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Today, most video on the internet is delivered as progressive download (e.g. Youtube). While this works fine in most cases, there are limitations as it comes to more &#039;&#039;advanced&#039;&#039; uses of video:&lt;br /&gt;
&lt;br /&gt;
* Long-form video (long downloads, waste of bandwidth if user doesn&#039;t watch)&lt;br /&gt;
* Live/DVR video (hard to do as progressive download, unstable)&lt;br /&gt;
* Delivery to mobile devices (lots of buffering due to changing network conditions)&lt;br /&gt;
&lt;br /&gt;
Adaptive streaming aims to solve these issues by:&lt;br /&gt;
&lt;br /&gt;
* Offering multiple versions of a video, at different bitrates / quality levels (e.g. from 100kbps to 2 mbps).&lt;br /&gt;
* Transporting the video not as one big file, but as separate, distinct chunks (e.g. by cutting up the video in small files, or by using range-requests).&lt;br /&gt;
* Allowing user-agents to seamlessly switch between quality levels (e.g. based upon changing device or network conditions), simply by downloading the &#039;&#039;next&#039;&#039; chunk from a different level.&lt;br /&gt;
&lt;br /&gt;
There&#039;s currently three widely used implementations of adaptive HTTP streaming:&lt;br /&gt;
&lt;br /&gt;
* [http://learn.iis.net/page.aspx/627/smooth-streaming/ Microsoft Smooth Streaming], used by Silverlight.&lt;br /&gt;
* [http://www.adobe.com/products/httpdynamicstreaming/ Adobe HTTP Dynamic Streaming], used by Flash.&lt;br /&gt;
* [http://devworld.apple.com/resources/http-streaming/ Apple HTTP Live Streaming], used by Quicktime X.&lt;br /&gt;
&lt;br /&gt;
There&#039;s of course still the dedicated streaming protocols (e.g. RTSP over UDP). Adaptive HTTP streaming does not aim to replace those, as there are various cases that are much better served with a &#039;&#039;real&#039;&#039; streaming approach. However, adaptive HTTP streaming could become the approach for the majority of online video delivery, for many of the same reasons that made progressive HTTP so popular:&lt;br /&gt;
&lt;br /&gt;
* It is easy to understand and implement.&lt;br /&gt;
* It builds upon existing HTTP infrastructure.&lt;br /&gt;
* It centralizes all intelligence (and control) in the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Chunks ==&lt;br /&gt;
&lt;br /&gt;
Every chunk should be a valid video file (header, videotrack, audiotrack). Every chunk should also contain at least 1 keyframe (at the start). This implies every single chunk can be played back by itself.&lt;br /&gt;
&lt;br /&gt;
Beyond validity, the amount of metadata should be kept as small as possible (single-digit kbps overhead).&lt;br /&gt;
&lt;br /&gt;
Codec parameters that can vary between the different quality levels of an adaptive stream are:&lt;br /&gt;
&lt;br /&gt;
* The datarate, dimensions (pixel+display) and framerate of the video track.&lt;br /&gt;
* The datarate, number of channels and sample frequency of the audio track.&lt;br /&gt;
&lt;br /&gt;
In order for quality level switches to occur without artifacts, the start positions of all chunks should align between the various quality levels. If this isn&#039;t the case, user-agents will display artifacts (ticks, skips, black) when a quality level switch occurs. Syncing should not be a requirement though. This will allow legacy content to be used for dynamic streaming with little effort (e.g. remuxing or using a smart server) and little issues (in practive, most keyframes are aligned between different transcodes of a video).&lt;br /&gt;
&lt;br /&gt;
In its most low-tech form, chunks can be stored as separate files-on-disc on a webserver. This poses issues around transcoding (no ecosystem yet) and file management (not everybody loves 100s of files). There are at least two solutions:&lt;br /&gt;
&lt;br /&gt;
1. A serverside module accepts chunk requests, pulls the correct GOP(s) from a video and wraps the necessary metadata.&lt;br /&gt;
2. Clients can accept and process video without headers and use HTTP range-requests to directly get the video data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Manifests ==&lt;br /&gt;
&lt;br /&gt;
The M3U8 manifest format [http://tools.ietf.org/html/draft-pantos-http-live-streaming-04 that Apple specified] is adopted. Generally, both an overall manifest (linking to the various quality levels) and a quality level manifest (linking to the various stream levels) are used. (Though, especially for live streaming, a single quality level may be used).&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of such an overall manifest. It specifies three quality levels, each with its own datarate, codecs and dimensions:&lt;br /&gt;
&lt;br /&gt;
 #EXTM3U &lt;br /&gt;
 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000,CODECS=&amp;quot;vp8,vorbis&amp;quot;,RESOLUTION=240x135&lt;br /&gt;
 http://example.com/low.m3u8 &lt;br /&gt;
 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000,CODECS=&amp;quot;vp8,vorbis&amp;quot;,RESOLUTION=640x360&lt;br /&gt;
 http://example.com/mid.m3u8 &lt;br /&gt;
 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000,CODECS=&amp;quot;vp8,vorbis&amp;quot;,RESOLUTION=1280x720&lt;br /&gt;
 http://example.com/hi.m3u8&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example manifest for one such quality level. It contains a full URL listing of all chunks for this quality level:&lt;br /&gt;
&lt;br /&gt;
 #EXTM3U&lt;br /&gt;
 #EXT-X-MEDIA-SEQUENCE:0&lt;br /&gt;
 #EXT-X-TARGETDURATION:10&lt;br /&gt;
 #EXTINF:10,&lt;br /&gt;
 http://media.example.com/segment1.webm&lt;br /&gt;
 #EXTINF:10,&lt;br /&gt;
 http://media.example.com/segment2.webm&lt;br /&gt;
 #EXTINF:10,&lt;br /&gt;
 http://media.example.com/segment3.webm&lt;br /&gt;
 #EXT-X-ENDLIST&lt;br /&gt;
&lt;br /&gt;
The video framerate, audio sample frequency and number of audio channels cannot be listed here according to the specs. In formats like WebM, Ogg and MPEG-TS (the container Apple specifies), this can be retrieved during demuxing.&lt;br /&gt;
&lt;br /&gt;
The #EXT-X-ENDLIST tag defines the end of a video. If this tag is present, the manifest is supposed to be fixed and the client will not re-load it during playback. If this tag is not present (generally only during live streams), the client should periodically re-fetch the manifest to get additional chunks.&lt;br /&gt;
&lt;br /&gt;
The M3U8 playlist format also provides a mechanism for stream interruptions (#EXT-X-DISCONTINUITY) and for encryption (#EXT-X-KEY). Moreover, regular ID3 tags can be used to enrich the manifest with metadata.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== User-agents ==&lt;br /&gt;
&lt;br /&gt;
The root manifest serves as the single, unique reference point for a adaptive stream. Therefore, user agents in theory need solely its URL to playback the stream. Here&#039;s an example for loading a root manifest: through the *src* attribute of the &amp;lt;video&amp;gt; tag in an HTML page:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;video width=&amp;quot;480&amp;quot; height=&amp;quot;270&amp;quot; src=&amp;quot;http://example.com/video.m3u8&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;http://example.com/video_low.webm&amp;quot;&amp;gt;Download the video&amp;lt;/a&amp;gt;&lt;br /&gt;
 &amp;lt;/video&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this variation, the manifest is loaded through the &amp;lt;source&amp;gt; tag, to provide fallback logic:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;video width=&amp;quot;480&amp;quot; height=&amp;quot;270&amp;quot; &amp;gt;&lt;br /&gt;
   &amp;lt;source src=&amp;quot;http://example.com/video-webm.m3u8&amp;quot; type=&amp;quot;manifest/webm&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;source src=&amp;quot;http://example.com/video-apple.m3u8&amp;quot; type=&amp;quot;manifest/m2ts&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;source src=&amp;quot;http://example.com/video-plain.webm&amp;quot; type=&amp;quot;video/webm&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;http://example.com/video-plain.webm&amp;quot;&amp;gt;Download the video&amp;lt;/a&amp;gt;&lt;br /&gt;
 &amp;lt;/video&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here&#039;s another example for loading the manifest; through the *enclosure* element in an RSS feed:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;rss version=&amp;quot;2.0&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;channel&amp;gt;&lt;br /&gt;
   &amp;lt;title&amp;gt;Example feed&amp;lt;/title&amp;gt;&lt;br /&gt;
   &amp;lt;link&amp;gt;http://example.com/&amp;lt;/link&amp;gt;&lt;br /&gt;
   &amp;lt;description&amp;gt;Example feed with a single adaptive stream.&amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;item&amp;gt;&lt;br /&gt;
     &amp;lt;title&amp;gt;Example stream&amp;lt;/title&amp;gt;&lt;br /&gt;
     &amp;lt;enclosure length=&amp;quot;1487&amp;quot; type=&amp;quot;manifest/webm&amp;quot;&lt;br /&gt;
       url=&amp;quot;http://example.com/video.m3u8&amp;quot; /&amp;gt;&lt;br /&gt;
   &amp;lt;/item&amp;gt;&lt;br /&gt;
 &amp;lt;/channel&amp;gt;&lt;br /&gt;
 &amp;lt;/rss&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Like the manifest parsing, the switching heuristics are upon the user-agent. They can be somewhat of a *secret sauce*. As a basic example, a user-agent can select a quality level if:&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;bitrate&#039;&#039; of the level is &amp;lt; 90% of the server » client &#039;&#039;downloadRate&#039;&#039;.&lt;br /&gt;
* The &#039;&#039;videoWidth&#039;&#039; of the level is &amp;lt; 120% of the video element &#039;&#039;width&#039;&#039;.&lt;br /&gt;
* The delta in &#039;&#039;droppedFrames&#039;&#039; is &amp;lt; 25%  of the delta in &#039;&#039;decodedFrames&#039;&#039; for this level.&lt;br /&gt;
&lt;br /&gt;
Since droppedFrames are only known after a level has started playing, it is generally only a reason for switching down. Based upon the growth rate of droppedFrames, a user-agent might choose to blacklist the quality level for a certain amount of time, or discard it altogether for this playback session.&lt;br /&gt;
&lt;br /&gt;
The quality level selection occurs at the start of every chunk URL fetch. Given an array of levels, the user-agent starts with the highest quality level first and then walks down the list. If the lowest-quality level does not match the criteria, the user-agent still uses it (else there would be no video).&lt;br /&gt;
&lt;br /&gt;
A user-agent typically tries to maintain X (3, 10, 20) seconds of video ready for decoding (buffered). If less than X seconds is available, the user-agent runs it quality level selection and requests another chunk.&lt;br /&gt;
&lt;br /&gt;
There is a tie-in between the length of a chunk, the bufferLenght and the speed with which a user-agent adapts to changing conditions. For example, should the bandwidth drop dramatically, 1 or 2 high-quality chunks will still be played from buffer before the first lower-quality chunk is shown. The other way around is also true: should a user go fullscreen, it will take some time until the stream switches to high quality. Lower bufferLenghts increase responsiveness but also increase the possiblity of buffer underruns.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Scripting ==&lt;br /&gt;
&lt;br /&gt;
Certain user-agents might not offer access to adaptive streaming heuristics. Other user-agents might, or should even do so. The obvious case is a webbrowser supporting the &amp;lt;video&amp;gt; element and a javascript engine:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== QOS Metrics ===&lt;br /&gt;
&lt;br /&gt;
The video element should provides accessors for retrieving quality of service metrics:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;downloadRate&#039;&#039;&#039;: The current server-client bandwidth (read-only).&lt;br /&gt;
* &#039;&#039;&#039;videoBitrate&#039;&#039;&#039;: The current video bitrate (read-only).&lt;br /&gt;
* &#039;&#039;&#039;droppedFrames&#039;&#039;&#039;: The total number of frames dropped for this playback session (read-only).&lt;br /&gt;
* &#039;&#039;&#039;decodedFrames&#039;&#039;&#039;: The total number of frames decoded for this playback session (read-only).&lt;br /&gt;
* &#039;&#039;&#039;height&#039;&#039;&#039;: The current height of the video element (already exists).&lt;br /&gt;
* &#039;&#039;&#039;videoHeight&#039;&#039;&#039;: The current height of the videofile (already exists).&lt;br /&gt;
* &#039;&#039;&#039;width&#039;&#039;&#039;: The current width of the video element (already exists).&lt;br /&gt;
* &#039;&#039;&#039;videoWidth&#039;&#039;&#039;: The current width of the videofile (already exists).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Native adaptive streaming ===&lt;br /&gt;
&lt;br /&gt;
In case a user-agent has manifest parsing / level switching heuristics built-in, the video element can provides access to the stream levels:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;currentLevel&#039;&#039;&#039;: The currently playing stream level.&lt;br /&gt;
* &#039;&#039;&#039;levels&#039;&#039;&#039;: An array of all stream levels (as parsed from the manifests). Example:&lt;br /&gt;
&lt;br /&gt;
 [{&lt;br /&gt;
   bitrate: 100000, &lt;br /&gt;
   codecs: &#039;vp8,vorbis&#039;,&lt;br /&gt;
   duration: 132,&lt;br /&gt;
   height: 180,&lt;br /&gt;
   url: manifest_100.m3u8,&lt;br /&gt;
   width: 240&lt;br /&gt;
 },{&lt;br /&gt;
   bitrate: 500000,&lt;br /&gt;
   codecs: &#039;vp8,vorbis&#039;,&lt;br /&gt;
   duration: 132,&lt;br /&gt;
   height: 360,&lt;br /&gt;
   url: manifest_500.m3u8,&lt;br /&gt;
   width: 640&lt;br /&gt;
 }]&lt;br /&gt;
&lt;br /&gt;
In addition to this, the video element provides an event to notify scripts of changes in the current stream level:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;levelChange&#039;&#039;&#039;: the currentLevel attribute has just been updated.&lt;br /&gt;
&lt;br /&gt;
Last, the video element provides functionality to override the user agent&#039;s built-in heuristics:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;setLevel(level)&#039;&#039;&#039;: This method forces the user to switch to another stream level. Invoking this method disables a user-agent&#039;s adaptive streaming heuristics. Use *setLevel(-1)* to enable heuristics again.&lt;br /&gt;
* &#039;&#039;&#039;bufferLength&#039;&#039;&#039;: This attribute controls how much videodata (in seconds) a user-agent should strive to keep buffered.&lt;br /&gt;
&lt;br /&gt;
An important example for &#039;&#039;&#039;bufferLength&#039;&#039;&#039;: a website owner might set this to a very high value to enable viewers on a low bandwidth to wait for buffering and still see a high-quality video.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== API adaptive streaming ===&lt;br /&gt;
&lt;br /&gt;
In case a user-agent does not have manifest parsing and level switching heuristics built-in, the video element can still accomodate adaptive streaming through a small stream API:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;appendVideo(url,[range])&#039;&#039;&#039;: fetch the URL and append the video to the currently playing video.&lt;br /&gt;
* &#039;&#039;&#039;bufferlength&#039;&#039;&#039; (read-only): get the current video buffer amount, in seconds.&lt;br /&gt;
&lt;br /&gt;
The single call allows developers to build adaptive HTTP streaming inside the javascripting layer. Manifest parsing and stream level APIs are not needed. The quality of service metrics are still needed though:&lt;br /&gt;
&lt;br /&gt;
* When the video plays fine, chunks fro the same quality level are constantly appended.&lt;br /&gt;
* When a switch to a different quality level is made,  chunks from a different quality level are appended.&lt;br /&gt;
* When the user seeks to a different position in the video, it&#039;s &#039;&#039;&#039;src&#039;&#039;&#039; is simply set to the appropriate chunk at that position.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;bufferlength&#039;&#039;&#039; getter reports upon the actual amount of data that&#039;s in the buffer. Scripts cannot presume any video they append to the videoElement is immediately available: the URL has to be resolved, the data has to be fetched and the data has to be demuxed. &lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;appendVideo&#039;&#039;&#039; call implies that properties such as &#039;&#039;duration&#039;&#039;, &#039;&#039;videoHeight&#039;&#039; and &#039;&#039;videoWidth&#039;&#039; may change during a playback session.&lt;br /&gt;
&lt;br /&gt;
A number of rules have to be set up as to how the concatenation will actually work. For example:&lt;br /&gt;
&lt;br /&gt;
* In order to allow user-agents to use a single decoding pipeline, the current video and the one that&#039;s appended  should contain the same container format and A/V codecs.&lt;br /&gt;
* Video is appended on a frame-by-frame basis (no bytedata).&lt;br /&gt;
* [Audio is appended by slightly extending the data and applying a crossfade?]&lt;br /&gt;
&lt;br /&gt;
The optional &#039;&#039;range&#039;&#039; parameter instructs the user-agent to only request a certain byterange.&lt;br /&gt;
&lt;br /&gt;
== Rationale ==&lt;br /&gt;
&lt;br /&gt;
Finally, some rationale for the choices made in this proposal. Why chunks and a manifest? Why not, for example, range-requests and &amp;lt;source&amp;gt; tags?&lt;br /&gt;
&lt;br /&gt;
First and foremost, we need a format that works not only in HTML5 browsers, but also in, for example, mobile apps (Android/Blackberry/iOS), desktop players (Miro/Quicktime/VLC) and big screen devices (Roku, Boxee, PS3). Especially for the very small screens (3G network) and large screens (full HD), adaptive streaming is incredibly valuable. Tayloring a solution too much towards the HTML5 syntax and browser environment will hinder broad adoption of an open video standard. Adaptive streaming and HTML5 should work nice together, but adaptive streaming should not be relying on HTML5.&lt;br /&gt;
&lt;br /&gt;
That said:&lt;br /&gt;
&lt;br /&gt;
* Providing the low-tech scenario of storing chunks as separate files on the webserver enables adaptive streaming in cases where either the server, the user-agent (apps / players / settops) or the network (firewalls, cellulars) does not support something like range-requests. As an example, implementing adaptive streaming using range-requests in Adobe Flash (e.g. as temporary fallback) would not be possible, since the range-request header is blocked.&lt;br /&gt;
* Ecosystem partners (CDNs, encoding providers, landmark publishers, etc) are already getting used to ánd building tools around the concept of *chunked* video streams. Examples are log aggregators that roll up chunks servings into a single logline, or encoders that simultaneously build multiple stream levels, chunk them up and render their manifests.&lt;br /&gt;
* With just the QOS metrics (*downloadRate* and *decodedFrames*) in place, it will be possible to build adaptive-streaming-like solutions (using range-requests) in javascript. In Flash, this same functionality is supported (and very popular) within both Flowplayer and JW Player. True adaptive streaming (continous switching without buffering) won&#039;t be possible, but the experience is good enough to suit people that don&#039;t have the encoder or browser (yet) to build or playback adaptive streams.&lt;/div&gt;</summary>
		<author><name>JeroenW</name></author>
	</entry>
	<entry>
		<id>https://wiki.whatwg.org/index.php?title=Adaptive_Streaming&amp;diff=5537</id>
		<title>Adaptive Streaming</title>
		<link rel="alternate" type="text/html" href="https://wiki.whatwg.org/index.php?title=Adaptive_Streaming&amp;diff=5537"/>
		<updated>2010-10-28T09:56:59Z</updated>

		<summary type="html">&lt;p&gt;JeroenW: /* API adaptive streaming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here is a (rough and incomplete) proposal for doing adaptive streaming using open video formats. Key components of the proposal:&lt;br /&gt;
&lt;br /&gt;
* Videos are served as separate, small chunks.&lt;br /&gt;
* Accompanying manifest files provide metadata.&lt;br /&gt;
* The user-agent parses manifests and switches between stream levels.&lt;br /&gt;
* An API provides QOS metrics and enables custom switching logic.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Today, most video on the internet is delivered as progressive download (e.g. Youtube). While this works fine in most cases, there are limitations as it comes to more &#039;&#039;advanced&#039;&#039; uses of video:&lt;br /&gt;
&lt;br /&gt;
* Long-form video (long downloads, waste of bandwidth if user doesn&#039;t watch)&lt;br /&gt;
* Live/DVR video (hard to do as progressive download, unstable)&lt;br /&gt;
* Delivery to mobile devices (lots of buffering due to changing network conditions)&lt;br /&gt;
&lt;br /&gt;
Adaptive streaming aims to solve these issues by:&lt;br /&gt;
&lt;br /&gt;
* Offering multiple versions of a video, at different bitrates / quality levels (e.g. from 100kbps to 2 mbps).&lt;br /&gt;
* Transporting the video not as one big file, but as separate, distinct chunks (e.g. by cutting up the video in small files, or by using range-requests).&lt;br /&gt;
* Allowing user-agents to seamlessly switch between quality levels (e.g. based upon changing device or network conditions), simply by downloading the &#039;&#039;next&#039;&#039; chunk from a different level.&lt;br /&gt;
&lt;br /&gt;
There&#039;s currently three widely used implementations of adaptive HTTP streaming:&lt;br /&gt;
&lt;br /&gt;
* [http://learn.iis.net/page.aspx/627/smooth-streaming/ Microsoft Smooth Streaming], used by Silverlight.&lt;br /&gt;
* [http://www.adobe.com/products/httpdynamicstreaming/ Adobe HTTP Dynamic Streaming], used by Flash.&lt;br /&gt;
* [http://devworld.apple.com/resources/http-streaming/ Apple HTTP Live Streaming], used by Quicktime X.&lt;br /&gt;
&lt;br /&gt;
There&#039;s of course still the dedicated streaming protocols (e.g. RTSP over UDP). Adaptive HTTP streaming does not aim to replace those, as there are various cases that are much better served with a &#039;&#039;real&#039;&#039; streaming approach. However, adaptive HTTP streaming could become the approach for the majority of online video delivery, for many of the same reasons that made progressive HTTP so popular:&lt;br /&gt;
&lt;br /&gt;
* It is easy to understand and implement.&lt;br /&gt;
* It builds upon existing HTTP infrastructure.&lt;br /&gt;
* It centralizes all intelligence (and control) in the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Chunks ==&lt;br /&gt;
&lt;br /&gt;
Every chunk should be a valid video file (header, videotrack, audiotrack). Every chunk should also contain at least 1 keyframe (at the start). This implies every single chunk can be played back by itself.&lt;br /&gt;
&lt;br /&gt;
Beyond validity, the amount of metadata should be kept as small as possible (single-digit kbps overhead).&lt;br /&gt;
&lt;br /&gt;
Codec parameters that can vary between the different quality levels of an adaptive stream are:&lt;br /&gt;
&lt;br /&gt;
* The datarate, dimensions (pixel+display) and framerate of the video track.&lt;br /&gt;
* The datarate, number of channels and sample frequency of the audio track.&lt;br /&gt;
&lt;br /&gt;
In order for quality level switches to occur without artifacts, the start positions of all chunks should align between the various quality levels. If this isn&#039;t the case, user-agents will display artifacts (ticks, skips, black) when a quality level switch occurs. Syncing should not be a requirement though. This will allow legacy content to be used for dynamic streaming with little effort (e.g. remuxing or using a smart server) and little issues (in practive, most keyframes are aligned between different transcodes of a video).&lt;br /&gt;
&lt;br /&gt;
In its most low-tech form, chunks can be stored as separate files-on-disc on a webserver. This poses issues around transcoding (no ecosystem yet) and file management (not everybody loves 100s of files). There are at least two solutions:&lt;br /&gt;
&lt;br /&gt;
1. A serverside module accepts chunk requests, pulls the correct GOP(s) from a video and wraps the necessary metadata.&lt;br /&gt;
2. Clients can accept and process video without headers and use HTTP range-requests to directly get the video data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Manifests ==&lt;br /&gt;
&lt;br /&gt;
The M3U8 manifest format [http://tools.ietf.org/html/draft-pantos-http-live-streaming-04 that Apple specified] is adopted. Generally, both an overall manifest (linking to the various quality levels) and a quality level manifest (linking to the various stream levels) are used. (Though, especially for live streaming, a single quality level may be used).&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of such an overall manifest. It specifies three quality levels, each with its own datarate, codecs and dimensions:&lt;br /&gt;
&lt;br /&gt;
 #EXTM3U &lt;br /&gt;
 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000,CODECS=&amp;quot;vp8,vorbis&amp;quot;,RESOLUTION=240x135&lt;br /&gt;
 http://example.com/low.m3u8 &lt;br /&gt;
 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000,CODECS=&amp;quot;vp8,vorbis&amp;quot;,RESOLUTION=640x360&lt;br /&gt;
 http://example.com/mid.m3u8 &lt;br /&gt;
 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000,CODECS=&amp;quot;vp8,vorbis&amp;quot;,RESOLUTION=1280x720&lt;br /&gt;
 http://example.com/hi.m3u8&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example manifest for one such quality level. It contains a full URL listing of all chunks for this quality level:&lt;br /&gt;
&lt;br /&gt;
 #EXTM3U&lt;br /&gt;
 #EXT-X-MEDIA-SEQUENCE:0&lt;br /&gt;
 #EXT-X-TARGETDURATION:10&lt;br /&gt;
 #EXTINF:10,&lt;br /&gt;
 http://media.example.com/segment1.webm&lt;br /&gt;
 #EXTINF:10,&lt;br /&gt;
 http://media.example.com/segment2.webm&lt;br /&gt;
 #EXTINF:10,&lt;br /&gt;
 http://media.example.com/segment3.webm&lt;br /&gt;
 #EXT-X-ENDLIST&lt;br /&gt;
&lt;br /&gt;
The video framerate, audio sample frequency and number of audio channels cannot be listed here according to the specs. In formats like WebM, Ogg and MPEG-TS (the container Apple specifies), this can be retrieved during demuxing.&lt;br /&gt;
&lt;br /&gt;
The #EXT-X-ENDLIST tag defines the end of a video. If this tag is present, the manifest is supposed to be fixed and the client will not re-load it during playback. If this tag is not present (generally only during live streams), the client should periodically re-fetch the manifest to get additional chunks.&lt;br /&gt;
&lt;br /&gt;
The M3U8 playlist format also provides a mechanism for stream interruptions (#EXT-X-DISCONTINUITY) and for encryption (#EXT-X-KEY). Moreover, regular ID3 tags can be used to enrich the manifest with metadata.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== User-agents ==&lt;br /&gt;
&lt;br /&gt;
The root manifest serves as the single, unique reference point for a adaptive stream. Therefore, user agents in theory need solely its URL to playback the stream. Here&#039;s an example for loading a root manifest: through the *src* attribute of the &amp;lt;video&amp;gt; tag in an HTML page:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;video width=&amp;quot;480&amp;quot; height=&amp;quot;270&amp;quot; src=&amp;quot;http://example.com/video.m3u8&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;http://example.com/video_low.webm&amp;quot;&amp;gt;Download the video&amp;lt;/a&amp;gt;&lt;br /&gt;
 &amp;lt;/video&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this variation, the manifest is loaded through the &amp;lt;source&amp;gt; tag, to provide fallback logic:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;video width=&amp;quot;480&amp;quot; height=&amp;quot;270&amp;quot; &amp;gt;&lt;br /&gt;
   &amp;lt;source src=&amp;quot;http://example.com/video-webm.m3u8&amp;quot; type=&amp;quot;manifest/webm&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;source src=&amp;quot;http://example.com/video-apple.m3u8&amp;quot; type=&amp;quot;manifest/m2ts&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;source src=&amp;quot;http://example.com/video-plain.webm&amp;quot; type=&amp;quot;video/webm&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;http://example.com/video-plain.webm&amp;quot;&amp;gt;Download the video&amp;lt;/a&amp;gt;&lt;br /&gt;
 &amp;lt;/video&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here&#039;s another example for loading the manifest; through the *enclosure* element in an RSS feed:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;rss version=&amp;quot;2.0&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;channel&amp;gt;&lt;br /&gt;
   &amp;lt;title&amp;gt;Example feed&amp;lt;/title&amp;gt;&lt;br /&gt;
   &amp;lt;link&amp;gt;http://example.com/&amp;lt;/link&amp;gt;&lt;br /&gt;
   &amp;lt;description&amp;gt;Example feed with a single adaptive stream.&amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;item&amp;gt;&lt;br /&gt;
     &amp;lt;title&amp;gt;Example stream&amp;lt;/title&amp;gt;&lt;br /&gt;
     &amp;lt;enclosure length=&amp;quot;1487&amp;quot; type=&amp;quot;manifest/webm&amp;quot;&lt;br /&gt;
       url=&amp;quot;http://example.com/video.m3u8&amp;quot; /&amp;gt;&lt;br /&gt;
   &amp;lt;/item&amp;gt;&lt;br /&gt;
 &amp;lt;/channel&amp;gt;&lt;br /&gt;
 &amp;lt;/rss&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Like the manifest parsing, the switching heuristics are upon the user-agent. They can be somewhat of a *secret sauce*. As a basic example, a user-agent can select a quality level if:&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;bitrate&#039;&#039; of the level is &amp;lt; 90% of the server » client &#039;&#039;downloadRate&#039;&#039;.&lt;br /&gt;
* The &#039;&#039;videoWidth&#039;&#039; of the level is &amp;lt; 120% of the video element &#039;&#039;width&#039;&#039;.&lt;br /&gt;
* The delta in &#039;&#039;droppedFrames&#039;&#039; is &amp;lt; 25%  of the delta in &#039;&#039;decodedFrames&#039;&#039; for this level.&lt;br /&gt;
&lt;br /&gt;
Since droppedFrames are only known after a level has started playing, it is generally only a reason for switching down. Based upon the growth rate of droppedFrames, a user-agent might choose to blacklist the quality level for a certain amount of time, or discard it altogether for this playback session.&lt;br /&gt;
&lt;br /&gt;
The quality level selection occurs at the start of every chunk URL fetch. Given an array of levels, the user-agent starts with the highest quality level first and then walks down the list. If the lowest-quality level does not match the criteria, the user-agent still uses it (else there would be no video).&lt;br /&gt;
&lt;br /&gt;
A user-agent typically tries to maintain X (3, 10, 20) seconds of video ready for decoding (buffered). If less than X seconds is available, the user-agent runs it quality level selection and requests another chunk.&lt;br /&gt;
&lt;br /&gt;
There is a tie-in between the length of a chunk, the bufferLenght and the speed with which a user-agent adapts to changing conditions. For example, should the bandwidth drop dramatically, 1 or 2 high-quality chunks will still be played from buffer before the first lower-quality chunk is shown. The other way around is also true: should a user go fullscreen, it will take some time until the stream switches to high quality. Lower bufferLenghts increase responsiveness but also increase the possiblity of buffer underruns.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Scripting ==&lt;br /&gt;
&lt;br /&gt;
Certain user-agents might not offer access to adaptive streaming heuristics. Other user-agents might, or should even do so. The obvious case is a webbrowser supporting the &amp;lt;video&amp;gt; element and a javascript engine:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== QOS Metrics ===&lt;br /&gt;
&lt;br /&gt;
The video element should provides accessors for retrieving quality of service metrics:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;downloadRate&#039;&#039;&#039;: The current server-client bandwidth (read-only).&lt;br /&gt;
* &#039;&#039;&#039;videoBitrate&#039;&#039;&#039;: The current video bitrate (read-only).&lt;br /&gt;
* &#039;&#039;&#039;droppedFrames&#039;&#039;&#039;: The total number of frames dropped for this playback session (read-only).&lt;br /&gt;
* &#039;&#039;&#039;decodedFrames&#039;&#039;&#039;: The total number of frames decoded for this playback session (read-only).&lt;br /&gt;
* &#039;&#039;&#039;height&#039;&#039;&#039;: The current height of the video element (already exists).&lt;br /&gt;
* &#039;&#039;&#039;videoHeight&#039;&#039;&#039;: The current height of the videofile (already exists).&lt;br /&gt;
* &#039;&#039;&#039;width&#039;&#039;&#039;: The current width of the video element (already exists).&lt;br /&gt;
* &#039;&#039;&#039;videoWidth&#039;&#039;&#039;: The current width of the videofile (already exists).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Native adaptive streaming ===&lt;br /&gt;
&lt;br /&gt;
In case a user-agent has manifest parsing / level switching heuristics built-in, the video element can provides access to the stream levels:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;currentLevel&#039;&#039;&#039;: The currently playing stream level.&lt;br /&gt;
* &#039;&#039;&#039;levels&#039;&#039;&#039;: An array of all stream levels (as parsed from the manifests). Example:&lt;br /&gt;
&lt;br /&gt;
 [{&lt;br /&gt;
   bitrate: 100000, &lt;br /&gt;
   codecs: &#039;vp8,vorbis&#039;,&lt;br /&gt;
   duration: 132,&lt;br /&gt;
   height: 180,&lt;br /&gt;
   url: manifest_100.m3u8,&lt;br /&gt;
   width: 240&lt;br /&gt;
 },{&lt;br /&gt;
   bitrate: 500000,&lt;br /&gt;
   codecs: &#039;vp8,vorbis&#039;,&lt;br /&gt;
   duration: 132,&lt;br /&gt;
   height: 360,&lt;br /&gt;
   url: manifest_500.m3u8,&lt;br /&gt;
   width: 640&lt;br /&gt;
 }]&lt;br /&gt;
&lt;br /&gt;
In addition to this, the video element provides an event to notify scripts of changes in the current stream level:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;levelChange&#039;&#039;&#039;: the currentLevel attribute has just been updated.&lt;br /&gt;
&lt;br /&gt;
Last, the video element provides functionality to override the user agent&#039;s built-in heuristics:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;setLevel(level)&#039;&#039;&#039;: This method forces the user to switch to another stream level. Invoking this method disables a user-agent&#039;s adaptive streaming heuristics. Use *setLevel(-1)* to enable heuristics again.&lt;br /&gt;
* &#039;&#039;&#039;bufferLength&#039;&#039;&#039;: This attribute controls how much videodata (in seconds) a user-agent should strive to keep buffered.&lt;br /&gt;
&lt;br /&gt;
An important example for &#039;&#039;&#039;bufferLength&#039;&#039;&#039;: a website owner might set this to a very high value to enable viewers on a low bandwidth to wait for buffering and still see a high-quality video.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== API adaptive streaming ===&lt;br /&gt;
&lt;br /&gt;
In case a user-agent does not have manifest parsing and level switching heuristics built-in, the video element can still accomodate adaptive streaming through a small stream API:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;appendVideo(url,[range])&#039;&#039;&#039;: fetch the URL and append the video to the currently playing video.&lt;br /&gt;
* &#039;&#039;&#039;bufferlength&#039;&#039;&#039; (read-only): get the current video buffer amount, in seconds.&lt;br /&gt;
&lt;br /&gt;
The single call allows developers to build adaptive HTTP streaming inside the javascripting layer. Manifest parsing and stream level APIs are not needed. The quality of service metrics are still needed though:&lt;br /&gt;
&lt;br /&gt;
* When the video plays fine, chunks fro the same quality level are constantly appended.&lt;br /&gt;
* When a switch to a different quality level is made,  chunks from a different quality level are appended.&lt;br /&gt;
* When the user seeks to a different position in the video, it&#039;s &#039;&#039;&#039;src&#039;&#039;&#039; is simply set to the appropriate chunk at that position.&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;bufferlength&#039;&#039;&#039; getter reports upon the actual amount of data that&#039;s in the buffer. Scripts cannot presume any video they append to the videoElement is immediately available: the URL has to be resolved, the data has to be fetched and the data has to be demuxed. &lt;br /&gt;
&lt;br /&gt;
This call implies that properties such as &#039;&#039;duration&#039;&#039;, &#039;&#039;videoHeight&#039;&#039; and &#039;&#039;videoWidth&#039;&#039; may change during a playback session.&lt;br /&gt;
&lt;br /&gt;
A number of rules have to be set up as to how the concatenation will actually work. For example:&lt;br /&gt;
&lt;br /&gt;
* In order to allow user-agents to use a single decoding pipeline, the current video and the one that&#039;s appended  should contain the same container format and A/V codecs.&lt;br /&gt;
* Video is appended on a frame-by-frame basis (no bytedata).&lt;br /&gt;
* [Audio is appended by slightly extending the data and applying a crossfade?]&lt;br /&gt;
&lt;br /&gt;
The optional &#039;&#039;range&#039;&#039; parameter instructs the user-agent to only request a certain byterange.&lt;br /&gt;
&lt;br /&gt;
== Rationale ==&lt;br /&gt;
&lt;br /&gt;
Finally, some rationale for the choices made in this proposal. Why chunks and a manifest? Why not, for example, range-requests and &amp;lt;source&amp;gt; tags?&lt;br /&gt;
&lt;br /&gt;
First and foremost, we need a format that works not only in HTML5 browsers, but also in, for example, mobile apps (Android/Blackberry/iOS), desktop players (Miro/Quicktime/VLC) and big screen devices (Roku, Boxee, PS3). Especially for the very small screens (3G network) and large screens (full HD), adaptive streaming is incredibly valuable. Tayloring a solution too much towards the HTML5 syntax and browser environment will hinder broad adoption of an open video standard. Adaptive streaming and HTML5 should work nice together, but adaptive streaming should not be relying on HTML5.&lt;br /&gt;
&lt;br /&gt;
That said:&lt;br /&gt;
&lt;br /&gt;
* Providing the low-tech scenario of storing chunks as separate files on the webserver enables adaptive streaming in cases where either the server, the user-agent (apps / players / settops) or the network (firewalls, cellulars) does not support something like range-requests. As an example, implementing adaptive streaming using range-requests in Adobe Flash (e.g. as temporary fallback) would not be possible, since the range-request header is blocked.&lt;br /&gt;
* Ecosystem partners (CDNs, encoding providers, landmark publishers, etc) are already getting used to ánd building tools around the concept of *chunked* video streams. Examples are log aggregators that roll up chunks servings into a single logline, or encoders that simultaneously build multiple stream levels, chunk them up and render their manifests.&lt;br /&gt;
* With just the QOS metrics (*downloadRate* and *decodedFrames*) in place, it will be possible to build adaptive-streaming-like solutions (using range-requests) in javascript. In Flash, this same functionality is supported (and very popular) within both Flowplayer and JW Player. True adaptive streaming (continous switching without buffering) won&#039;t be possible, but the experience is good enough to suit people that don&#039;t have the encoder or browser (yet) to build or playback adaptive streams.&lt;/div&gt;</summary>
		<author><name>JeroenW</name></author>
	</entry>
	<entry>
		<id>https://wiki.whatwg.org/index.php?title=Adaptive_Streaming&amp;diff=5536</id>
		<title>Adaptive Streaming</title>
		<link rel="alternate" type="text/html" href="https://wiki.whatwg.org/index.php?title=Adaptive_Streaming&amp;diff=5536"/>
		<updated>2010-10-26T10:40:37Z</updated>

		<summary type="html">&lt;p&gt;JeroenW: /* API adaptive streaming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here is a (rough and incomplete) proposal for doing adaptive streaming using open video formats. Key components of the proposal:&lt;br /&gt;
&lt;br /&gt;
* Videos are served as separate, small chunks.&lt;br /&gt;
* Accompanying manifest files provide metadata.&lt;br /&gt;
* The user-agent parses manifests and switches between stream levels.&lt;br /&gt;
* An API provides QOS metrics and enables custom switching logic.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Today, most video on the internet is delivered as progressive download (e.g. Youtube). While this works fine in most cases, there are limitations as it comes to more &#039;&#039;advanced&#039;&#039; uses of video:&lt;br /&gt;
&lt;br /&gt;
* Long-form video (long downloads, waste of bandwidth if user doesn&#039;t watch)&lt;br /&gt;
* Live/DVR video (hard to do as progressive download, unstable)&lt;br /&gt;
* Delivery to mobile devices (lots of buffering due to changing network conditions)&lt;br /&gt;
&lt;br /&gt;
Adaptive streaming aims to solve these issues by:&lt;br /&gt;
&lt;br /&gt;
* Offering multiple versions of a video, at different bitrates / quality levels (e.g. from 100kbps to 2 mbps).&lt;br /&gt;
* Transporting the video not as one big file, but as separate, distinct chunks (e.g. by cutting up the video in small files, or by using range-requests).&lt;br /&gt;
* Allowing user-agents to seamlessly switch between quality levels (e.g. based upon changing device or network conditions), simply by downloading the &#039;&#039;next&#039;&#039; chunk from a different level.&lt;br /&gt;
&lt;br /&gt;
There&#039;s currently three widely used implementations of adaptive HTTP streaming:&lt;br /&gt;
&lt;br /&gt;
* [http://learn.iis.net/page.aspx/627/smooth-streaming/ Microsoft Smooth Streaming], used by Silverlight.&lt;br /&gt;
* [http://www.adobe.com/products/httpdynamicstreaming/ Adobe HTTP Dynamic Streaming], used by Flash.&lt;br /&gt;
* [http://devworld.apple.com/resources/http-streaming/ Apple HTTP Live Streaming], used by Quicktime X.&lt;br /&gt;
&lt;br /&gt;
There&#039;s of course still the dedicated streaming protocols (e.g. RTSP over UDP). Adaptive HTTP streaming does not aim to replace those, as there are various cases that are much better served with a &#039;&#039;real&#039;&#039; streaming approach. However, adaptive HTTP streaming could become the approach for the majority of online video delivery, for many of the same reasons that made progressive HTTP so popular:&lt;br /&gt;
&lt;br /&gt;
* It is easy to understand and implement.&lt;br /&gt;
* It builds upon existing HTTP infrastructure.&lt;br /&gt;
* It centralizes all intelligence (and control) in the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Chunks ==&lt;br /&gt;
&lt;br /&gt;
Every chunk should be a valid video file (header, videotrack, audiotrack). Every chunk should also contain at least 1 keyframe (at the start). This implies every single chunk can be played back by itself.&lt;br /&gt;
&lt;br /&gt;
Beyond validity, the amount of metadata should be kept as small as possible (single-digit kbps overhead).&lt;br /&gt;
&lt;br /&gt;
Codec parameters that can vary between the different quality levels of an adaptive stream are:&lt;br /&gt;
&lt;br /&gt;
* The datarate, dimensions (pixel+display) and framerate of the video track.&lt;br /&gt;
* The datarate, number of channels and sample frequency of the audio track.&lt;br /&gt;
&lt;br /&gt;
In order for quality level switches to occur without artifacts, the start positions of all chunks should align between the various quality levels. If this isn&#039;t the case, user-agents will display artifacts (ticks, skips, black) when a quality level switch occurs. Syncing should not be a requirement though. This will allow legacy content to be used for dynamic streaming with little effort (e.g. remuxing or using a smart server) and little issues (in practive, most keyframes are aligned between different transcodes of a video).&lt;br /&gt;
&lt;br /&gt;
In its most low-tech form, chunks can be stored as separate files-on-disc on a webserver. This poses issues around transcoding (no ecosystem yet) and file management (not everybody loves 100s of files). There are at least two solutions:&lt;br /&gt;
&lt;br /&gt;
1. A serverside module accepts chunk requests, pulls the correct GOP(s) from a video and wraps the necessary metadata.&lt;br /&gt;
2. Clients can accept and process video without headers and use HTTP range-requests to directly get the video data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Manifests ==&lt;br /&gt;
&lt;br /&gt;
The M3U8 manifest format [http://tools.ietf.org/html/draft-pantos-http-live-streaming-04 that Apple specified] is adopted. Generally, both an overall manifest (linking to the various quality levels) and a quality level manifest (linking to the various stream levels) are used. (Though, especially for live streaming, a single quality level may be used).&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of such an overall manifest. It specifies three quality levels, each with its own datarate, codecs and dimensions:&lt;br /&gt;
&lt;br /&gt;
 #EXTM3U &lt;br /&gt;
 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000,CODECS=&amp;quot;vp8,vorbis&amp;quot;,RESOLUTION=240x135&lt;br /&gt;
 http://example.com/low.m3u8 &lt;br /&gt;
 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000,CODECS=&amp;quot;vp8,vorbis&amp;quot;,RESOLUTION=640x360&lt;br /&gt;
 http://example.com/mid.m3u8 &lt;br /&gt;
 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000,CODECS=&amp;quot;vp8,vorbis&amp;quot;,RESOLUTION=1280x720&lt;br /&gt;
 http://example.com/hi.m3u8&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example manifest for one such quality level. It contains a full URL listing of all chunks for this quality level:&lt;br /&gt;
&lt;br /&gt;
 #EXTM3U&lt;br /&gt;
 #EXT-X-MEDIA-SEQUENCE:0&lt;br /&gt;
 #EXT-X-TARGETDURATION:10&lt;br /&gt;
 #EXTINF:10,&lt;br /&gt;
 http://media.example.com/segment1.webm&lt;br /&gt;
 #EXTINF:10,&lt;br /&gt;
 http://media.example.com/segment2.webm&lt;br /&gt;
 #EXTINF:10,&lt;br /&gt;
 http://media.example.com/segment3.webm&lt;br /&gt;
 #EXT-X-ENDLIST&lt;br /&gt;
&lt;br /&gt;
The video framerate, audio sample frequency and number of audio channels cannot be listed here according to the specs. In formats like WebM, Ogg and MPEG-TS (the container Apple specifies), this can be retrieved during demuxing.&lt;br /&gt;
&lt;br /&gt;
The #EXT-X-ENDLIST tag defines the end of a video. If this tag is present, the manifest is supposed to be fixed and the client will not re-load it during playback. If this tag is not present (generally only during live streams), the client should periodically re-fetch the manifest to get additional chunks.&lt;br /&gt;
&lt;br /&gt;
The M3U8 playlist format also provides a mechanism for stream interruptions (#EXT-X-DISCONTINUITY) and for encryption (#EXT-X-KEY). Moreover, regular ID3 tags can be used to enrich the manifest with metadata.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== User-agents ==&lt;br /&gt;
&lt;br /&gt;
The root manifest serves as the single, unique reference point for a adaptive stream. Therefore, user agents in theory need solely its URL to playback the stream. Here&#039;s an example for loading a root manifest: through the *src* attribute of the &amp;lt;video&amp;gt; tag in an HTML page:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;video width=&amp;quot;480&amp;quot; height=&amp;quot;270&amp;quot; src=&amp;quot;http://example.com/video.m3u8&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;http://example.com/video_low.webm&amp;quot;&amp;gt;Download the video&amp;lt;/a&amp;gt;&lt;br /&gt;
 &amp;lt;/video&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this variation, the manifest is loaded through the &amp;lt;source&amp;gt; tag, to provide fallback logic:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;video width=&amp;quot;480&amp;quot; height=&amp;quot;270&amp;quot; &amp;gt;&lt;br /&gt;
   &amp;lt;source src=&amp;quot;http://example.com/video-webm.m3u8&amp;quot; type=&amp;quot;manifest/webm&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;source src=&amp;quot;http://example.com/video-apple.m3u8&amp;quot; type=&amp;quot;manifest/m2ts&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;source src=&amp;quot;http://example.com/video-plain.webm&amp;quot; type=&amp;quot;video/webm&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;http://example.com/video-plain.webm&amp;quot;&amp;gt;Download the video&amp;lt;/a&amp;gt;&lt;br /&gt;
 &amp;lt;/video&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here&#039;s another example for loading the manifest; through the *enclosure* element in an RSS feed:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;rss version=&amp;quot;2.0&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;channel&amp;gt;&lt;br /&gt;
   &amp;lt;title&amp;gt;Example feed&amp;lt;/title&amp;gt;&lt;br /&gt;
   &amp;lt;link&amp;gt;http://example.com/&amp;lt;/link&amp;gt;&lt;br /&gt;
   &amp;lt;description&amp;gt;Example feed with a single adaptive stream.&amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;item&amp;gt;&lt;br /&gt;
     &amp;lt;title&amp;gt;Example stream&amp;lt;/title&amp;gt;&lt;br /&gt;
     &amp;lt;enclosure length=&amp;quot;1487&amp;quot; type=&amp;quot;manifest/webm&amp;quot;&lt;br /&gt;
       url=&amp;quot;http://example.com/video.m3u8&amp;quot; /&amp;gt;&lt;br /&gt;
   &amp;lt;/item&amp;gt;&lt;br /&gt;
 &amp;lt;/channel&amp;gt;&lt;br /&gt;
 &amp;lt;/rss&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Like the manifest parsing, the switching heuristics are upon the user-agent. They can be somewhat of a *secret sauce*. As a basic example, a user-agent can select a quality level if:&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;bitrate&#039;&#039; of the level is &amp;lt; 90% of the server » client &#039;&#039;downloadRate&#039;&#039;.&lt;br /&gt;
* The &#039;&#039;videoWidth&#039;&#039; of the level is &amp;lt; 120% of the video element &#039;&#039;width&#039;&#039;.&lt;br /&gt;
* The delta in &#039;&#039;droppedFrames&#039;&#039; is &amp;lt; 25%  of the delta in &#039;&#039;decodedFrames&#039;&#039; for this level.&lt;br /&gt;
&lt;br /&gt;
Since droppedFrames are only known after a level has started playing, it is generally only a reason for switching down. Based upon the growth rate of droppedFrames, a user-agent might choose to blacklist the quality level for a certain amount of time, or discard it altogether for this playback session.&lt;br /&gt;
&lt;br /&gt;
The quality level selection occurs at the start of every chunk URL fetch. Given an array of levels, the user-agent starts with the highest quality level first and then walks down the list. If the lowest-quality level does not match the criteria, the user-agent still uses it (else there would be no video).&lt;br /&gt;
&lt;br /&gt;
A user-agent typically tries to maintain X (3, 10, 20) seconds of video ready for decoding (buffered). If less than X seconds is available, the user-agent runs it quality level selection and requests another chunk.&lt;br /&gt;
&lt;br /&gt;
There is a tie-in between the length of a chunk, the bufferLenght and the speed with which a user-agent adapts to changing conditions. For example, should the bandwidth drop dramatically, 1 or 2 high-quality chunks will still be played from buffer before the first lower-quality chunk is shown. The other way around is also true: should a user go fullscreen, it will take some time until the stream switches to high quality. Lower bufferLenghts increase responsiveness but also increase the possiblity of buffer underruns.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Scripting ==&lt;br /&gt;
&lt;br /&gt;
Certain user-agents might not offer access to adaptive streaming heuristics. Other user-agents might, or should even do so. The obvious case is a webbrowser supporting the &amp;lt;video&amp;gt; element and a javascript engine:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== QOS Metrics ===&lt;br /&gt;
&lt;br /&gt;
The video element should provides accessors for retrieving quality of service metrics:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;downloadRate&#039;&#039;&#039;: The current server-client bandwidth (read-only).&lt;br /&gt;
* &#039;&#039;&#039;videoBitrate&#039;&#039;&#039;: The current video bitrate (read-only).&lt;br /&gt;
* &#039;&#039;&#039;droppedFrames&#039;&#039;&#039;: The total number of frames dropped for this playback session (read-only).&lt;br /&gt;
* &#039;&#039;&#039;decodedFrames&#039;&#039;&#039;: The total number of frames decoded for this playback session (read-only).&lt;br /&gt;
* &#039;&#039;&#039;height&#039;&#039;&#039;: The current height of the video element (already exists).&lt;br /&gt;
* &#039;&#039;&#039;videoHeight&#039;&#039;&#039;: The current height of the videofile (already exists).&lt;br /&gt;
* &#039;&#039;&#039;width&#039;&#039;&#039;: The current width of the video element (already exists).&lt;br /&gt;
* &#039;&#039;&#039;videoWidth&#039;&#039;&#039;: The current width of the videofile (already exists).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Native adaptive streaming ===&lt;br /&gt;
&lt;br /&gt;
In case a user-agent has manifest parsing / level switching heuristics built-in, the video element can provides access to the stream levels:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;currentLevel&#039;&#039;&#039;: The currently playing stream level.&lt;br /&gt;
* &#039;&#039;&#039;levels&#039;&#039;&#039;: An array of all stream levels (as parsed from the manifests). Example:&lt;br /&gt;
&lt;br /&gt;
 [{&lt;br /&gt;
   bitrate: 100000, &lt;br /&gt;
   codecs: &#039;vp8,vorbis&#039;,&lt;br /&gt;
   duration: 132,&lt;br /&gt;
   height: 180,&lt;br /&gt;
   url: manifest_100.m3u8,&lt;br /&gt;
   width: 240&lt;br /&gt;
 },{&lt;br /&gt;
   bitrate: 500000,&lt;br /&gt;
   codecs: &#039;vp8,vorbis&#039;,&lt;br /&gt;
   duration: 132,&lt;br /&gt;
   height: 360,&lt;br /&gt;
   url: manifest_500.m3u8,&lt;br /&gt;
   width: 640&lt;br /&gt;
 }]&lt;br /&gt;
&lt;br /&gt;
In addition to this, the video element provides an event to notify scripts of changes in the current stream level:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;levelChange&#039;&#039;&#039;: the currentLevel attribute has just been updated.&lt;br /&gt;
&lt;br /&gt;
Last, the video element provides functionality to override the user agent&#039;s built-in heuristics:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;setLevel(level)&#039;&#039;&#039;: This method forces the user to switch to another stream level. Invoking this method disables a user-agent&#039;s adaptive streaming heuristics. Use *setLevel(-1)* to enable heuristics again.&lt;br /&gt;
* &#039;&#039;&#039;bufferLength&#039;&#039;&#039;: This attribute controls how much videodata (in seconds) a user-agent should strive to keep buffered.&lt;br /&gt;
&lt;br /&gt;
An important example for &#039;&#039;&#039;bufferLength&#039;&#039;&#039;: a website owner might set this to a very high value to enable viewers on a low bandwidth to wait for buffering and still see a high-quality video.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== API adaptive streaming ===&lt;br /&gt;
&lt;br /&gt;
In case a user-agent does not have manifest parsing and level switching heuristics built-in, the video element can still accomodate adaptive streaming through a small stream API:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;appendVideo(url,[range])&#039;&#039;&#039;: fetch the URL and append the video to the currently playing video.&lt;br /&gt;
&lt;br /&gt;
This single call allows developers to build adaptive HTTP streaming inside the javascripting layer. Manifest parsing and stream level APIs are not needed. The quality of service metrics are still needed though:&lt;br /&gt;
&lt;br /&gt;
* When the video plays fine, chunks fro the same quality level are constantly appended.&lt;br /&gt;
* When a switch to a different quality level is made,  chunks from a different quality level are appended.&lt;br /&gt;
* When the user seeks to a different position in the video, it&#039;s &#039;&#039;&#039;src&#039;&#039;&#039; is simply set to the appropriate chunk at that position.&lt;br /&gt;
&lt;br /&gt;
This call implies that properties such as &#039;&#039;duration&#039;&#039;, &#039;&#039;videoHeight&#039;&#039; and &#039;&#039;videoWidth&#039;&#039; may change during a playback session.&lt;br /&gt;
&lt;br /&gt;
A number of rules have to be set up as to how the concatenation will actually work. For example:&lt;br /&gt;
&lt;br /&gt;
* In order to allow user-agents to use a single decoding pipeline, the current video and the one that&#039;s appended  should contain the same container format and A/V codecs.&lt;br /&gt;
* Video is appended on a frame-by-frame basis (no bytedata).&lt;br /&gt;
* [Audio is appended by slightly extending the data and applying a crossfade?]&lt;br /&gt;
&lt;br /&gt;
The optional &#039;&#039;range&#039;&#039; parameter instructs the user-agent to only request a certain byterange.&lt;br /&gt;
&lt;br /&gt;
== Rationale ==&lt;br /&gt;
&lt;br /&gt;
Finally, some rationale for the choices made in this proposal. Why chunks and a manifest? Why not, for example, range-requests and &amp;lt;source&amp;gt; tags?&lt;br /&gt;
&lt;br /&gt;
First and foremost, we need a format that works not only in HTML5 browsers, but also in, for example, mobile apps (Android/Blackberry/iOS), desktop players (Miro/Quicktime/VLC) and big screen devices (Roku, Boxee, PS3). Especially for the very small screens (3G network) and large screens (full HD), adaptive streaming is incredibly valuable. Tayloring a solution too much towards the HTML5 syntax and browser environment will hinder broad adoption of an open video standard. Adaptive streaming and HTML5 should work nice together, but adaptive streaming should not be relying on HTML5.&lt;br /&gt;
&lt;br /&gt;
That said:&lt;br /&gt;
&lt;br /&gt;
* Providing the low-tech scenario of storing chunks as separate files on the webserver enables adaptive streaming in cases where either the server, the user-agent (apps / players / settops) or the network (firewalls, cellulars) does not support something like range-requests. As an example, implementing adaptive streaming using range-requests in Adobe Flash (e.g. as temporary fallback) would not be possible, since the range-request header is blocked.&lt;br /&gt;
* Ecosystem partners (CDNs, encoding providers, landmark publishers, etc) are already getting used to ánd building tools around the concept of *chunked* video streams. Examples are log aggregators that roll up chunks servings into a single logline, or encoders that simultaneously build multiple stream levels, chunk them up and render their manifests.&lt;br /&gt;
* With just the QOS metrics (*downloadRate* and *decodedFrames*) in place, it will be possible to build adaptive-streaming-like solutions (using range-requests) in javascript. In Flash, this same functionality is supported (and very popular) within both Flowplayer and JW Player. True adaptive streaming (continous switching without buffering) won&#039;t be possible, but the experience is good enough to suit people that don&#039;t have the encoder or browser (yet) to build or playback adaptive streams.&lt;/div&gt;</summary>
		<author><name>JeroenW</name></author>
	</entry>
	<entry>
		<id>https://wiki.whatwg.org/index.php?title=Adaptive_Streaming&amp;diff=5535</id>
		<title>Adaptive Streaming</title>
		<link rel="alternate" type="text/html" href="https://wiki.whatwg.org/index.php?title=Adaptive_Streaming&amp;diff=5535"/>
		<updated>2010-10-26T10:29:59Z</updated>

		<summary type="html">&lt;p&gt;JeroenW: /* Adaptive Video Streaming */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here is a (rough and incomplete) proposal for doing adaptive streaming using open video formats. Key components of the proposal:&lt;br /&gt;
&lt;br /&gt;
* Videos are served as separate, small chunks.&lt;br /&gt;
* Accompanying manifest files provide metadata.&lt;br /&gt;
* The user-agent parses manifests and switches between stream levels.&lt;br /&gt;
* An API provides QOS metrics and enables custom switching logic.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Introduction ==&lt;br /&gt;
&lt;br /&gt;
Today, most video on the internet is delivered as progressive download (e.g. Youtube). While this works fine in most cases, there are limitations as it comes to more &#039;&#039;advanced&#039;&#039; uses of video:&lt;br /&gt;
&lt;br /&gt;
* Long-form video (long downloads, waste of bandwidth if user doesn&#039;t watch)&lt;br /&gt;
* Live/DVR video (hard to do as progressive download, unstable)&lt;br /&gt;
* Delivery to mobile devices (lots of buffering due to changing network conditions)&lt;br /&gt;
&lt;br /&gt;
Adaptive streaming aims to solve these issues by:&lt;br /&gt;
&lt;br /&gt;
* Offering multiple versions of a video, at different bitrates / quality levels (e.g. from 100kbps to 2 mbps).&lt;br /&gt;
* Transporting the video not as one big file, but as separate, distinct chunks (e.g. by cutting up the video in small files, or by using range-requests).&lt;br /&gt;
* Allowing user-agents to seamlessly switch between quality levels (e.g. based upon changing device or network conditions), simply by downloading the &#039;&#039;next&#039;&#039; chunk from a different level.&lt;br /&gt;
&lt;br /&gt;
There&#039;s currently three widely used implementations of adaptive HTTP streaming:&lt;br /&gt;
&lt;br /&gt;
* [http://learn.iis.net/page.aspx/627/smooth-streaming/ Microsoft Smooth Streaming], used by Silverlight.&lt;br /&gt;
* [http://www.adobe.com/products/httpdynamicstreaming/ Adobe HTTP Dynamic Streaming], used by Flash.&lt;br /&gt;
* [http://devworld.apple.com/resources/http-streaming/ Apple HTTP Live Streaming], used by Quicktime X.&lt;br /&gt;
&lt;br /&gt;
There&#039;s of course still the dedicated streaming protocols (e.g. RTSP over UDP). Adaptive HTTP streaming does not aim to replace those, as there are various cases that are much better served with a &#039;&#039;real&#039;&#039; streaming approach. However, adaptive HTTP streaming could become the approach for the majority of online video delivery, for many of the same reasons that made progressive HTTP so popular:&lt;br /&gt;
&lt;br /&gt;
* It is easy to understand and implement.&lt;br /&gt;
* It builds upon existing HTTP infrastructure.&lt;br /&gt;
* It centralizes all intelligence (and control) in the client.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Chunks ==&lt;br /&gt;
&lt;br /&gt;
Every chunk should be a valid video file (header, videotrack, audiotrack). Every chunk should also contain at least 1 keyframe (at the start). This implies every single chunk can be played back by itself.&lt;br /&gt;
&lt;br /&gt;
Beyond validity, the amount of metadata should be kept as small as possible (single-digit kbps overhead).&lt;br /&gt;
&lt;br /&gt;
Codec parameters that can vary between the different quality levels of an adaptive stream are:&lt;br /&gt;
&lt;br /&gt;
* The datarate, dimensions (pixel+display) and framerate of the video track.&lt;br /&gt;
* The datarate, number of channels and sample frequency of the audio track.&lt;br /&gt;
&lt;br /&gt;
In order for quality level switches to occur without artifacts, the start positions of all chunks should align between the various quality levels. If this isn&#039;t the case, user-agents will display artifacts (ticks, skips, black) when a quality level switch occurs. Syncing should not be a requirement though. This will allow legacy content to be used for dynamic streaming with little effort (e.g. remuxing or using a smart server) and little issues (in practive, most keyframes are aligned between different transcodes of a video).&lt;br /&gt;
&lt;br /&gt;
In its most low-tech form, chunks can be stored as separate files-on-disc on a webserver. This poses issues around transcoding (no ecosystem yet) and file management (not everybody loves 100s of files). There are at least two solutions:&lt;br /&gt;
&lt;br /&gt;
1. A serverside module accepts chunk requests, pulls the correct GOP(s) from a video and wraps the necessary metadata.&lt;br /&gt;
2. Clients can accept and process video without headers and use HTTP range-requests to directly get the video data.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Manifests ==&lt;br /&gt;
&lt;br /&gt;
The M3U8 manifest format [http://tools.ietf.org/html/draft-pantos-http-live-streaming-04 that Apple specified] is adopted. Generally, both an overall manifest (linking to the various quality levels) and a quality level manifest (linking to the various stream levels) are used. (Though, especially for live streaming, a single quality level may be used).&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of such an overall manifest. It specifies three quality levels, each with its own datarate, codecs and dimensions:&lt;br /&gt;
&lt;br /&gt;
 #EXTM3U &lt;br /&gt;
 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000,CODECS=&amp;quot;vp8,vorbis&amp;quot;,RESOLUTION=240x135&lt;br /&gt;
 http://example.com/low.m3u8 &lt;br /&gt;
 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000,CODECS=&amp;quot;vp8,vorbis&amp;quot;,RESOLUTION=640x360&lt;br /&gt;
 http://example.com/mid.m3u8 &lt;br /&gt;
 #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000,CODECS=&amp;quot;vp8,vorbis&amp;quot;,RESOLUTION=1280x720&lt;br /&gt;
 http://example.com/hi.m3u8&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example manifest for one such quality level. It contains a full URL listing of all chunks for this quality level:&lt;br /&gt;
&lt;br /&gt;
 #EXTM3U&lt;br /&gt;
 #EXT-X-MEDIA-SEQUENCE:0&lt;br /&gt;
 #EXT-X-TARGETDURATION:10&lt;br /&gt;
 #EXTINF:10,&lt;br /&gt;
 http://media.example.com/segment1.webm&lt;br /&gt;
 #EXTINF:10,&lt;br /&gt;
 http://media.example.com/segment2.webm&lt;br /&gt;
 #EXTINF:10,&lt;br /&gt;
 http://media.example.com/segment3.webm&lt;br /&gt;
 #EXT-X-ENDLIST&lt;br /&gt;
&lt;br /&gt;
The video framerate, audio sample frequency and number of audio channels cannot be listed here according to the specs. In formats like WebM, Ogg and MPEG-TS (the container Apple specifies), this can be retrieved during demuxing.&lt;br /&gt;
&lt;br /&gt;
The #EXT-X-ENDLIST tag defines the end of a video. If this tag is present, the manifest is supposed to be fixed and the client will not re-load it during playback. If this tag is not present (generally only during live streams), the client should periodically re-fetch the manifest to get additional chunks.&lt;br /&gt;
&lt;br /&gt;
The M3U8 playlist format also provides a mechanism for stream interruptions (#EXT-X-DISCONTINUITY) and for encryption (#EXT-X-KEY). Moreover, regular ID3 tags can be used to enrich the manifest with metadata.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== User-agents ==&lt;br /&gt;
&lt;br /&gt;
The root manifest serves as the single, unique reference point for a adaptive stream. Therefore, user agents in theory need solely its URL to playback the stream. Here&#039;s an example for loading a root manifest: through the *src* attribute of the &amp;lt;video&amp;gt; tag in an HTML page:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;video width=&amp;quot;480&amp;quot; height=&amp;quot;270&amp;quot; src=&amp;quot;http://example.com/video.m3u8&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;http://example.com/video_low.webm&amp;quot;&amp;gt;Download the video&amp;lt;/a&amp;gt;&lt;br /&gt;
 &amp;lt;/video&amp;gt;&lt;br /&gt;
&lt;br /&gt;
In this variation, the manifest is loaded through the &amp;lt;source&amp;gt; tag, to provide fallback logic:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;video width=&amp;quot;480&amp;quot; height=&amp;quot;270&amp;quot; &amp;gt;&lt;br /&gt;
   &amp;lt;source src=&amp;quot;http://example.com/video-webm.m3u8&amp;quot; type=&amp;quot;manifest/webm&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;source src=&amp;quot;http://example.com/video-apple.m3u8&amp;quot; type=&amp;quot;manifest/m2ts&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;source src=&amp;quot;http://example.com/video-plain.webm&amp;quot; type=&amp;quot;video/webm&amp;quot;&amp;gt;&lt;br /&gt;
   &amp;lt;a href=&amp;quot;http://example.com/video-plain.webm&amp;quot;&amp;gt;Download the video&amp;lt;/a&amp;gt;&lt;br /&gt;
 &amp;lt;/video&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here&#039;s another example for loading the manifest; through the *enclosure* element in an RSS feed:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;rss version=&amp;quot;2.0&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;channel&amp;gt;&lt;br /&gt;
   &amp;lt;title&amp;gt;Example feed&amp;lt;/title&amp;gt;&lt;br /&gt;
   &amp;lt;link&amp;gt;http://example.com/&amp;lt;/link&amp;gt;&lt;br /&gt;
   &amp;lt;description&amp;gt;Example feed with a single adaptive stream.&amp;lt;/description&amp;gt;&lt;br /&gt;
   &amp;lt;item&amp;gt;&lt;br /&gt;
     &amp;lt;title&amp;gt;Example stream&amp;lt;/title&amp;gt;&lt;br /&gt;
     &amp;lt;enclosure length=&amp;quot;1487&amp;quot; type=&amp;quot;manifest/webm&amp;quot;&lt;br /&gt;
       url=&amp;quot;http://example.com/video.m3u8&amp;quot; /&amp;gt;&lt;br /&gt;
   &amp;lt;/item&amp;gt;&lt;br /&gt;
 &amp;lt;/channel&amp;gt;&lt;br /&gt;
 &amp;lt;/rss&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Like the manifest parsing, the switching heuristics are upon the user-agent. They can be somewhat of a *secret sauce*. As a basic example, a user-agent can select a quality level if:&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;bitrate&#039;&#039; of the level is &amp;lt; 90% of the server » client &#039;&#039;downloadRate&#039;&#039;.&lt;br /&gt;
* The &#039;&#039;videoWidth&#039;&#039; of the level is &amp;lt; 120% of the video element &#039;&#039;width&#039;&#039;.&lt;br /&gt;
* The delta in &#039;&#039;droppedFrames&#039;&#039; is &amp;lt; 25%  of the delta in &#039;&#039;decodedFrames&#039;&#039; for this level.&lt;br /&gt;
&lt;br /&gt;
Since droppedFrames are only known after a level has started playing, it is generally only a reason for switching down. Based upon the growth rate of droppedFrames, a user-agent might choose to blacklist the quality level for a certain amount of time, or discard it altogether for this playback session.&lt;br /&gt;
&lt;br /&gt;
The quality level selection occurs at the start of every chunk URL fetch. Given an array of levels, the user-agent starts with the highest quality level first and then walks down the list. If the lowest-quality level does not match the criteria, the user-agent still uses it (else there would be no video).&lt;br /&gt;
&lt;br /&gt;
A user-agent typically tries to maintain X (3, 10, 20) seconds of video ready for decoding (buffered). If less than X seconds is available, the user-agent runs it quality level selection and requests another chunk.&lt;br /&gt;
&lt;br /&gt;
There is a tie-in between the length of a chunk, the bufferLenght and the speed with which a user-agent adapts to changing conditions. For example, should the bandwidth drop dramatically, 1 or 2 high-quality chunks will still be played from buffer before the first lower-quality chunk is shown. The other way around is also true: should a user go fullscreen, it will take some time until the stream switches to high quality. Lower bufferLenghts increase responsiveness but also increase the possiblity of buffer underruns.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Scripting ==&lt;br /&gt;
&lt;br /&gt;
Certain user-agents might not offer access to adaptive streaming heuristics. Other user-agents might, or should even do so. The obvious case is a webbrowser supporting the &amp;lt;video&amp;gt; element and a javascript engine:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== QOS Metrics ===&lt;br /&gt;
&lt;br /&gt;
The video element should provides accessors for retrieving quality of service metrics:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;downloadRate&#039;&#039;&#039;: The current server-client bandwidth (read-only).&lt;br /&gt;
* &#039;&#039;&#039;videoBitrate&#039;&#039;&#039;: The current video bitrate (read-only).&lt;br /&gt;
* &#039;&#039;&#039;droppedFrames&#039;&#039;&#039;: The total number of frames dropped for this playback session (read-only).&lt;br /&gt;
* &#039;&#039;&#039;decodedFrames&#039;&#039;&#039;: The total number of frames decoded for this playback session (read-only).&lt;br /&gt;
* &#039;&#039;&#039;height&#039;&#039;&#039;: The current height of the video element (already exists).&lt;br /&gt;
* &#039;&#039;&#039;videoHeight&#039;&#039;&#039;: The current height of the videofile (already exists).&lt;br /&gt;
* &#039;&#039;&#039;width&#039;&#039;&#039;: The current width of the video element (already exists).&lt;br /&gt;
* &#039;&#039;&#039;videoWidth&#039;&#039;&#039;: The current width of the videofile (already exists).&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Native adaptive streaming ===&lt;br /&gt;
&lt;br /&gt;
In case a user-agent has manifest parsing / level switching heuristics built-in, the video element can provides access to the stream levels:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;currentLevel&#039;&#039;&#039;: The currently playing stream level.&lt;br /&gt;
* &#039;&#039;&#039;levels&#039;&#039;&#039;: An array of all stream levels (as parsed from the manifests). Example:&lt;br /&gt;
&lt;br /&gt;
 [{&lt;br /&gt;
   bitrate: 100000, &lt;br /&gt;
   codecs: &#039;vp8,vorbis&#039;,&lt;br /&gt;
   duration: 132,&lt;br /&gt;
   height: 180,&lt;br /&gt;
   url: manifest_100.m3u8,&lt;br /&gt;
   width: 240&lt;br /&gt;
 },{&lt;br /&gt;
   bitrate: 500000,&lt;br /&gt;
   codecs: &#039;vp8,vorbis&#039;,&lt;br /&gt;
   duration: 132,&lt;br /&gt;
   height: 360,&lt;br /&gt;
   url: manifest_500.m3u8,&lt;br /&gt;
   width: 640&lt;br /&gt;
 }]&lt;br /&gt;
&lt;br /&gt;
In addition to this, the video element provides an event to notify scripts of changes in the current stream level:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;levelChange&#039;&#039;&#039;: the currentLevel attribute has just been updated.&lt;br /&gt;
&lt;br /&gt;
Last, the video element provides functionality to override the user agent&#039;s built-in heuristics:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;setLevel(level)&#039;&#039;&#039;: This method forces the user to switch to another stream level. Invoking this method disables a user-agent&#039;s adaptive streaming heuristics. Use *setLevel(-1)* to enable heuristics again.&lt;br /&gt;
* &#039;&#039;&#039;bufferLength&#039;&#039;&#039;: This attribute controls how much videodata (in seconds) a user-agent should strive to keep buffered.&lt;br /&gt;
&lt;br /&gt;
An important example for &#039;&#039;&#039;bufferLength&#039;&#039;&#039;: a website owner might set this to a very high value to enable viewers on a low bandwidth to wait for buffering and still see a high-quality video.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== API adaptive streaming ===&lt;br /&gt;
&lt;br /&gt;
In case a user-agent does not have manifest parsing and level switching heuristics built-in, the video element can still accomodate adaptive streaming through a small stream API:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;appendVideo(url,[range])&#039;&#039;&#039;: fetch the URL and append the video to the currently playing video.&lt;br /&gt;
&lt;br /&gt;
This single call allows developers to build adaptive HTTP streaming inside the javascripting layer. Manifest parsing and stream level APIs are not needed. The quality of service metrics are still needed though.&lt;br /&gt;
&lt;br /&gt;
This call implies that properties such as &#039;&#039;duration&#039;&#039;, &#039;&#039;videoHeight&#039;&#039; and &#039;&#039;videoWidth&#039;&#039; may change during a playback session.&lt;br /&gt;
&lt;br /&gt;
A number of rules have to be set up as to how the concatenation will actually work. For example:&lt;br /&gt;
&lt;br /&gt;
* In order to allow user-agents to use a single decoding pipeline, the current video and the one that&#039;s appended  should contain the same container format and A/V codecs.&lt;br /&gt;
* Video is appended on a frame-by-frame basis (no bytedata).&lt;br /&gt;
* [Audio is appended by slightly extending the data and applying a crossfade?]&lt;br /&gt;
&lt;br /&gt;
The optional &#039;&#039;range&#039;&#039; parameter instructs the user-agent to only request a certain byterange.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Rationale ==&lt;br /&gt;
&lt;br /&gt;
Finally, some rationale for the choices made in this proposal. Why chunks and a manifest? Why not, for example, range-requests and &amp;lt;source&amp;gt; tags?&lt;br /&gt;
&lt;br /&gt;
First and foremost, we need a format that works not only in HTML5 browsers, but also in, for example, mobile apps (Android/Blackberry/iOS), desktop players (Miro/Quicktime/VLC) and big screen devices (Roku, Boxee, PS3). Especially for the very small screens (3G network) and large screens (full HD), adaptive streaming is incredibly valuable. Tayloring a solution too much towards the HTML5 syntax and browser environment will hinder broad adoption of an open video standard. Adaptive streaming and HTML5 should work nice together, but adaptive streaming should not be relying on HTML5.&lt;br /&gt;
&lt;br /&gt;
That said:&lt;br /&gt;
&lt;br /&gt;
* Providing the low-tech scenario of storing chunks as separate files on the webserver enables adaptive streaming in cases where either the server, the user-agent (apps / players / settops) or the network (firewalls, cellulars) does not support something like range-requests. As an example, implementing adaptive streaming using range-requests in Adobe Flash (e.g. as temporary fallback) would not be possible, since the range-request header is blocked.&lt;br /&gt;
* Ecosystem partners (CDNs, encoding providers, landmark publishers, etc) are already getting used to ánd building tools around the concept of *chunked* video streams. Examples are log aggregators that roll up chunks servings into a single logline, or encoders that simultaneously build multiple stream levels, chunk them up and render their manifests.&lt;br /&gt;
* With just the QOS metrics (*downloadRate* and *decodedFrames*) in place, it will be possible to build adaptive-streaming-like solutions (using range-requests) in javascript. In Flash, this same functionality is supported (and very popular) within both Flowplayer and JW Player. True adaptive streaming (continous switching without buffering) won&#039;t be possible, but the experience is good enough to suit people that don&#039;t have the encoder or browser (yet) to build or playback adaptive streams.&lt;/div&gt;</summary>
		<author><name>JeroenW</name></author>
	</entry>
	<entry>
		<id>https://wiki.whatwg.org/index.php?title=Adaptive_Streaming&amp;diff=5525</id>
		<title>Adaptive Streaming</title>
		<link rel="alternate" type="text/html" href="https://wiki.whatwg.org/index.php?title=Adaptive_Streaming&amp;diff=5525"/>
		<updated>2010-10-20T10:09:24Z</updated>

		<summary type="html">&lt;p&gt;JeroenW: Created page with &amp;#039;= Adaptive Video Streaming =  Here is a (rough and incomplete) proposal for doing adaptive streaming using open video formats. WebM is used as an example, but all points should a...&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= Adaptive Video Streaming =&lt;br /&gt;
&lt;br /&gt;
Here is a (rough and incomplete) proposal for doing adaptive streaming using open video formats. WebM is used as an example, but all points should apply to Ogg as well. Key components of the proposal:&lt;br /&gt;
&lt;br /&gt;
* Videos are served as separate, small chunks.&lt;br /&gt;
* Accompanying manifest files provide metadata.&lt;br /&gt;
* The user-agent parses manifests and switches between stream levels.&lt;br /&gt;
* An API provides QOS metrics and enables custom switching logic.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Chunks ==&lt;br /&gt;
&lt;br /&gt;
Every chunk should be a valid video file (header, videotrack, audiotrack). Every chunk should also contain at least 1 keyframe (at the start). This implies every single chunk can be played back by itself.&lt;br /&gt;
&lt;br /&gt;
Beyond validity, the amount of metadata should be kept as small as possible (single-digit kbps overhead).&lt;br /&gt;
&lt;br /&gt;
Codec parameters that can vary between the different quality levels of an adaptive stream are:&lt;br /&gt;
&lt;br /&gt;
* The datarate, dimensions (pixel+display) and framerate of the video track.&lt;br /&gt;
* The datarate, number of channels and sample frequency of the audio track.&lt;br /&gt;
&lt;br /&gt;
In order for quality level switches to occur without artifacts, the start positions of all chunks should align between the various quality levels. If this isn&#039;t the case, user-agents will display artifacts (ticks, skips, black) when a quality level switch occurs. Syncing should not be a requirement though. This will allow legacy content to be used for dynamic streaming with little effort (e.g. remuxing or using a smart server) and little issues (in practive, most keyframes are aligned between different transcodes of a video).&lt;br /&gt;
&lt;br /&gt;
In its most low-tech form, chunks can be stored as separate files-on-disc on a webserver. This poses issues around transcoding (no ecosystem yet) and file management (not everybody loves 100s of files). A small serverside module can easily fix these issues:&lt;br /&gt;
&lt;br /&gt;
* User-agent requests from chunks are translated to byte-range requests inside a full video.&lt;br /&gt;
* The data is pulled from the video.&lt;br /&gt;
* The data is wrapped into a valid WebM file.&lt;br /&gt;
* (The resulting chunk is cached locally.)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Manifests ==&lt;br /&gt;
&lt;br /&gt;
The [http://tools.ietf.org/html/draft-pantos-http-live-streaming-04 M3U8 manifest format] that Apple specified is adopted. Generally, both an overall manifest (linking to the various quality levels) and a quality level manifest (linking to the various stream levels) are used. (Though, especially for live streaming, a single quality level may be used).&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example of such an overall manifest. It specifies three quality levels, each with its own datarate, codecs and dimensions:&lt;br /&gt;
&lt;br /&gt;
  #EXTM3U &lt;br /&gt;
  #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=1280000,CODECS=&amp;quot;vp8,vorbis&amp;quot;,RESOLUTION=240x135&lt;br /&gt;
  http://example.com/low.m3u8 &lt;br /&gt;
  #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2560000,CODECS=&amp;quot;vp8,vorbis&amp;quot;,RESOLUTION=640x360&lt;br /&gt;
  http://example.com/mid.m3u8 &lt;br /&gt;
  #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=7680000,CODECS=&amp;quot;vp8,vorbis&amp;quot;,RESOLUTION=1280x720&lt;br /&gt;
  http://example.com/hi.m3u8&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example manifest for one such quality level. It contains a full URL listing of all chunks for this quality level:&lt;br /&gt;
&lt;br /&gt;
  #EXTM3U&lt;br /&gt;
  #EXT-X-MEDIA-SEQUENCE:0&lt;br /&gt;
  #EXT-X-TARGETDURATION:10&lt;br /&gt;
  #EXTINF:10,&lt;br /&gt;
  http://media.example.com/segment1.webm&lt;br /&gt;
  #EXTINF:10,&lt;br /&gt;
  http://media.example.com/segment2.webm&lt;br /&gt;
  #EXTINF:10,&lt;br /&gt;
  http://media.example.com/segment3.webm&lt;br /&gt;
  #EXT-X-ENDLIST&lt;br /&gt;
&lt;br /&gt;
The video framerate, audio sample frequency and number of audio channels cannot be listed here according to the specs. Both in WebM and in MPEG-TS (the container Apple specifies), this can be retrieved during demuxing.&lt;br /&gt;
&lt;br /&gt;
The M3U8 playlist format can be used to provide &#039;&#039;sliding windows&#039;&#039; (for livestreaming) using the #EXT-X-MEDIA-SEQUENCE and #EXT-X-ENDLIST attributes. It can also be used for providing encryption (something we&#039;ll ignore). Moreover, regular ID3 tags can be used to enrich the manifest with metadata.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== User-agents ==&lt;br /&gt;
&lt;br /&gt;
The root manifest serves as the single, unique reference point for a adaptive stream. Therefore, user agents need solely its URL to playback the stream.&lt;br /&gt;
&lt;br /&gt;
Here&#039;s an example for loading a root manifest: through the *src* attribute of the &amp;lt;video&amp;gt; tag in an HTML page:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;video width=&amp;quot;480&amp;quot; height=&amp;quot;270&amp;quot; src=&amp;quot;http://example.com/video.m3u8&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;http://example.com/video_low.webm&amp;quot;&amp;gt;Download the video&amp;lt;/a&amp;gt;&lt;br /&gt;
  &amp;lt;/video&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In this variation, the manifest is loaded through the &amp;lt;source&amp;gt; tag, to provide fallback logic:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;video width=&amp;quot;480&amp;quot; height=&amp;quot;270&amp;quot; &amp;gt;&lt;br /&gt;
    &amp;lt;source src=&amp;quot;http://example.com/video.m3u8&amp;quot; type=&amp;quot;video/m3u8&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;source src=&amp;quot;http://example.com/video_low.webm&amp;quot; type=&amp;quot;video/webm&amp;quot;&amp;gt;&lt;br /&gt;
    &amp;lt;a href=&amp;quot;http://example.com/video_low.webm&amp;quot;&amp;gt;Download the video&amp;lt;/a&amp;gt;&lt;br /&gt;
  &amp;lt;/video&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here&#039;s another example for loading the manifest; through the *enclosure* element in an RSS feed:&lt;br /&gt;
&lt;br /&gt;
  &amp;lt;rss version=&amp;quot;2.0&amp;quot;&amp;gt;&lt;br /&gt;
  &amp;lt;channel&amp;gt;&lt;br /&gt;
    &amp;lt;title&amp;gt;Example feed&amp;lt;/title&amp;gt;&lt;br /&gt;
    &amp;lt;link&amp;gt;http://example.com/&amp;lt;/link&amp;gt;&lt;br /&gt;
    &amp;lt;description&amp;gt;Example feed with a single adaptive stream.&amp;lt;/description&amp;gt;&lt;br /&gt;
    &amp;lt;item&amp;gt;&lt;br /&gt;
      &amp;lt;title&amp;gt;Example stream&amp;lt;/title&amp;gt;&lt;br /&gt;
      &amp;lt;enclosure length=&amp;quot;1487&amp;quot; type=&amp;quot;video/m3u8&amp;quot;&lt;br /&gt;
        url=&amp;quot;http://example.com/video.m3u8&amp;quot; /&amp;gt;&lt;br /&gt;
    &amp;lt;/item&amp;gt;&lt;br /&gt;
  &amp;lt;/channel&amp;gt;&lt;br /&gt;
  &amp;lt;/rss&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Like the manifest parsing, the switching heuristics are upon the user-agent. They can be somewhat of a *secret sauce*. As a basic example, a user-agent can select a quality level if:&lt;br /&gt;
&lt;br /&gt;
* The &#039;&#039;bitrate&#039;&#039; of the level is &amp;lt; 90% of the server » client &#039;&#039;downloadRate&#039;&#039;.&lt;br /&gt;
* The &#039;&#039;videoWidth&#039;&#039; of the level is &amp;lt; 120% of the video element &#039;&#039;width&#039;&#039;.&lt;br /&gt;
* The delta in &#039;&#039;droppedFrames&#039;&#039; is &amp;lt; 25%  of the delta in &#039;&#039;decodedFrames&#039;&#039; for this level.&lt;br /&gt;
&lt;br /&gt;
Since droppedFrames are only known after a level has started playing, it is generally only a reason for switching down. Based upon the growth rate of droppedFrames, a user-agent might choose to blacklist the quality level for a certain amount of time, or discard it altogether for this playback session.&lt;br /&gt;
&lt;br /&gt;
The quality level selection occurs at the start of every chunk URL fetch. Given an array of levels, the user-agent starts with the highest quality level first and then walks down the list. If the lowest-quality level does not match the criteria, the user-agent still uses it (else there would be no video).&lt;br /&gt;
&lt;br /&gt;
A user-agent typically tries to maintain X (3, 10, 20) seconds of video ready for decoding (buffered). If less than X seconds is available, the user-agent runs it quality level selection and requests another chunk.&lt;br /&gt;
&lt;br /&gt;
There is a tie-in between the length of a chunk, the bufferLenght and the speed with which a user-agent adapts to changing conditions. For example, should the bandwidth drop dramatically, 1 or 2 high-quality chunks will still be played from buffer before the first lower-quality chunk is shown. The other way around is also true: should a user go fullscreen, it will take some time until the stream switches to high quality. Lower bufferLenghts increase responsiveness but also increase the possiblity of buffer underruns.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Scripting API ==&lt;br /&gt;
&lt;br /&gt;
Certain user-agents might not offer access to adaptive streaming heuristics. Other user-agents might, or should even do so. The obvious case is a webbrowser supporting the &amp;lt;video&amp;gt; element and a javascript engine:&lt;br /&gt;
&lt;br /&gt;
The video element provides accessors for retrieving quality of service metrics:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;downloadRate&#039;&#039;: The current server-client bandwidth (read-only).&lt;br /&gt;
* &#039;&#039;decodeRate&#039;&#039;: The current level&#039;s bitrate (read-only).&lt;br /&gt;
* &#039;&#039;droppedFrames&#039;&#039;: The total number of frames dropped for this playback session (read-only).&lt;br /&gt;
* &#039;&#039;decodedFrames&#039;&#039;: The total number of frames decoded for this playback session (read-only).&lt;br /&gt;
* &#039;&#039;height&#039;&#039;: The current height of the video element (already exists).&lt;br /&gt;
* &#039;&#039;videoHeight&#039;&#039;: The current height of the videofile (already exists).&lt;br /&gt;
* &#039;&#039;width&#039;&#039;: The current width of the video element (already exists).&lt;br /&gt;
* &#039;&#039;videoWidth&#039;&#039;: The current width of the videofile (already exists).&lt;br /&gt;
&lt;br /&gt;
In addition to this, the video element provides access to the stream levels:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;currentLevel&#039;&#039;: The currently playing stream level.&lt;br /&gt;
* &#039;&#039;levels&#039;&#039;: An array of all stream levels (as parsed from the manifests). Example:&lt;br /&gt;
&lt;br /&gt;
  [{&lt;br /&gt;
    bitrate: 100000, &lt;br /&gt;
    codecs: &#039;vp8,vorbis&#039;,&lt;br /&gt;
    duration: 132,&lt;br /&gt;
    height: 180,&lt;br /&gt;
    url: manifest_100.m3u8,&lt;br /&gt;
    width: 240&lt;br /&gt;
  },{&lt;br /&gt;
    bitrate: 500000,&lt;br /&gt;
    codecs: &#039;vp8,vorbis&#039;,&lt;br /&gt;
    duration: 132,&lt;br /&gt;
    height: 360,&lt;br /&gt;
    url: manifest_500.m3u8,&lt;br /&gt;
    width: 640&lt;br /&gt;
  }]&lt;br /&gt;
&lt;br /&gt;
In addition to this, the video element provides an event to notify scripts of changes in the current stream level:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;levelChange&#039;&#039;: the currentLevel attribute has just been updated.&lt;br /&gt;
&lt;br /&gt;
Last, the video element provides functionality to override the user agent&#039;s built-in heuristics:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;setLevel(level)&#039;&#039;: This method forces the user to switch to another stream level. Invoking this method disables a user-agent&#039;s adaptive streaming heuristics. Use &#039;&#039;setLevel(-1)&#039;&#039; to enable heuristics again.&lt;br /&gt;
* &#039;&#039;bufferLength&#039;&#039;: This attribute controls how much videodata (in seconds) a user-agent should strive to keep buffered.&lt;br /&gt;
&lt;br /&gt;
An important example for &#039;&#039;bufferLenght&#039;&#039;: a website owner might set this to a very high value to enable viewers on a low bandwidth to wait for buffering and still see a high-quality video.&lt;br /&gt;
&lt;br /&gt;
== Rationale ==&lt;br /&gt;
&lt;br /&gt;
Finally, some rationale for the choices made in this proposal. Why chunks and a manifest? Why not, for example, range-requests and &amp;lt;source&amp;gt; tags?&lt;br /&gt;
&lt;br /&gt;
First and foremost, we need a format that works not only in HTML5 browsers, but also in, for example, mobile apps (Android/Blackberry/iOS), desktop players (Miro/Quicktime/VLC) and big screen devices (Roku, Boxee, PS3). Especially for the very small screens (3G network) and large screens (full HD), adaptive streaming is incredibly valuable. Tayloring a solution too much towards the HTML5 syntax and browser environment will hinder broad adoption of an open video standard. Adaptive streaming and HTML5 should work nice together, but adaptive streaming should not be relying on HTML5.&lt;br /&gt;
&lt;br /&gt;
That said:&lt;br /&gt;
&lt;br /&gt;
* Providing the low-tech scenario of storing chunks as separate files on the webserver enables adaptive streaming in cases where either the server, the user-agent (apps / players / settops) or the network (firewalls, cellulars) does not support something like range-requests. As an example, implementing adaptive streaming using range-requests in Adobe Flash (e.g. as temporary fallback) would not be possible, since the range-request header is blocked.&lt;br /&gt;
* Ecosystem partners (CDNs, encoding providers, landmark publishers, etc) are already getting used to ánd building tools around the concept of *chunked* video streams. Examples are log aggregators that roll up chunks servings into a single logline, or encoders that simultaneously build multiple stream levels, chunk them up and render their manifests.&lt;br /&gt;
* With just the QOS metrics (*downloadRate* and *decodedFrames*) in place, it will be possible to build adaptive-streaming-like solutions (using range-requests) in javascript. In Flash, this same functionality is supported (and very popular) within both Flowplayer and JW Player. True adaptive streaming (continous switching without buffering) won&#039;t be possible, but the experience is good enough to suit people that don&#039;t have the encoder or browser (yet) to build or playback adaptive streams.&lt;/div&gt;</summary>
		<author><name>JeroenW</name></author>
	</entry>
</feed>