Skip to content

Commit

Permalink
Partial tutorial for offline. Issue #60.
Browse files Browse the repository at this point in the history
Change-Id: If8388520b9dcbe8fb8ff95abe378a4e104f98e05
  • Loading branch information
natalieharris authored and joeyparrish committed May 22, 2015
1 parent eeaafe9 commit a953d7e
Show file tree
Hide file tree
Showing 2 changed files with 286 additions and 0 deletions.
183 changes: 183 additions & 0 deletions tutorials/offline.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
<!--
Copyright 2015 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<h3 class="tutorial-heading">
Offline Playback
</h3>

<p>
Shaka Player supports offline playback since v1.3.0. Offline streams are handled
by {@link shaka.player.OfflineVideoSource}. The offline API works similarily to
the other video source APIs, but adds the functionality to store a group,
retrieve a list of all stored groups and to delete a group from storage.
</p>

<p>
A group refers to one video stream and one audio stream, if present, from
a DASH MPD. Storage of text content is not yet supported. Each group will
have a unique ID, which should be persisted by the application for later
playback.
</p>

<h3 class="tutorial-heading">
Storing Content
</h3>

<p>
If you have not familiarized yourself with the the Player, please start
with {@tutorial player}. In order to store content you need to install the
polyfills and initialize the player, but do not need to load the video source.
</p>

<p>
Here is a simple page which demonstrates basic offline storage:
</p>

<pre class="prettyprint source"><code id="sample7">&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset="utf-8"&gt;
&lt;title&gt;TurtleTube - Offline&lt;/title&gt;
&lt;!-- Load the Shaka Player library. --&gt;
&lt;script src="shaka-player.compiled.js"&gt;&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;video id="video"
width="640" height="480"
crossorigin="anonymous"
controls&gt;
Your browser does not support HTML5 video.
&lt;/video&gt;
&lt;/body&gt;
&lt;script&gt;
function initPlayer() {
// Install polyfills.
shaka.polyfill.installAll();

// Find the video element.
var video = document.getElementById('video');

// Attach the player to the window so that it can be easily debugged.
window.player = new shaka.player.Player(video);

// Listen for errors from the Player.
player.addEventListener('error', function(event) {
console.error(event);
});
}

function chooseTracks(videoSource) {
var ids = [];

var videoTracks = videoSource.getVideoTracks();
if (videoTracks.length) {
videoTracks.sort(shaka.player.VideoTrack.compare);
// Choosing the smallest track.
var track = videoTracks[0];
ids.push(track.id);
}

var audioTracks = videoSource.getAudioTracks();
if (audioTracks.length) {
// The video source gives you the preferred language first.
// Remove any tracks from other languages first.
var lang = audioTracks[0].lang;
audioTracks = audioTracks.filter(function(track) {
return track.lang == lang;
});
// From what's left, choose the middle stream. If we have high, medium,
// and low quality audio, this is medium. If we only have high and low,
// this is high.
var index = Math.floor(audioTracks.length / 2);
ids.push(audioTracks[index].id);
}

// Return IDs of chosen tracks.
return Promise.resolve(ids);
}

function storeContent() {
if (!window.player) {
initPlayer();
}

// Construct an OfflineVideoSource.
var estimator = new shaka.util.EWMABandwidthEstimator();
var offlineSource = new shaka.player.OfflineVideoSource(
null, // groupId, not used when storing content.
estimator);

// Listen for progress events from the OfflineVideoSource.
offlineSource.addEventListener('progress', function(event) {
// Percentage complete is the detail field of the event.
console.log(
'Content storage is ' + event.detail.toFixed(2) + '% complete.');
});

// Store content from MPD url.
var mpdUrl = 'http://turtle-tube.appspot.com/t/t2/dash.mpd';
var preferredLanguage = 'en-US';
offlineSource.store(
mpdUrl,
preferredLanguage,
null, // interpretContentProtection, not needed for clear content.
chooseTracks.bind(null, offlineSource)
).then(
function(groupId) {
window.groupId = groupId;
console.log('Stored content under group ID ' + window.groupId);
}
).catch(
function(e) {
console.error(e);
});
}

document.addEventListener('DOMContentLoaded', storeContent);
&lt;/script&gt;
&lt;/html&gt;
</code></pre>

<h3 class="tutorial-heading">
Playing Stored Content
</h3>

<p>
TODO
</p>

<h3 class="tutorial-heading">
Deleting Stored Content
</h3>

<p>
TODO
</p>

<h3 class="tutorial-heading">
Offline Caveats
</h3>

<p>
{@link shaka.player.OfflineVideoSource} can only store encrypted streams on
platforms that support persistent licenses.
</p>

<p>
Offline playback relies on the {@link http://goo.gl/TFHaXL Indexed Database
API} for storage of content. Indexed Database is currently supported by most
web browsers.
</p>
103 changes: 103 additions & 0 deletions tutorials/sample7.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>TurtleTube - Offline</title>
<!-- Load the Shaka Player library. -->
<script src="shaka-player.compiled.js"></script>
</head>
<body>
<video id="video"
width="640" height="480"
crossorigin="anonymous"
controls>
Your browser does not support HTML5 video.
</video>
</body>
<script>
function initPlayer() {
// Install polyfills.
shaka.polyfill.installAll();

// Find the video element.
var video = document.getElementById('video');

// Attach the player to the window so that it can be easily debugged.
window.player = new shaka.player.Player(video);

// Listen for errors from the Player.
player.addEventListener('error', function(event) {
console.error(event);
});
}

function chooseTracks(videoSource) {
var ids = [];

var videoTracks = videoSource.getVideoTracks();
if (videoTracks.length) {
videoTracks.sort(shaka.player.VideoTrack.compare);
// Choosing the smallest track.
var track = videoTracks[0];
ids.push(track.id);
}

var audioTracks = videoSource.getAudioTracks();
if (audioTracks.length) {
// The video source gives you the preferred language first.
// Remove any tracks from other languages first.
var lang = audioTracks[0].lang;
audioTracks = audioTracks.filter(function(track) {
return track.lang == lang;
});
// From what's left, choose the middle stream. If we have high, medium,
// and low quality audio, this is medium. If we only have high and low,
// this is high.
var index = Math.floor(audioTracks.length / 2);
ids.push(audioTracks[index].id);
}

// Return IDs of chosen tracks.
return Promise.resolve(ids);
}

function storeContent() {
if (!window.player) {
initPlayer();
}

// Construct an OfflineVideoSource.
var estimator = new shaka.util.EWMABandwidthEstimator();
var offlineSource = new shaka.player.OfflineVideoSource(
null, // groupId, not used when storing content.
estimator);

// Listen for progress events from the OfflineVideoSource.
offlineSource.addEventListener('progress', function(event) {
// Percentage complete is the detail field of the event.
console.log(
'Content storage is ' + event.detail.toFixed(2) + '% complete.');
});

// Store content from MPD url.
var mpdUrl = 'http://turtle-tube.appspot.com/t/t2/dash.mpd';
var preferredLanguage = 'en-US';
offlineSource.store(
mpdUrl,
preferredLanguage,
null, // interpretContentProtection, not needed for clear content.
chooseTracks.bind(null, offlineSource)
).then(
function(groupId) {
window.groupId = groupId;
console.log('Stored content under group ID ' + window.groupId);
}
).catch(
function(e) {
console.error(e);
});
}

document.addEventListener('DOMContentLoaded', storeContent);
</script>
</html>

0 comments on commit a953d7e

Please sign in to comment.