diff --git a/lib/player/offline_video_source.js b/lib/player/offline_video_source.js index be12394a96..1dedcfe5a1 100644 --- a/lib/player/offline_video_source.js +++ b/lib/player/offline_video_source.js @@ -406,6 +406,7 @@ shaka.player.OfflineVideoSource.prototype.reconstructManifestInfo_ = /** * Deletes a group of streams from storage. * @return {!Promise} + * @export */ shaka.player.OfflineVideoSource.prototype.deleteGroup = function() { shaka.asserts.assert(this.groupId_ >= 0); diff --git a/tutorials/offline.html b/tutorials/offline.html index 0944a78d81..26bc33fbb1 100644 --- a/tutorials/offline.html +++ b/tutorials/offline.html @@ -79,6 +79,14 @@

}); } + function initialize() { + if (!window.player) + initPlayer(); + + if (!window.estimator) + window.estimator = new shaka.util.EWMABandwidthEstimator(); + } + function chooseTracks(videoSource) { var ids = []; @@ -110,15 +118,10 @@

} 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); + window.estimator); // Listen for progress events from the OfflineVideoSource. offlineSource.addEventListener('progress', function(event) { @@ -130,7 +133,7 @@

// Store content from MPD url. var mpdUrl = 'http://turtle-tube.appspot.com/t/t2/dash.mpd'; var preferredLanguage = 'en-US'; - offlineSource.store( + return offlineSource.store( mpdUrl, preferredLanguage, null, // interpretContentProtection, not needed for clear content. @@ -138,15 +141,20 @@

).then( function(groupId) { window.groupId = groupId; - console.log('Stored content under group ID ' + window.groupId); + console.log('Stored content under group ID ' + groupId); } - ).catch( + ); + } + + function test() { + initialize(); + storeContent().catch( function(e) { console.error(e); }); } - document.addEventListener('DOMContentLoaded', storeContent); + document.addEventListener('DOMContentLoaded', test); </script> </html> @@ -156,17 +164,280 @@

-TODO +In order to playback content, you need the group ID of the stored content. The +group ID will be used to create a new {@link shaka.player.OfflineVideoSource} +to be loaded into the {@link shaka.player.Player}.

+
<!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 initialize() {
+      if (!window.player)
+        initPlayer();
+
+      if (!window.estimator)
+        window.estimator = new shaka.util.EWMABandwidthEstimator();
+    }
+
+    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() {
+      // Construct an OfflineVideoSource.
+      var offlineSource = new shaka.player.OfflineVideoSource(
+          null, // groupId, not used when storing content.
+          window.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';
+      return 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 ' + groupId);
+          }
+      );
+    }
+
+    function playOfflineContent() {
+      // Construct an OfflineVideoSource and load with player.
+      var offlineSource =
+          new shaka.player.OfflineVideoSource(window.groupId, window.estimator);
+      return window.player.load(offlineSource).then(
+          function() {
+            window.player.play();
+            console.log('Offline content with group ID ' + window.groupId +
+                  ' ready for playback.');
+          });
+    }
+
+    function test() {
+      initialize();
+      storeContent().then(playOfflineContent).catch(
+          function(e) {
+            console.error(e);
+          });
+    }
+
+    document.addEventListener('DOMContentLoaded', test);
+  </script>
+</html>
+
+

Deleting Stored Content

-TODO +Similar to playing stored content, you will create a new {@link +shaka.player.OfflineVideoSource} with a known group ID to delete content.

+
<!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 initialize() {
+      if (!window.player)
+        initPlayer();
+
+      if (!window.estimator)
+        window.estimator = new shaka.util.EWMABandwidthEstimator();
+    }
+
+    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() {
+      // Construct an OfflineVideoSource.
+      var offlineSource = new shaka.player.OfflineVideoSource(
+          null, // groupId, not used when storing content.
+          window.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';
+      return 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 ' + groupId);
+          }
+      );
+    }
+
+    function playOfflineContent() {
+      // Construct an OfflineVideoSource and load with player.
+      var offlineSource =
+          new shaka.player.OfflineVideoSource(window.groupId, window.estimator);
+      return window.player.load(offlineSource).then(
+          function() {
+            window.player.play();
+            console.log('Offline content with group ID ' + window.groupId +
+                  ' ready for playback.');
+          });
+    }
+
+    function deleteOfflineContent() {
+      var offlineSource =
+          new shaka.player.OfflineVideoSource(window.groupId, window.estimator);
+      return offlineSource.deleteGroup().then(
+          function() {
+            console.log('Offline content with group ID ' + window.groupId +
+                        ' successfully deleted.');
+          });
+    }
+
+    function test() {
+      initialize();
+      storeContent().then(deleteOfflineContent).catch(
+          function(e) {
+            console.error(e);
+          });
+    }
+
+    document.addEventListener('DOMContentLoaded', test);
+  </script>
+</html>
+
+

Offline Caveats

diff --git a/tutorials/sample7.txt b/tutorials/sample7.txt index fbe0b343a2..7f41554297 100644 --- a/tutorials/sample7.txt +++ b/tutorials/sample7.txt @@ -31,6 +31,14 @@ }); } + function initialize() { + if (!window.player) + initPlayer(); + + if (!window.estimator) + window.estimator = new shaka.util.EWMABandwidthEstimator(); + } + function chooseTracks(videoSource) { var ids = []; @@ -62,15 +70,10 @@ } 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); + window.estimator); // Listen for progress events from the OfflineVideoSource. offlineSource.addEventListener('progress', function(event) { @@ -82,7 +85,7 @@ // Store content from MPD url. var mpdUrl = 'http://turtle-tube.appspot.com/t/t2/dash.mpd'; var preferredLanguage = 'en-US'; - offlineSource.store( + return offlineSource.store( mpdUrl, preferredLanguage, null, // interpretContentProtection, not needed for clear content. @@ -90,14 +93,19 @@ ).then( function(groupId) { window.groupId = groupId; - console.log('Stored content under group ID ' + window.groupId); + console.log('Stored content under group ID ' + groupId); } - ).catch( + ); + } + + function test() { + initialize(); + storeContent().catch( function(e) { console.error(e); }); } - document.addEventListener('DOMContentLoaded', storeContent); + document.addEventListener('DOMContentLoaded', test); diff --git a/tutorials/sample8.txt b/tutorials/sample8.txt new file mode 100644 index 0000000000..6c733daa5b --- /dev/null +++ b/tutorials/sample8.txt @@ -0,0 +1,123 @@ + + + + + TurtleTube - Offline + + + + + + + + diff --git a/tutorials/sample9.txt b/tutorials/sample9.txt new file mode 100644 index 0000000000..fa295fba5a --- /dev/null +++ b/tutorials/sample9.txt @@ -0,0 +1,133 @@ + + + + + TurtleTube - Offline + + + + + + + +