Skip to main content

How to run JIT with Accurate Player SDK

This is a step-by-step tutorial that covers how to build a JIT frontend application using the Accurate Player SDK.

info

The source code for this tutorial is available for download in the Accurate Player SDK Examples repository

Prerequisites

First, you need the Node.js JavaScript runtime installed. If you don't have it installed already, go to How to install Node.js and follow the instructions.

Verify that you have a recent version of node installed, we recommend that you use the latest LTS version of node. Type this to get the node version printed in your terminal:

node -v

The installation of node also includes npm, a package manager for Node.js. We will use npm to install the packages required to run the JIT frontend application.

To install Accurate Player's SDK packages, you will need a username and password to Codemill's npm repository. Your sales representative can provide you with these. Once you have these, login to Codemill's npm repository by running this command in your terminal:

npm login --auth-type=legacy --registry=https://codemill.jfrog.io/codemill/api/npm/accurate-video/ --scope=@accurate-player

This will make npm use the Codemill npm repository for all packages whose name starts with @accurate-player. After a successful command, your access token will be stored in your user config. The user config location can be found by running:

npm config get userconfig

Finally, this tutorial requires a JIT backend service running on localhost.

Building the application

Basic Player

We will use Vite, a frontend build tool, to create the frontend application.

To scaffold your project run:

npm create vite@latest

You will be prompted some information about the project:

Need to install the following packages:
create-vite@5.2.3
Ok to proceed? (y) y
✔ Project name: … jit-frontend
✔ Select a framework: › Vanilla
✔ Select a variant: › TypeScript

Scaffolding project in jit/tutorials/quick-start/jit-frontend...

Done. Now run:

cd jit-frontend
npm install
npm run start

Follow the instructions to get the development server up and running.

Next, you need a license key for Accurate Player JIT. If you don't have one, talk to your sales representative. In the jit-frontend directory, create a file called license-key.js:

license-key.js
window.LICENSE_KEY = "<YOUR LICENSE KEY>";

Next, include your license key in the application:

...
<head>
...
<script src="/license-key.js"></script>
...
</head>

Now we need to install the AP SDK libraries we will use in this tutorial. In the jit-frontend project run:

npm install -d @accurate-player/accurate-player-core
npm install -d @accurate-player/accurate-player-jit
npm install -d @accurate-player/accurate-player-plugins
npm install -d @accurate-player/accurate-player-controls

Next, delete everything already in src/main.ts, then add imports and declare the player:

main.ts
import './style.css'
import {JITPlayer} from "@accurate-player/accurate-player-jit";
import {
Player,
PlayerEventType,
} from "@accurate-player/accurate-player-core";

let player: Player;

Next, in src/main.ts, let's add a button, video, and a status container to the page:

main.ts
const applicationContainer = document.querySelector<HTMLDivElement>('#app')!;
applicationContainer.innerHTML = `
<button id="loadbutton">Load video</button>
<div id="status">Idle</div>
<div class="video-container" >
<video id="videomaster" autoplay></video>
</div>
`;

The autoplay attribute on the <video> element is important here as we want the WebRTC stream to start as soon as we start receiving it.

Locate the button and add an event listener for click:

main.ts
const loadButton: HTMLButtonElement = document.querySelector("#loadbutton")!;
loadButton.addEventListener("click", () => {
initPlayer();
loadVideo();
});

There needs to be user activation on the page before the browser allows us to start watching the WebRTC video stream (because of autoplay).

We already added the calls to initPlayer and loadVideo. Let's look at those functions next.

main.ts
function initPlayer() {
const videoMaster: HTMLVideoElement = document.querySelector("#videomaster")!;
const statusDiv: HTMLDivElement = document.querySelector("#status")!;
player = new JITPlayer(videoMaster, window.LICENSE_KEY, {
jitBackend: "http://localhost:8080",
iceServers: [{
urls: [
"stun:stun.l.google.com:19302",
"stun:stun1.l.google.com:19302",
"stun:stun2.l.google.com:19302",
"stun:stun3.l.google.com:19302",
"stun:stun4.l.google.com:19302",
]
}],
});
player.on(PlayerEventType.Loading, () => {
statusDiv.innerText = "Loading (this may take a while)...";
});
player.on(PlayerEventType.Loaded, () => {
statusDiv.innerText = "Loaded";
player.api.play();
});
}

