Skip to content
On this page

Hướng dẫn sử dụng Shaka Player

1. Giới thiệu

Phần này sẽ cung cấp thông tin để tích hợp hệ thống SigmaMultiDRM vào trình phát shaka player:

::: Thông tin

Trong đó, MERCHANT_ID và APP_ID có thể được lấy từ hệ thống Dashboard như hình dưới đây.

get_customer_info :::

2. Yêu cầu

::: Thông tin yêu cầu

  • Trình duyệt hỗ trợ Html5:
Trình duyệtWidevinePlayReadyFairPlayHỗ trợ mã hóa license
Chrome (Window, MacOS, Android, ChromeOS, Linux)YesNoNoYes
Firefox (Window, MacOS, Linux)YesNoNoYes
Microsoft Edge (Window, MacOS, Android)YesYesNoNo
Safari (Safari 8+ on MacOS, Safari on iOS 11.2+)NoNoYesNo
iOS Browser (Chrome, Cốc Cốc, Microsoft Edge, Firefox, Opera)NoNoYesNo
Opera (Window, MacOS)YesNoNoYes
Internet Explorer (Window 8.1+)NoYesYesNo
  • Smart TVs:
Smart TVsWidevinePlayReadyFairPlayHỗ trợ mã hóa license
SamSung Tizen (2016-2017, 2018+ Models)YesYesNoNo
SamSung Tizen&Orsay (2010-2015 Models)NoYesNoNo
LG (WebOS 3.0+)YesYesNoNo
LG (WebOS 1.2 & Netcast)NoYesNoNo
Smart TV Alliance (LG, Philips, Toshiba, Panasonic)YesYesNoNo
Android TVYesYesNoNo

:::

3. Tích hợp Sigma MultiDRM vào Shaka Player

3.1. Sử dụng tính năng mã hóa license sử dụng Sigma Packer SDK

Để sử dụng tính năng mã hóa giấy phép, bạn cần cài đặt Sigma Packer SDK vào trong ứng dụng

Cài đặt SDK

  • Địa chỉ: sigma_packer.js

  • Thêm mã nguồn:

    html
    <script src="sigma_packer.js"></script>
    <script src="shaka-player.compiled.js"></script>

Chú ý: Việc cài đặt theo từng bước dưới đây

3.2 Init application

  • Mặc định
javascript
var player;
document.addEventListener('DOMContentLoaded', function () {
  shaka.polyfill.installAll();
  var video = document.getElementById('VIDEO_ID'); // media element
  player = new this.shaka.Player(video);
});
  • Tính năng mã hóa license: Bạn cần chạy shaka polyfill sau khi SigmaPacker được khởi tạo:
javascript
var player;
document.addEventListener('DOMContentLoaded', function () {
  var video = document.getElementById('VIDEO_ID'); // media element
  player = new this.shaka.Player(video);

  window.sigmaPacker = new SigmaPacker();
  window.sigmaPacker.onload = () => {
    console.log('SigmaPacker loaded');
    shaka.polyfill.installAll();
  };
  window.sigmaPacker.init();
});

Note: Nếu bạn đang sử dụng ReactJS, hãy đặt đoạn mã này vào tệp src/App.js ngay sau import các tiện ích được sử dụng để khởi tạo SigmaPacker.

javascript
// src/App.js
import ... from "...";
import ... from "...";

window.sigmaPacker = new SigmaPacker();
window.sigmaPacker.onload = () => {
  console.log('SigmaPacker loaded');
  shaka.polyfill.installAll();
};
window.sigmaPacker.init();
// do something

3.3 Cấu hình trình phát video sử dụng địa chỉ máy chủ của hệ thống Sigma MultiDRM

javascript
const manifestUri = MANIFEST_URI;
const licenseWidevineServer = LICENSE_WIDEVINE_URL;
const licensePlayReadyServer = LICENSE_PLAYREADY_URL;
const licenseFairPlayServer = LICENSE_FAIRPLAY_URL;

