Playing Video

Seamlessly switching between web apps and streaming video

The Senza platform has two modes:

  1. It can use a web browser in the cloud to run HTML5 apps with rich content, including video.
  2. It can stream the video directly, without the need to consume the resources required for a web browser. 

If your web app plays a video fullscreen, Senza can seamlessly switch between these two modes. This gives you the power to use web technologies whenever you want to, and the efficiency of streaming directly to the client when you don't need them.

This app is the Reference Implementation for integrating the client library.

Banner

For this demo, we'll add a "Welcome to Senza" banner that displays on top of the video. 

  1. When we want to show the banner, we'll switch to foreground mode to see the browser.
  2. When we want to hide the banner, we'll switch to background mode and stream the video.

Code

We can start with some HTML in index.html :

<!DOCTYPE html>
<html>
<head>
  <title>Welcome to Senza!</title>
  <link rel="stylesheet" href="styles.css">
</head>
<body>
  <div id="main">
    <video id="video" width="1920" height="1080" muted="muted"></video>
    <div id="banner">
      Welcome to Senza
    </div>
  </div>
</body>
<script type="text/javascript" src="./dist/bundle.js"></script>
</html>

And a little bit of CSS in styles.css to make our banner look pretty:

@font-face {
  font-family: Montserrat;
  src: url(https://fonts.gstatic.com/s/montserrat/v26/JTUSjIg1_i6t8kCHKm459WlhyyTh89Y.woff2);
}

body {
  width: 1920px;
  height: 1080px;
	margin: 0px;
	background-color: black;
  overflow: hidden;
}
  
#main {
  position: relative;
  width: 1920px;
  height: 1080px;
	background-color: white;
  text-align: center;
}

#banner {
  position: absolute;
  width: 1800px;
  height: 175px;
  top: 800px;
  left: 60px;
  color: white;
  padding-top: 45px;
  font: 80pt Montserrat;
  font-weight: 500;
  background-color: black;
  background-image: url("images/gradient.jpg");
  filter: drop-shadow(0px 10px 15px black);
  border-radius: 20px;
  z-index: 2;
  opacity: 0.9;
}

Then create a index.js file for your script.

Webpack

We're going to use webpack to transpile all your scripts, including the client library, into one bundle.
First, make sure you have installed Node.js and the Client Library.

Create a package.json file like this:

{
  "name": "banner",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "webpack": "^5.72.1",
    "webpack-cli": "^4.9.2"
  },
  "dependencies": {
    "senza-sdk": "^4.2.6",
  }
}

When you import the senza-sdk package, it will also install the Shaka player as a dependency. That will let you use our subclass of the Skaka player to play video both in your app and on the cloud connector.

And a webpack.config.js file like this:

const path = require("path");
 
module.exports = {
    entry: ["./index.js"],
    mode: "development",
    output: {
        path: path.resolve(__dirname, "dist"),
        filename: "bundle.js"
    }
};

Run the following commands once to download the required node modules. This will create a node_modules folder and a package-lock.json file.

npm install
npm ci

Now each time you make changes to the banner.js file, run the webpack command to update the bundle.js file in the dist folder:

npx webpack -w --config webpack.config.js

The -wflag tells the command to stay running, and it will continuously watch your code for changes. That way you don't have to run the command each time you modify your code.

You'll want to load the page using your local web server. See Viewing Your App for details, as well as instructions on how to turn on your local web server.

When you load the page you'll see the banner on top of the video.

Shaka Player subclass

We're going to use a subclass of the Shaka Player to help us play video on Senza. It works just like the ordinary Shaka Player, except it also manages the Remote Player for you so you can stream video directly to the cloud connector. See the Reference Integration page for more details.

Playing video with Senza

Now for the fun part! We're going to use the Senza client library to configure the player so that it can play our favorite bunny video. Let's add some code to the index.js.

First, import the things we'll need from the Senza library, as well as the Shaka player. Also define a constant with the URL for our video resource.

import { init, uiReady, ShakaPlayer, lifecycle } from "senza-sdk";

const TEST_VIDEO = "https://dash.akamaized.net/akamai/bbb_30fps/bbb_30fps.mpd";

let player;

When the page loads, we will:

  • Call the init() function from the client library.
  • Create an instance of the Senza Shaka Player attach it to the media element.
  • Load the video by calling the player's load() method with the URL.
  • Play the video by calling play() on the media element.
  • Call the uiReady() function when the user interface is ready.

You'll notice that several of these functions run asynchronously, so we call them using the await keyword.

window.addEventListener("load", async () => {
  try {
    await init();
    player = new ShakaPlayer(video);
    await player.load(TEST_VIDEO);
    await video.play();
    uiReady();
  } catch (error) {
    console.error(error);
  }
});

Remote Control input

We can handle button presses on the Remote Control by listening for keydown events.

document.addEventListener("keydown", async function (event) {
  switch (event.key) {
    case "Enter": await toggleBackground(); break;
    case "Escape": await playPause(); break;
    case "ArrowLeft": skip(-30); break;
    case "ArrowRight": skip(30); break;
    default: return;
  }
  event.preventDefault();
});

The remote control buttons will do the following:

  • The OK button (enter key) will toggle between foreground and background modes. When the app is in the foreground the video plays in the local player, and when it is in the background the video plays in the remote player.
  • The back button (escape key) will pause or play the video.
  • The left and right arrow keys will skip backwards and forwards by 30 seconds.

Here are a few helper functions that we'll use to toggle back and forth between different states:

async function toggleBackground() {
  if (lifecycle.state == lifecycle.UiState.BACKGROUND) {
    await lifecycle.moveToForeground();
  } else {
    await lifecycle.moveToBackground();
  }
}

async function playPause() {
  if (video.paused) {
    await video.play();
  } else {
    await video.pause();
  }
}

function skip(seconds) {
  video.currentTime = video.currentTime + seconds;
}

That's really about it for the implementation of the app! Most of the details are handled by the Senza Shaka Player. See the Reference Integration page for more details on the implementation.

Try it out

Try viewing your app in the device simulator or on a cloud connector device to see how it works! When you load the page you'll see the video start playing. Try pressing OK to toggle between foreground and background modes, back to pause or play the video, left to skip backwards, and right to skip forwards.

Conclusion

That's it! You've learned in this demo how easy it can be to play video in the local player using the web browser, to stream the video directly to the device using the local player, and to switch back and forth.


What’s Next