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
- Widevine:
- Playready:
- Fairplay:
- Staging:
- Production:
- Certificate URI: https://cert.sigmadrm.com/app/fairplay/{MERCHANT_ID}/{APP_ID}
- License URL: https://license.sigmadrm.com/license/verify/fairplay
Trong đó, MERCHANT_ID và APP_ID có thể được lấy từ hệ thống Dashboard như hình dưới đây.
:::
2. Yêu cầu
::: Thông tin yêu cầu
- Trình duyệt hỗ trợ Html5:
Trình duyệt | Widevine | PlayReady | FairPlay | Hỗ trợ mã hóa license |
---|---|---|---|---|
Chrome (Window, MacOS, Android, ChromeOS, Linux) | Yes | No | No | Yes |
Firefox (Window, MacOS, Linux) | Yes | No | No | Yes |
Microsoft Edge (Window, MacOS, Android) | Yes | Yes | No | No |
Safari (Safari 8+ on MacOS, Safari on iOS 11.2+) | No | No | Yes | No |
iOS Browser (Chrome, Cốc Cốc, Microsoft Edge, Firefox, Opera) | No | No | Yes | No |
Opera (Window, MacOS) | Yes | No | No | Yes |
Internet Explorer (Window 8.1+) | No | Yes | Yes | No |
- Smart TVs:
Smart TVs | Widevine | PlayReady | FairPlay | Hỗ trợ mã hóa license |
---|---|---|---|---|
SamSung Tizen (2016-2017, 2018+ Models) | Yes | Yes | No | No |
SamSung Tizen&Orsay (2010-2015 Models) | No | Yes | No | No |
LG (WebOS 3.0+) | Yes | Yes | No | No |
LG (WebOS 1.2 & Netcast) | No | Yes | No | No |
Smart TV Alliance (LG, Philips, Toshiba, Panasonic) | Yes | Yes | No | No |
Android TV | Yes | Yes | No | No |
:::
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
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:
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.
// 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
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ường | Kiểu | Mô tả |
---|---|---|
licenseWidevineServer | String | Xem mục 1 |
licensePlayReadyServer | String | Xem mục 1 |
licenseFairPlayServer | String | Xem mục 1 |
manifestUri | String | URL 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:
Props | Type | Description |
---|---|---|
CERTIFICATE_URI | String | Xem mục 1 |
MERCHANT_ID | String | Định danh khách hàng |
APP_ID | String | Định danh ứng dụng |
USER_ID | String | Định danh người dùng trên hệ thống của khách hàng |
SESSION_ID | String | Mã 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
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
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:
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,
})
);
}
});
Props | Type | Description |
---|---|---|
MERCHANT_ID | String | Định danh khách hàng |
APP_ID | String | Định danh ứng dụng |
USER_ID | String | Định danh người dùng trên hệ thống của khách hàng |
SESSION_ID | String | Mã 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:
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:
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) {}
}
});