player.configure({
  drm: {
    servers: {
      'com.widevine.alpha': licenseWidevineServer,
      'com.microsoft.playready': licensePlayReadyServer,
      'com.apple.fps.1_0': licenseFairPlayServer,
    },
  },
});
// Try to load a manifest.
try {
  await player.load(manifestUri);
  // The video should now be playing!
} catch (e) {
  console.error(e);
}
TrườngKiểuMô tả
licenseWidevineServerStringXem mục 1
licensePlayReadyServerStringXem mục 1
licenseFairPlayServerStringXem mục 1
manifestUriStringURL của nội dung muốn xem

3.4 Thông tin cấu hình header của yêu cầu

Thông tin cấu hình:

PropsTypeDescription
CERTIFICATE_URIStringXem mục 1
MERCHANT_IDStringĐịnh danh khách hàng
APP_IDStringĐịnh danh ứng dụng
USER_IDStringĐịnh danh người dùng trên hệ thống của khách hàng
SESSION_IDStringMã xác thực của người dùng được cấp bởi hệ thống của khách hàng

3.4.1 Cấu hình header cho FairPlay

javascript
var licenseURL; // Biến lưu thông tin địa chỉ request license
// Đầu tiên cần cấu hình certificate
const serverCertificateURI = CERTIFICATE_URI; // xem mục 1
const response = await fetch(serverCertificateURI);
if (!response.ok) {
  console.error('Could not get certificate!');
  return;
}
const certificate = await response.arrayBuffer();
player.configure({
  drm: {
    advanced: {
      'com.apple.fps.1_0': {
        serverCertificate: new Uint8Array(certificate),
      },
    },
  },
});
// Chỉnh sửa thông tin nội dung (assetId) và lưu thông tin licenseURL
player.configure('drm.initDataTransform', (initData, type, drmInfo) => {
  if (type != 'skd') return initData;
  const skdURL = shaka.util.StringUtils.fromBytesAutoDetect(initData);
  const contentId = new URL(skdURL).searchParams.get('assetId');
  const cert = player.drmInfo().serverCertificate;
  licenseURL = skdURL.replace('skd://', 'https://');
  return shaka.util.FairPlayUtils.initDataTransform(initData, contentId, cert);
});
// Tùy chỉnh request lấy license
player.getNetworkingEngine().registerRequestFilter(function (type, request) {
  if (type == shaka.net.NetworkingEngine.RequestType.LICENSE) {
    request.uris = [licenseURL];
    request.method = 'POST';
    request.headers['Content-Type'] = 'application/json';
    request.headers['custom-data'] = btoa(
      JSON.stringify({
        userId: 'USER_ID',
        sessionId: 'SESSION_ID',
        merchantId: 'MERCHANT_ID',
        appId: 'APP_ID',
      })
    );
    const originalPayload = new Uint8Array(request.body);
    const base64Payload =
      shaka.util.Uint8ArrayUtils.toStandardBase64(originalPayload);
    request.body = JSON.stringify({
      spc: base64Payload,
      assetId: new URL(licenseURL).searchParams.get('assetId'),
    });
  }
});

3.4.2. Cấu hình header cho Widevine or PlayReady

javascript
player.getNetworkingEngine().registerRequestFilter(function (type, request) {
  // Only add headers to license requests:
  if (type == shaka.net.NetworkingEngine.RequestType.LICENSE) {
    // This is the specific header name and value the server wants:

    request.headers['Content-Type'] = 'application/octet-stream';
    request.headers['custom-data'] = btoa(
      JSON.stringify({
        userId: 'USER_ID',
        sessionId: 'SESSION_ID',
        merchantId: 'MERCHANT_ID',
        appId: 'APP_ID',
      })
    );
  }
});

Nếu bạn sử dụng tính năng mã hóa license, bạn cần thêm một vài trường vào trong header như sau:

