This package provides a customizable, modular web-based media player built on top of PRESTOplay. It supports advanced features such as DRM, adaptive streaming (DASH, HLS, Smooth), and robust subtitle and audio-only handling. The code is designed to quickly integrate secure video playback into their web applications, with options for custom controls and extensibility.
@castlabs/prestoplay)npm run build
npm link
npm link prestoplay-drm-player
The final product is a JS package that initializes a video player that supports:
prestoplay-package/
├── demo.html # Demo page for testing the player
├── src/
│ ├── index.js # Main player logic and class
│ ├── custom-controls.js # Custom UI controls logic
│ ├── drm-config.js # DRM configuration templates
│ ├── audio-only-handler.js# Audio-only content handling
│ ├── subtitle-handler.js # Subtitle detection/handling logic
│ └── styles.css # Player and control styles
├── package.json # Project metadata and dependencies
├── webpack.config.js # Webpack build configuration
└── README.md # Project documentation
File Roles:
index.js: Main entry point, player class, and orchestration.custom-controls.js: Handles custom UI controls (play, pause, subtitles, etc.).drm-config.js: DRM setup and configuration.audio-only-handler.js: Logic for handling audio-only content.subtitle-handler.js: Logic for subtitle detection and management.styles.css: Styling for the player and controls.demo.html: Example usage and UI for testing.Create and configure a PRESTOplay player instance, attach it to the DOM, and set up controls.
Example Initialization:const player = new PrestoPlayDRMPlayer({
containerId: "video-container", // (required) id of the container div
source: "https://example.com/video.mpd", // (required) video source URL
prestoplayCred: { // (required) DRM credentials
license: "", // (required)
viewerId: "" // (required)
},
width: 960, // (optional) video width
height: 540, // (optional) video height
isDRM: true, // (optional) enable DRM
drmConfig: { // (optional) DRM config object (for User Authorization Callback Approach)
env: "DRMtoday_STAGING", // (optional) DRM environment, "DRMtoday" (Production) or "DRMtoday_STAGING" (Staging)
customData: {
userId: "rental1",
sessionId: "p0", // (optional) sessionId to validate user's active subscription
merchant: "organizationApiName",
assetId: "Widevine-Test" // (optional) assetId of license requested content
}
},
drmtoday: { // (optional) DRM config object (for Upfront Authorization Token Approach)
userId: "rental1",
sessionId: "p0",
merchant: "organizationApiName",
environment: "DRMtoday_STAGING",
authToken: "MY_AUTHORIZATION_TOKEN" // (optional) pre-generated authorization token to validate user's active subscription
},
controls: false, // (optional) use built-in controls
autoplay: false, // (optional)
loop: false, // (optional)
muted: false // (optional)
});
Required Parameters:
containerId: The id of the HTML element to attach the player to.source: The video source URL (DASH, HLS, etc.).prestoplayCred.license: DRM license string.prestoplayCred.viewerId: DRM merchant UUID.width, height: Video dimensions.isDRM: Enable DRM (default: false).drmConfig: DRM configuration object (see example above).controls: Use built-in controls (default: false).autoplay, loop, muted: Standard video options.class PrestoPlayDRMPlayer {
constructor(options = {}) {
if (!options.containerId) throw new Error("containerId is required");
if (!options.source) throw new Error("source is required");
if (!options.prestoplayCred?.license && !options.prestoplayCred?.viewerId)
throw new Error("license and viewerId is required to initialize a PRESTOplay player");
// ...
}
}
About PRESTOplay License and Merchant:
this.player = new clpp.Player(this.video, this.options.prestoplayCred);
prestoplayCred.license is the license string you obtain from the PRESTOplay license page. Note: This license is only valid for the domains that have been registered with the license itself. If you use it on an unregistered domain, playback will fail.prestoplayCred.viewerId is your merchant UUID (universally unique identifier) provided by PRESTOplay.containerId, source, or PRESTOplay license, DRM credentials will cause initialization to fail.Configure DRM and load the video source.
Code Snippet:await this.player.load({
source: this.options.source,
autoplay: this.options.autoplay,
loop: this.options.loop,
muted: this.options.muted,
drm: this.options.isDRM ? this.options.drmConfig : undefined,
});
Explanation:
load method loads the video, sets up the player, and applies DRM if needed.Add custom controls and handle subtitle tracks.
Code Snippet:import { createCustomControls } from "./custom-controls";
createCustomControls(this.player, this.video, this.options.containerId);
Explanation:
Detect and adjust UI for audio-only content.
Code Snippet:import { checkAudioOnlyContent } from "./audio-only-handler";
checkAudioOnlyContent(this);
Explanation:
this) to access and update state.data-audio-only attribute correctly.Detect, enable, and manage subtitle tracks using a modular handler.
Code Snippet:import { setupSubtitleDetection } from "./subtitle-handler";
setupSubtitleDetection(this);
Explanation:
this) to access and update state (subtitleProcessed, prestoTracks).
| Feature | Upfront Authorization Token | User Authorization Callback |
|---|---|---|
| Core Idea | The backend server pre-authorizes the user and gives the player a "ticket" (the token) to present to DRMtoday. | DRMtoday receives a request and asks the backend server in real-time, "Is this user allowed to watch this?" |
| Workflow | One-way trip: Client -> The Backend Server -> Client -> DRMtoday | Round trip: Client -> DRMtoday -> The Backend Server -> DRMtoday -> Client |
| Backend Responsibility | Generate a secure, signed, and short-lived token before the license request is made. | Implement a server endpoint that can receive a real-time callback from DRMtoday and respond instantly. |
| Complexity | Simpler for the DRM provider (DRMtoday), but requires the backend server to handle token generation logic. | More complex backend logic is required to handle the real-time callback, but it gives you more direct control. |
| Latency | Potentially lower latency, as DRMtoday can issue the license immediately after validating the token without an extra network hop. | Slightly higher latency due to the additional real-time callback from DRMtoday to the backend server. |
| Real-time Control | Less real-time control. A user's rights are based on when the token was generated (tokens are valid for 10 minutes). | Maximum real-time control. You can deny a license request the instant a user's subscription expires. |
| Best For | Standard VOD playback, SPAs, and situations where you want to reduce the real-time load on the backend server. | Live streaming, pay-per-view events, or systems where immediate, up-to-the-second authorization is critical. |
this) as context, making state management explicit and modular.log() utility in demo.html for step-by-step tracing.For further questions or advanced customization, refer to the official PRESTOplay documentation or contact your system administrator.