When we create the JITPlayer we need to provide:

  • the video element that we added earler
  • the license key that you got from your sales rep

and settings that specify:

We also added some event listeners to get callbacks when the player is loading (PlayerEventType.Loading) and is finished loading (PlayerEventType.Loaded) to update the status text on the page.

Next we load a video file:

main.ts
function loadVideo() {
player.api.loadVideoFile({
src: "https://accurate-player-static.s3.eu-central-1.amazonaws.com/Sintel/sintel-2048-timecode-6ch.mp4",
frameRate: {
numerator: 24,
denominator: 1
}
});
}

And now we have a functioning player!

JIT Parameters

When loading a file with JIT, we can append a number of parameters. Read more about JitVideoFile and JitParameters in the docs. Below are a few common examples.

src can be a URL as above. It can also be a local file path, accessible on the host machine running the backend. That would look something like this instead:

...
src: "file:///media/video.mp4",
...

Another example would be to scale down 4k to HD to be able to stream without lagging/buffering. Scaling down the example file by half would look something like this:

import { JITVideoFile } from "@accurate-player/accurate-player-jit";

function loadVideo() {
let jitVideoFile: JITVideoFile = {
src: "https://s3.eu-central-1.amazonaws.com/accurate-player-demo-assets/timecode/sintel-2048-timecode-stereo.mp4",
}
jitVideoFile.frameRate = {
numerator: 24,
denominator: 1,
};

jitVideoFile.jit = {};
jitVideoFile.jit.resolution = {
width: 2048 / 2,
height: 872 / 2
};
jitVideoFile.jit.lowres = 1;

player.api.loadVideoFile(jitVideoFile);
}

Accurate Player Controls

To make it a little more usable, we want to add Accurate Player Controls. Start with importing the package:

import "@accurate-player/accurate-player-controls";

Then alter the html like this:

applicationContainer.innerHTML = `
<button id="loadbutton">Load video</button>
<div id="status">Idle</div>
<div class="video-container" >
<video id="videomaster" autoplay></video>
<apc-controls class="apc-video"></apc-controls>
</div>

And init the controls in initPlayer:

  const apControls = document.querySelector("apc-controls") as any;
apControls.init(videoMaster, player);

And, to restrict apc-controls to the video container, add this to style.css:

.video-container {
position: relative;
}

And now you have video controls, so that you can play, pause, search, change playback speed, etc!

Accurate Player Hotkeys

To activate keyboard hotkeys, import the plugin:

import { HotkeyPlugin } from "@accurate-player/accurate-player-plugins";

and initialize it in the initPlayer function:

  new HotkeyPlugin(player);

Quality slider

Default, JIT sets the streaming quality automatically. To be able to set it manually, we want a slider. Add this to the html element:

    <input type="range" id="quality-input-el" class="quality-input" min="1" max="100" value="50" disabled>
<div>
<label for="override-quality-el">Override quality manually</label>
<input type="checkbox" id="override-quality-el" class="override-quality">
</div>

Now we have a slider and a checkbox to toggle to setting the quality manually. Let's create references to them:

const overrideQualityCheckbox = document.getElementById("override-quality-el") as HTMLAudioElement;
const qualityInput = document.getElementById("quality-input-el") as HTMLAudioElement;

And, in initPlayer, add some event listeners to update both quality and related elements, for the automatic and the manual case:

  overrideQualityCheckbox.checked = false;
overrideQualityCheckbox.addEventListener('change', function() {
qualityInput.disabled = !overrideQualityCheckbox.checked;
updateManualQuality();
});
qualityInput.addEventListener('change', function() {
updateManualQuality();
});
player.on(PlayerEventType.StatusChanged, () => {
if (!overrideQualityCheckbox.checked) {
qualityInput.value = player.api.reportedQuality;
}
});

And, finally, create the handler that actually sets the quality:

function updateManualQuality()
{
let value = Math.round(qualityInput.value as number);

if (overrideQualityCheckbox.checked && value && value >= 1 && value <= 100)
{
player?.api.setQuality(value);
}
else
{
player?.api.setQuality(null);
}
}

Result

That's it. You can inspect the final file jit-frontend/src/main.ts

This is the bare minimum to get you started. You can add extra functionality to your player / application by loading more Plugins or by following any of our other tutorials in the Accurate Player SDK Examples repository.