javascript
player.getNetworkingEngine().registerRequestFilter(function (type, request) {
  const StringUtils = shaka.util.StringUtils;
  const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;
  if (type == shaka.net.NetworkingEngine.RequestType.LICENSE) {
    // This is the specific header name and value the server wants:
    const packInfo = window.sigmaPacker.getDataPacker(request.body) || {};
    request.headers['Content-Type'] = 'application/octet-stream';
    request.headers['custom-data'] = btoa(
      JSON.stringify({
        userId: 'USER_ID',
        sessionId: 'SESSION_ID',
        merchantId: 'MERCHANT_ID',
        appId: 'APP_ID',
        reqId: packInfo.requestId,
        deviceInfo: packInfo.deviceInfo,
      })
    );
  }
});
PropsTypeDescription
MERCHANT_IDStringĐịnh danh khách hàng
APP_IDStringĐịnh danh ứng dụng
USER_IDStringĐịnh danh người dùng trên hệ thống của khách hàng
SESSION_IDStringMã xác thực của người dùng được cấp bởi hệ thống của khách hàng

3.5 Cấu hinh thông tin trả về

Cấu hình cho Widevine, PlayReady và FairPlayer là giống nhau và như sau:

javascript
player.getNetworkingEngine().registerResponseFilter(function (type, response) {
  var StringUtils = shaka.util.StringUtils;
  var Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;

  // Only manipulate license responses:
  if (type == shaka.net.NetworkingEngine.RequestType.LICENSE) {
    // This is the wrapped license, which is a JSON string.
    try {
      var wrappedString = StringUtils.fromUTF8(response.data);
      // Parse the JSON string into an object.
      var wrapped = JSON.parse(wrappedString);

      // This is a base64-encoded version of the raw license.
      var rawLicenseBase64 = wrapped.license;
      // Decode that base64 string into a Uint8Array and replace the response
      // data.  The raw license will be fed to the Widevine CDM.
      response.data = Uint8ArrayUtils.fromBase64(rawLicenseBase64);

      // Read additional fields from the server.
      // The server we are using in this tutorial does not send anything useful.
      // In practice, you could send any license metadata the client might need.
      // Here we log what the server sent to the JavaScript console for
      // inspection.
      console.log(wrapped);
    } catch (err) {}
  }
});

Nếu bạn sử dụng tính năng mã hóa license, bạn cần làm thêm như sau:

javascript
player.getNetworkingEngine().registerResponseFilter(function (type, response) {
  // Alias some utilities provided by the library.
  const StringUtils = shaka.util.StringUtils;
  const Uint8ArrayUtils = shaka.util.Uint8ArrayUtils;

  // Only manipulate license responses:
  if (type == shaka.net.NetworkingEngine.RequestType.LICENSE) {
    // This is the wrapped license, which is a JSON string.
    try {
      const wrappedString = StringUtils.fromUTF8(response.data);
      // Parse the JSON string into an object.
      const wrapped = JSON.parse(wrappedString);

      if (response.headers['client-info']) {
        console.log(response.headers['client-info']);
        window.sigmaPacker.update(atob(response.headers['client-info']));
      } else if (wrapped.clientInfo) {
        console.log(wrapped.clientInfo);
        window.sigmaPacker.update(JSON.stringify(wrapped.clientInfo));
      }

      // This is a base64-encoded version of the raw license.
      const rawLicenseBase64 = wrapped.license;
      // Decode that base64 string into a Uint8Array and replace the response
      // data.  The raw license will be fed to the Widevine CDM.
      response.data = Uint8ArrayUtils.fromBase64(rawLicenseBase64);
      // Read additional fields from the server.
      // The server we are using in this tutorial does not send anything useful.
      // In practice, you could send any license metadata the client might need.
      // Here we log what the server sent to the JavaScript console for
      // inspection.
      console.log(wrapped);
    } catch (err) {}
  }
});

4. Mẫu

Mã nguồn mẫu