Docs
TikTok Minis Player
Your app must use the official TikTok Minis player (VePlayer) to play reviewed mini drama episodes. This helps protect copyright safety and ensures a consistent playback experience. After your content passes review, your server prepares the required playback data, such as album_id, episode_id, vid, and a play credential, and your app uses VePlayer through the TikTok Minis SDK to render and control playback.
Note: Third-party players and native HTML video are not allowed. If they are used, TikTok will replace them with a default blocked UI. If you need support for gradual migration, submit a support ticket or contact your operations representative.
Integrate VePlayer
Follow these steps to integrate VePlayer into your mini app.
Step 1: Get the player
- Initialize the TikTok Minis SDK when the page loads.
- Obtain and cache the VePlayer constructor.
Parameters
TTMinis.getPlayer(channel) // channel: 'byteplus' | 'volcengine'. Returns Promise<typeof VePlayer>. Call init() first.Example:
let VePlayerCtor = null;
TTMinis.getPlayer().then((VePlayerClass) => {
VePlayerCtor = VePlayerClass;
});Step 2: Prepare playback data
Get approved video information from your server. This includes:
Field | Meaning | Description |
| Drama ID | Identifies the drama or album being played |
| Episode ID | Identifies the episode within the drama |
| BytePlus video ID | Identifies the actual video stored in BytePlus. Learn more about managing media assets on BytePlus. |
| Temporary play credential used for video playback on older versions of the app (TikTok versions below 44.5.0) | If a video has successfully passed content review, you can request this token via the relevant API endpoint. Note that this token is valid only for a limited duration; therefore, you should retrieve it only when you are certain that playback is required. |
Step 3: Play video
Create player
Reserve a player container element on the playback page, and use the constructor of the player VePlayer obtained in the previous step to create the player as follows:
<div id="player-container-xx" style="width: 100%; height: 100%" />const playerSdkIns = new VePlayer({
id: 'player-container-xx', // The id of the player container element
vid: 'sdsd3**33', // video id from BytePlus
lang: 'en', // UI language
albumId: videoInfo.album_id, // album id
episodeId: videoInfo.episode_id, // episode id
defaultDefinition: '720p', // default definition, If there is no need to transcode the video into multiple resolutions, it can be left unset.
getVideoByToken: {
playAuthToken: videoInfo.play_auth_token, // play temporary credential
}
});Each player instance must use a unique container. Make sure the container has the correct size through CSS.
If you use a framework such as React, you can also pass the corresponding root field through the HTMLElement object.
import { useEffect, useRef } from "react";
import * as React from "react";
export const PlayerComponent = (props) => {
const rootRef = useRef(null);
const playerSdkRef = useRef(null);
useEffect(() => {
const root = rootRef.current;
if (!root) return;
if (playerSdkRef.current) return;
playerSdkRef.current = new VePlayer({
root,
vid: props.videoInfo.vid,
albumId: props.videoInfo.album_id,
episodeId: props.videoInfo.episode_id,
getVideoByToken: {
playAuthToken: props.videoInfo.play_auth_token,
},
});
return () => {
playerSdkRef.current?.destroy();
playerSdkRef.current = null;
};
}, []);
return React.createElement('div', { ref: rootRef, className: 'player-container' });
};The player provides a rich set of UI plugins. Because mini dramas are immersive, choose a simpler configuration, for example:
const playerSdkIns = new VePlayer({
id: 'player-container-xx', // player container id
vid: 'sdsd3**33', // videovid
lang: 'en', // UI language, support en、zh-cn、jp
vid: videoData.vid, // video id
albumId: videoData.albumId, // album id
episodeId: videoData.episodeId, // episode id
closeVideoClick: false, // Whether to toggle play/pause via video click/touchend behavior
closeVideoDblclick: true, // Whether to toggle play/pause via video double click/touchend behavior
videoFillMode: "fillWidth", // video fill mode
getVideoByToken: {
playAuthToken: videoData.playAuthToken, // play auth token
needPoster: true, // whether to need poster
},
ignores: [
"moreButtonPlugin", // more button plugin at the top right corner
"enter", // enter plugin
"fullscreen", // fullscreen plugin
"volume", // volume plugin
"play", // play plugin
"pip", // picture in picture plugin
"replay", // replay plugin
"playbackrate", // playback rate plugin
"sdkDefinitionPlugin", // definition plugin
],
commonStyle: {
playedColor: "#ffffff", // played color of the progress bar after playback is completed
},
mobile: {
gradient: "none", // gradient of the container background in mobile
},
sdkErrorPlugin: {
isNeedRefreshButton: false, // whether to need refresh button
},
start: {
disableAnimate: true, // whether to disable animate
isShowPause: true, // whether to show pause button
},
});Playback interface calls
- Playback control is provided by the player kernel.
playerSdkIns.on(VePlayer.Events.READY, () => {
const player = playerSdk.player; // Obtain player kernel
console.log('player core', player);
})Note: The creation of the player kernel is an asynchronous process. Directly obtaining the kernel after the player is instantiated will not yield the kernel because the creation of the kernel has not yet completed. You can obtain the player kernel through the player property of the SDK instance after the SDK triggers an event (such as the ready event).
For more information, refer to the player kernel reference from BytePlus.
- Get the properties of the player kernel. For example, to get the current playback time:
const currentTime = playerSdkIns.player?.currentTime; // get current play time
const paused = playerSdkIns.player?.paused; // is paused
const ended = playerSdkIns.player?.ended; // is playing ended- Call the methods of the player kernel. Taking the call of the play and pause methods as an example, the sample code is as follows:
const playBtn = document.getElementById('play_btn'); // call player.play() based on user action
playBtn.addEventListener('click', (e) => {
playerSdkIns.player?.play();
});
const pauseBtn = document.getElementById('pause_btn'); // call player.pause() based on user action
pauseBtn.addEventListener('click', (e) => {
playerSdkIns.player?.pause();
});- Switch video: If you need to switch videos without destroying the player instance, you can call the playNext method and pass in the new video information.
playerSdkIns.playNext({
albumId: nextVideoData.albumId,
episodeId: nextVideoData.episodeId,
vid: nextVideoData.vid,
getVideoByToken: {
playAuthToken: nextVideoData.playAuthToken, // play auth token
},
}).then(() => {
console.log('play next video completed');
});Monitor playback status
The player provides a full event monitoring mechanism so you can implement playback-related features as needed.
- Listen for playback errors:
playerSdkIns.on(VePlayer.Events.ERROR, (error) => {
// error TODO
})- Listen and play
playerSdkIns.on(VePlayer.Events.PLAY, () => {
// TODO after play
})- Listen for playback time updates:
playerSdkIns.on(VePlayer.Events.TIME_UPDATE, (data) => {
const { currentTime } = data;
console.log('currentTime: ', currentTime);
})For more information, refer to the events reference from BytePlus.
Destroy player
Destroy the player instance after playback is complete and the player is no longer needed.
playerSdkIns.destroy();VePlayer reference documents
Other relevant documents for the VePlayer are listed. License configuration is not required for TikTok Minis.
- Web Player SDK: Initialization parameters
- Web Player SDK: External subtitles
- Web Player SDK: Customizing UI
- Web Player SDK: Player kernel
- Web Player SDK: Events
Acquire video playback token (for older client versions)
Invoke this API to retrieve a play credential used for video playback on older versions of the app (TikTok versions below 44.5.0).
Base info
HTTP URL | |
HTTP Method | GET |
HTTP Header |
|
Request parameters
Field | Type | Description | Example | Required |
client_key | string | Client unique identifier | mnxxxxxxx | Yes |
episode_id | string | Episode ID | 7234234123423421 | Yes |
Example
curl --location --request GET 'https://open.tiktokapis.com/v2/sg/shortdrama/play_token?client_key=mnxxxxxxxxxxxxx&episode_id=3453425324534' \
--header 'Authorization: Bearer xxxxx'Response
Field | Type | Description | Example |
play_auth_token | string | Video playback token | wasfasdfasdfasdfaasdfafasfastokenxasdfafasfa |
Migrate from a third-party player
If you use a third-party player or native HTML video, TikTok will replace it with a default blocked UI. You can apply for an exemption to support gradual migration by submitting a support ticket or reaching out to your operations representative.
Before the exemption is available, if you need to customize the replaced UI elements, use the setValidateVideoReplaceElement API from the TikTok Minis SDK.
TTMinis.setValidateVideoReplaceElement(customReplaceElement: (
videoEl: HTMLVideoElement,
replaceReason: string,
) => HTMLElement | null)External subtitles
After developers upload subtitles via the media library API, VePlayer supports automatically parsing the subtitle list from short drama media info and injecting it into the subtitle plugin for display, without the need to manually configure the subtitle list Subtitle.list.
Subtitle configuration is only used to control plugin behavior (such as isDefaultOpen, style, etc.), and the list field within it will be overridden by the automatically parsed results.
Through the formatAutoSubtitleItem callback, each subtitle item can be filtered, renamed, and sorted. Subtitle language tags (language / language_id) are automatically converted to native language names (for example, Simplified Chinese, English, 日本語).
Note:
autoSubtitledepends on theSubtitleplugin. IfSubtitleis not configured, the subtitle plugin will not be registered whennew VePlayeris called, and subtitles will not be displayed.- If subtitles in multiple languages are required, developers need to use the media asset library interface multiple times to upload subtitle files for each language.
new VePlayer({
// ...
autoSubtitle: true,
Subtitle: {}, // Required: ensures the plugin is registered
});Note: Subtitle.list does not need to be manually passed in. After enabling autoSubtitle, the player will automatically parse the subtitle list when retrieving media information, and write it to Subtitle.list after filtering, customizing, or sorting through formatAutoSubtitleItem.
The player provides a UI plugin for subtitle selection and corresponding APIs for controlling subtitle display.
Subtitle format support
WebVTT, SRT, ASS, and SSA (complex subtitle styles are not supported; only text content is displayed)
Initialization configuration
autoSubtitle
Property | Type | Default |
|
|
|
When set to true, the player will automatically convert subtitle_info_list / SubtitleInfoList into a subtitle list and apply it to the subtitle plugin when media info is obtained.
formatAutoSubtitleItem
Property | Type | Default |
|
|
|
A formatting callback triggered before each subtitle item is generated, used for filtering, renaming, or adjusting order.
Callback Parameters:
Parameter | Type | Description |
|
| Raw subtitle item returned by the server |
|
| Index of the current item in the original list (starting from 0) |
item Object Fields:
item comes from the server-side subtitle list data.
Field | Type | Description |
|
| Subtitle ID |
|
| Subtitle language tag, e.g., |
|
| Subtitle language ID, e.g., |
|
| Subtitle format, e.g., |
|
| External subtitle file URL |
|
| Subtitle source, e.g., |
|
| Subtitle status, e.g., |
|
| Subtitle title; used as a name fallback when language mapping does not match |
|
| Subtitle tag |
|
| File ID |
|
| Storage URI |
|
| Video ID |
Example subtitle item:
{
"file_id": "",
"format": "webvtt",
"language": "cmn-Hans-CN",
"language_id": 1,
"source": "MT",
"status": "enable",
"store_uri": "",
"subtitle_id": "1857853977",
"subtitle_url": "https://veplayer-vod-cdn.bytepluscdn.com/.../?X-Amz-...",
"tag": "",
"title": "",
"vid": ""
}Return Value Behavior:
Return Value | Behavior |
| Use this value as the subtitle display name |
| Pass through, keep the default parsed result |
| Filter out this subtitle, not shown in the list |
| Use |
| Filter out this subtitle |
| Set sort weight; smaller values come first; can be used with |
| Set this subtitle as the default selection; can be used with |
Subtitle
Top-level Configuration:
style Sub-configuration:
Property | Type | Default | Description |
|
|
| Whether to adjust subtitle position along with the control bar |
|
|
| Font display mode: |
|
|
| Height offset (px) when following the bottom control bar |
|
|
| Whether to auto-adjust font size based on the video frame |
|
|
| Percentage of subtitle distance from the bottom of the video frame |
|
|
| Base font size for landscape video |
|
|
| Base font size for portrait video |
|
|
| Minimum font size on PC |
|
|
| Minimum font size on mobile |
|
|
| Maximum number of display lines |
|
|
| Font color, supports 16-bit color values or RGB values |
list Item Structure (ISubTitleItem):
Property | Type | Description |
|
| Subtitle ID |
|
| Subtitle language tag |
|
| Subtitle display name |
|
| External subtitle URL |
|
| Inline subtitle content (WebVTT / SRT text) |
|
| Structured subtitle content list (used when not in URL form) |
|
| Whether this is the default selected subtitle |
Configuration example:
new VePlayer({
autoSubtitle: true,
Subtitle: {
isDefaultOpen: true,
isShowIcon: true,
mode: 'external',
style: {
follow: true,
mode: 'stroke',
offsetBottom: 4,
line: 'double',
fontColor: '#fff',
},
},
});Subtitle language name auto-conversion
When autoSubtitle parses subtitle items, it first looks up the built-in language mapping table via language_id (numeric) or language (language tag, e.g., cmn-Hans-CN), and converts it to the native name of that language for display.
|
| Display Name |
| 1 | 简体中文 |
| 2 | English |
| 3 | 日本語 |
| 4 | 한국어 |
| 5 | 中英双语 |
| 6 | Русский |
| 7 | Français |
| 8 | Português |
| 9 | Español |
| 10 | Tiếng Việt |
| 20 | Deutsch |
| 26 | Italiano |
| 36 | 繁體中文 |
| 34 | العربية |
| 42 | हिन्दी |
For the complete language list, see BytePlus VOD Subtitle Language Documentation.
If the language tag or ID is not in the mapping table, it falls back to title → label → text → language → tag → language_id raw value in order.
Usage Examples
Basic Usage
new VePlayer({
vid: 'your_vid',
getVideoByToken: { playAuthToken: 'your_token' },
autoSubtitle: true,
Subtitle: { isDefaultOpen: true },
});Specify default language subtitle
When the player initializes, the subtitle plugin reads the item with isDefault: true (or default: true) as the default selected subtitle. If multiple subtitles are marked as default, only the first one takes effect; other marks are ignored.
Default Selection Rules (by priority):
- Specify the subtitle returned by
formatAutoSubtitleItemas{ isDefault: true }or{ default: true } - If none of the above is specified and
Subtitle.isDefaultOpenistrue(default value), the first subtitle in the list will be automatically selected.
new VePlayer({
// ...
autoSubtitle: true,
formatAutoSubtitleItem: (item) => {
// The English track is selected by default.
if (item.language === 'eng-US') {
return { isDefault: true };
}
return true;
},
Subtitle: { isDefaultOpen: true },
});You can also combine sorting with default subtitle selection:
formatAutoSubtitleItem: (item, index) => {
if (item.source === 'MT') return false;
return {
order: item.language === 'eng-US' ? 0 : index + 1,
isDefault: item.language === 'eng-US',
};
},Default display system language subtitle
Automatically select the subtitle corresponding to the device's system language (navigator.language). The example below matches via language tag mapping (see the "Subtitle Language Name Auto-Conversion" section above for language tags). If multiple matches are found, only the first takes effect; if no match is found, it falls back to the default behavior of isDefaultOpen (auto-select the first subtitle).
// Mobile system language → Subtitle language label
const SYSTEM_LANG_TO_SUBTITLE_LANGUAGE = {
'zh-hant': 'cmn-Hant-CN', // Traditional Chinese
zh: 'cmn-Hans-CN', // Simplified Chinese
en: 'eng-US',
ja: 'jpn-JP',
ko: 'kor-KR',
ru: 'rus-RU',
fr: 'fra-FR',
pt: 'por-PT',
es: 'spa-ES',
vi: 'vie-VN',
de: 'deu-DE',
it: 'ita-IT',
ar: 'ara-SA',
hi: 'hin-IN',
};
function getSystemSubtitleLanguage() {
const lower = (navigator.language || navigator.languages?.[0] || '').toLowerCase();
const iso = lower.split('-')[0];
if (iso === 'zh') {
const isHant = lower.includes('hant') || /\b(tw|hk|mo)\b/.test(lower);
return SYSTEM_LANG_TO_SUBTITLE_LANGUAGE[isHant ? 'zh-hant' : 'zh'];
}
return SYSTEM_LANG_TO_SUBTITLE_LANGUAGE[iso] ?? null;
}
const systemSubtitleLanguage = getSystemSubtitleLanguage();
new VePlayer({
// ...
autoSubtitle: true,
formatAutoSubtitleItem: (item) => {
// The subtitle corresponding to the system language is set as the default selection (e.g., if the system is in Chinese, then Chinese is the default).
if (
systemSubtitleLanguage != null &&
typeof item.language === 'string' &&
item.language.toLowerCase() === systemSubtitleLanguage.toLowerCase()
) {
return { isDefault: true };
}
return true;
},
Subtitle: { isDefaultOpen: true },
});You can also use language_id matching instead (e.g., Number(item.language_id) === 1), the principle is the same.
Filter to SRT format only
new VePlayer({
// ...
autoSubtitle: true,
formatAutoSubtitleItem: (item, index) => {
if (typeof item === 'object' && item.format !== 'srt') return false;
return { order: index };
},
Subtitle: { isDefaultOpen: true },
});Custom subtitle names
new VePlayer({
// ...
autoSubtitle: true,
formatAutoSubtitleItem: (item) => {
return item.title || item.language;
},
Subtitle: {},
});Filter specific source and custom sorting
new VePlayer({
// ...
autoSubtitle: true,
formatAutoSubtitleItem: (item, index) => {
// Filter out Machine Translation (MT) sources
if (item.source === 'MT') return false;
// ASR source is ranked at the top.
return { order: item.source === 'ASR' ? 0 : index + 1 };
},
Subtitle: {},
});Display only specific languages
new VePlayer({
// ...
autoSubtitle: true,
formatAutoSubtitleItem: (item) => {
const allowedLangs = ['cmn-Hans-CN', 'eng-US'];
if (!allowedLangs.includes(item.language)) return null;
return { label: item.title || item.language };
},
Subtitle: {},
});Subtitle Control API
The following APIs can be called directly through the player instance without using the subtitle UI icon. Ensure the Subtitle plugin is registered (configured with Subtitle: {}) before calling.
getSubtitleList()
Get the current subtitle list.
const list = playerSdk.getSubtitleList();
// return examples:
// [
// { id: 'sub-zh', language: 'cmn-Hans-CN', text: '简体中文', url: 'https://...' },
// { id: 'sub-en', language: 'eng-US', text: 'English', url: 'https://...' },
// ]Return Value | Type | Description |
Subtitle list |
| Returns |
switchSubtitle(subtitle)
Switch to a specified subtitle.
// Switch by ID
playerSdk.switchSubtitle({ id: 'sub-en' });
// Switch via language
playerSdk.switchSubtitle({ language: 'eng-US' });Parameter | Type | Description |
|
| Subtitle ID; either this or |
|
| Subtitle language tag |
Returns Promise<void>; resolves on successful switch, rejects if the target subtitle is not found.
showSubtitle()
Enable subtitle display. Resumes the last selected subtitle; if none was selected, automatically selects the first one.
playerSdk.showSubtitle();hideSubtitle()
Disable subtitle display. Subtitle data is retained and can be re-enabled via showSubtitle() or switchSubtitle().
playerSdk.hideSubtitle();Comprehensive example
const playerSdk = new VePlayer({
// ...
autoSubtitle: true,
Subtitle: { isDefaultOpen: false }, // Not displayed by default, manually controlled
});
// get subtitle list
const list = playerSdk.getSubtitleList();
console.log(list); // [{ id, language, text, ... }, ...]
// switch to english
await playerSdk.switchSubtitle({ language: 'eng-US' });
// hide subtitle
playerSdk.hideSubtitle();
// show subtitle
playerSdk.showSubtitle();Preload for first frame optimization
Note: VePlayer preloading is used to download part of the target video's data in advance before actual playback, so that during actual playback, the pre-downloaded video data cache can be used for quick start, reducing the time to first frame and the waiting time for episode switching.
The short drama scene can directly pass the episode parameters into setPreloadList / addPreloadList , and the SDK will internally query the short drama video information and convert it into the resource data required for player preloading.
Note: This feature is a newly added one and does not affect applications that have historically integrated with the player.
Overview and working principle
Core idea of the VePlayer preloading module: Before the user actually clicks to play, download a portion of the target video's data to the memory cache in advance; when the user actually plays, the player directly reads data from the cache, skipping the network download phase, thereby significantly reducing the time to first frame and the waiting time for episode switching.
The working principle is shown in the figure below:
Compatibility description
Project | Support Status | Description |
Encapsulation Format | MP4 | Currently only MP4 resource preloading is supported |
Playback Configuration | has enabled MSE capabilities | Player instantiation must pass in |
Browser Environment | Environment supporting MSE | PC, Android H5, and iOS 17.1+ support |
Short video input parameters | Support |
|
Quickstart
The following is the simplest runnable example to help you complete the basic preloading process within 30 seconds:
// 1. Initialize the preloading module
await VePlayer.prepare({
strategies: { preload: true },
});
// 2. Set the preload list
await VePlayer.setPreloadList([
{
vid: "**********",
albumId: "***********",
episodeId: "********",
defaultDefinition: "720p",
getVideoByToken: { playAuthToken: "..." },
},
]);
// 3. Create a player (MSE must be enabled)
const playerSdk = new VePlayer({
id: video,
vid: "**********",
albumId: "***********",
episodeId: "********",
defaultDefinition: "720p",
getVideoByToken: { playAuthToken: "..." },
enableMp4MSE: true,
});Initialization and configuration
Initialize the preloading module
Before calling setPreloadList / addPreloadList, you need to initialize the preloading module first:
await VePlayer.prepare({
strategies: {
preload: true,
},
});strategies.preload can be passed true to use the default configuration, or a configuration object can be passed in, for example, to set the default preloading scene, preloading duration, maximum cache count, etc.
strategies.preload Configuration Parameters
Parameter Name | Type | Default Value | Description |
|
|
| Preload scenarios. |
|
|
| Number of videos preloaded forward, only takes effect in the Feed stream scenario where |
|
|
| Number of videos preloaded backward, only takes effect in the Feed stream scenario where |
|
|
| Preloading duration of a single video, unit: seconds |
|
|
| Maximum number of video caches; after exceeding, eviction follows the LRU strategy |
|
|
| Whether to disable preloading; |
Preloaded resource format
Preloading short dramas only requires passing in the drama parameters:
const episode = {
vid: "**********",
albumId: "***********",
episodeId: "********",
defaultDefinition: "720p",
getVideoByToken: {
playAuthToken: "...",
},
};Field | Type | Description | Required |
|
| Short Drama ID | Yes |
|
| Short drama episode ID, which is also part of the cache key for short drama video information | Yes |
|
| Video ID; it is recommended to pass it in for easy querying and matching of video data. Please ensure that each video has a unique video vid | No |
|
| Preload target clarity, which is also part of the short drama video information cache key | No |
|
| Play Token configuration will be reused for short drama video information query | No |
Media information cache
Tip: Recommended to enable: Linkage between media information caching and preloading. During preloading, short video information has been requested and cached in advance. When playing, directly reusing the cache can save the time consumed by interface requests, and only by cooperating with preloading can the first frame truly be optimized to the extreme.
Media information caching is turned off by default. After it is enabled, when querying short video information or obtaining media information via playAuthToken, the cache will be read first; if there is no hit, a request will be initiated, and valid results will be written to the cache.
VePlayer.setMediaInfoCacheConfig({
enable: true
});Supported configuration items are as follows:
Configuration Item | Type | Default Value | Description |
|
|
| Whether to enable media information caching |
|
|
| Cache location; |
|
|
| Cache expiration time, in milliseconds; invalid values will be ignored. The actual expiration time will not be later than the expiration time of the playback URL |
|
|
| Maximum number of cached items; items will be evicted based on the most recent access time after exceeding this limit |
Short video information cache is distinguished by episodeId + defaultDefinition for different episodes and definitions. To clear the cache, you can call:
VePlayer.clearMediaInfoCache();Note: cacheType: localStorage is suitable for cross-page or persistent reuse of media information; if you only need to reuse within the current page, use the default memory.
Detailed explanation of preloading scenes
Scenario comparison and selection recommendations
Preloading switches the execution mode via setPreloadScene(scene, options), scene corresponds to the PreloadScene enumeration:
PreloadScene.NORMAL(0): Normal scene, manually perform preloading.PreloadScene.FEED(1): Feed stream / Previous/Next episode switching scene, where the player automatically performs preloading.
The essential difference between the two scenarios lies in "who decides which videos to preload": in the normal scenario, the business explicitly specifies the resources to be loaded through setPreloadList / addPreloadList; in the Feed stream scenario, the player automatically locates based on the vid of the currently playing video in the ordered list, and schedules several episodes before and after according to prevCount / nextCount.
Dimension | Normal Scenario NORMAL (0) | Feed Stream Scenario FEED (1) |
Trigger Mode | Manual: Immediately enter the preload queue after the business calls | Automatic: Automatically detect and schedule when the player creates an instance or switches sets ( |
List Semantics | Resource collection to be preloaded, loaded upon invocation | Ordered playlist, retrieving previous and next videos in the list based on the current playback position |
Scheduling Scope | Load as much as the business provides | Only load the first |
| does not take effect | Effective (default 1 before, 2 after, prioritize loading subsequent videos) |
Currently playing video | will not be preloaded (already playing) | will not be preloaded and only serve subsequent cuts |
List maintenance cost | The business needs to decide on its own when to load which episodes | The business only needs to maintain a complete and ordered list, and the preloading of the cut set is managed by the player |
Typical Entrance | Homepage / "Preheating" of exposure, hover, and near-click of the landing page card | Play the determined episode playback sequence within the play page |
Switching scenes will clear the list of items to be loaded that have not yet entered the preloading queue (tasks already being loaded are not affected), preventing the manual list from being carried over into automatic mode and causing unexpected loading.
Selection Recommendations: For general scenarios, preheating the first episode before the playback page opens is suitable; for Feed stream scenarios, continuous episode chasing within the playback page is appropriate. In practice, the two are often used in combination (see "Linkage between Manual Preheating and Automatic Management" for details).
Manual Mode
Manual mode is suitable for explicitly adding preloading tasks for certain episodes before the playback page is opened, when the card is exposed, or when the user is about to click on a specific episode.
await VePlayer.prepare({
strategies: { preload: true },
});
await VePlayer.setPreloadScene(0);
await VePlayer.setPreloadList([
{
vid,
albumId,
episodeId,
defaultDefinition: "720p",
getVideoByToken: { playAuthToken },
},
]);
const playerSdk = new VePlayer({
id: video,
vid,
albumId,
episodeId,
defaultDefinition: "720p",
getVideoByToken: { playAuthToken },
enableMp4MSE: true,
});In Manual Mode:
setPreloadList(list)will replace the current preload list.addPreloadList(list)will append new resources to be preloaded without clearing the existing list.- The player will not preload the video that is currently playing.
- If you want the first video after instantiation to hit preloading, you need to allow sufficient download time before
new VePlayer().
Auto Mode (Feed Stream)
Automatic mode is suitable for scenarios where there is already a defined playback sequence within the playback page. The business only needs to set a complete playlist, and the player will locate the current playing video based on its vid in the list and automatically select several videos before and after it to add to the preloading task.
How Feed Stream Scenarios Work
In the Feed stream scenario, the business only needs to set up a complete and ordered list, and the remaining scheduling is entrusted to the player. The behavior can be summarized as:
- Select target by playback position: Based on the currently playing video, automatically select the previous
prevCountand nextnextCountepisodes for preloading, and prioritize loading subsequent videos. - Does not compete for bandwidth with playback: Preloading will sense the current playback state and only proceed opportunistically when the current video is playing smoothly; when the current playback is laggy or the buffer is insufficient, it will automatically yield to prioritize ensuring the video being played.
- Execute item by item: Preload tasks are executed serially, advancing with the playback progress to avoid saturating the network all at once.
- Automatic Deduplication : Videos that are already in the cache, already in the queue, or currently playing will not be preloaded repeatedly; the currently playing video itself will not be preloaded either.
Therefore, the automatic mode eliminates the need for the business to manually maintain the next episode list after each episode switch, making it more suitable for continuous drama watching within the playback page.
await VePlayer.prepare({
appId: 521173,
strategies: { preload: true },
});
await VePlayer.setPreloadScene(1, {
prevCount: 1,
nextCount: 2,
});
await VePlayer.setPreloadList(episodeList);
const playerSdk = new VePlayer({
id: video,
vid: currentVid,
albumId,
episodeId: currentEpisodeId,
defaultDefinition: "720p",
getVideoByToken: { playAuthToken },
enableMp4MSE: true,
});In Automatic Mode:
setPreloadList(list)sets an ordered playlist, which should be consistent with the actual playback order of the feed stream videos.- If you need to add Tabular Data, use
addPreloadList(list). - Under the feed flow, try to keep only one player instance on the entire page, switch videos through playNext, or switch videos by destroying the old player and creating a new one.
- The player will automatically select videos within the range of
prevCountandnextCountfor preloading based on the current position of the playing video. - When creating a player instance, switching videos, setting or adding to the preload list, a preload task check will be triggered.
- The first video being played will not be automatically preloaded; the automatic mode mainly serves the subsequent episode-switching experience.
When slicing a set, video information that can match the preloaded list still needs to be passed in:
playerSdk.playNext({
vid: nextVid,
albumId,
episodeId: nextEpisodeId,
defaultDefinition: "720p",
getVideoByToken: { playAuthToken },
enableMp4MSE: true,
});Connection between manual preheating and automatic hosting
The most common combined usage in practice: Use manual mode to preheat the first episode on the home page, and then switch to automatic mode to manage subsequent episode switching after entering the playback page.
From the home page to the playback page: Preheat the first episode in manual mode
- Call
setPreloadScene(0)before card exposure, user hover, slide proximity, or click. - Use
setPreloadListoraddPreloadListto add the first episode preloading task. - When the user enters the playback page, if the first video has already been downloaded to the target duration, it can directly hit the preloaded data.
Switch from the preheating on the home page to the automatic mode on the playback page
VePlayer.preloader?.clearPreloadList();
VePlayer.preloader?.removeAllPreloadTask?.();
await VePlayer.setPreloadScene(1, {
prevCount: 1,
nextCount: 2,
});
await VePlayer.setPreloadList(episodeList);Comparison with multi-instance player preloading
Another common preloading approach on the web ispreloading with multiple instance players: create a hidden player / <video> instance for each video to be loaded (set preload="auto" or directly load()), trigger the browser to download in advance, and then switch instances or replace src during playback. VePlayer's preloading does not rely on additional playback instances, but rather aglobal singleton preloading module downloads data to memory cache based on MSE, and directly reuses it to participate in playback when a hit occurs.
Dimension | Multi-instance Player Preloading | VePlayer Preloading (This Solution) |
Resource Occupancy | One | Global singleton preloading module, no additional playback instances, only in-memory cached data |
Concurrency Limit | Subject to the Concurrency Limit of browser media elements (especially on mobile devices / iOS, which typically only allows 1 stream of decoding) | Does not occupy the decoder and is not restricted by the Concurrency Limit of media elements |
Download Granularity | The browser decides on its own, usually pulling data as needed, making it difficult to precisely control the download volume | Control the download duration according to |
Cache Management | Each instance is independent, making it difficult to uniformly retire and reuse | Unified Cache + |
Decoupled from Playback | Preloading requires an existing playback instance first | Decoupled from the playback instance, it can be preheated even when there is no player (such as on the home page) |
Cut Set Scheduling | The business independently manages the creation/destruction and switching of multiple instances | The Feed stream scenario is automatically scheduled by the player according to |
Hit Metric | No unified hit caliber | Provides |
Bandwidth Competition | Simultaneous full downloads of multiple instances tend to preempt the bandwidth of the first screen | Only download the first segment required for starting playback, with controllable concurrency, reducing bandwidth competition |
Advantages of this solution
- Lightweight with No Additional Instances: Does not create redundant players /
<video>, does not occupy the decoder, avoids the Concurrency Limit of media elements on mobile devices (especially iOS), and has significantly lower memory and performance overhead. - Controllable Download, Bandwidth Saving: According to
preloadTime, only download the first segment (GOP/Range segment) required for starting playback, rather than the entire video, to avoid competing for bandwidth with the first-screen resources. - Unified Caching and Reuse: All preloaded data enters the unified cache, is evicted according to
preloadMaxCacheCountLRU, reused across episodes and pages, and directly participates in the start-up after a hit to reduce the time to first frame. - Decoupled from Playback : The preloading module is a global singleton, which can preheat the first episode in advance when there are no playback instances (home page/landing page), and also supports automatic scheduling within the playback page according to the playback progress.
- Scheduling and Hosting : In the Feed stream scenario, the player automatically maintains preloading of previous and next episodes based on the current
vid, and the business does not need to manually manage the lifecycle of multiple instances. - Measurable: The hit situation can be quantified through
player.preLoadDataandPRELOAD_INFOevents, facilitating the evaluation of benefits and parameter adjustment.
Hit monitoring and metrics
player.preLoadData
After starting playback, you can read preLoadData to check if the current player hits preloading:
playerSdk.on(VePlayer.Events.PLAY, (args) => {
console.log(playerSdk.preLoadData);
// { hit: 1, duration: 5.2, length: 413696 }
});Field | Type | Description |
|
|
|
|
| Preloading duration, unit: second |
|
| Preloaded data volume, unit: ByteDance |
PRELOAD_INFO Event
This event is triggered when the player finds an available preloaded cache. It is recommended to combine with byteLength to determine whether there is actually available data.
playerSdk.on(VePlayer.Events.PRELOAD_INFO, data => {
console.log([PRELOAD_INFO], data);
});Task and data management
VePlayer.preloader provides interfaces for cleaning up preloaded data, canceling tasks, and resetting the list of items to be preloaded. The scope of action of the three is different, and it is recommended to choose according to the actual scenario.
API | Target Object | Do you want to interrupt the task that is being loaded? | Does it affect subsequent preloading tasks? | Typical Scenario |
| Downloaded preloaded data | No | No | Release cached preloaded data while retaining the ability to schedule subsequent tasks |
| Current task, list to be preloaded, task being loaded | Yes | Yes, the current task queue will be cleared | Leave the page, switch business scenarios, and switch from the home page preheating to the automatic mode of the playback page |
| List of resources to be preloaded | No | Yes, the list to be preloaded will be cleared | Reset the preload list that is about to be executed, but do not remove the downloaded data |
Clean up preloaded data
removeAll() will remove the preloaded data that has already been downloaded, without canceling subsequent preloading tasks or preventing new tasks from continuing to execute.
VePlayer.preloader?.removeAll();Suitable for use when cache pressure is high, preloaded data needs to be released, but the current preloading strategy and subsequent task scheduling still need to be retained.
Cancel preloading task
removeAllPreloadTask() will cancel all preloading tasks, clear the preloading resource list, remove the current task list, and interrupt the currently loading task.
VePlayer.preloader?.removeAllPreloadTask?.();Suitable for use when the page is destroyed, the business scenario is switched, or the current preloading behavior needs to be stopped immediately.
Empty the list to be preloaded
clearPreloadList() will clear all lists of resources to be preloaded, without removing the preloaded data that has already been downloaded, nor will it actively interrupt the currently ongoing loading tasks.
VePlayer.preloader?.clearPreloadList();Suitable for cleaning up the old list before resetting setPreloadList , or for use when only wishing to stop subsequent list scheduling.
Notes
- When instantiating the player,
enableMp4MSE: truemust be passed in; otherwise, preloaded data cannot be used. defaultDefinitionmust be consistent with the actual playback resolution; otherwise, both the short video information cache and preload cache may fail to hit.- Preload hits require a download window.
setPreloadList/addPreloadListWhen the interval between them and actual playback is too short, it may only create cache entries, but there are not enough bytes to participate in the start of playback. - If the video is incompatible due to issues such as non-transcoding, it will cause the player to degrade from MSE playback to native video playback, and in this case, preloaded cached data cannot be used for playback start.
- It is not recommended to add preloading tasks for all episodes without limitation. In the short drama scenario, the number of tasks should be controlled based on user paths, click probabilities, and network conditions.
- When switching pages or execution modes, old lists and necessary old tasks should be cleared to avoid network resource competition.
Best Practices
Within the playback page: Automode is preferred
The short drama playback page usually has a fixed playback sequence, such as from Episode 1 to Episode N. After entering the playback page, it is recommended to use the automatic mode:
- Initialize the preloading module.
- Call
setPreloadScene(1, { prevCount, nextCount })to switch to automatic mode. - Call
setPreloadList(episodeList)to set the complete or partial ordered list on the playback page. - Create a player instance and ensure that the instantiation parameters include
enableMp4MSE: true.
From the home page to the playback page: the first episode can be preheated using the manual mode
If you want the first video on the playback page to also hit preloading, you can use the manual mode in advance on the home page or landing page with episode cards:
- Call
setPreloadScene(0)before card exposure, user hover, slide proximity, or click. - Use
setPreloadListoraddPreloadListto add the first episode preloading task. - When the user enters the playback page, if the first video has already been downloaded to the target duration, it can directly hit the preloaded data.
Recommended Configuration Reference
Scene | Recommended Configuration | Description |
Homepage Preheat First Episode |
| Manual mode preheats for 1 episode, and 5 seconds of data is sufficient to start broadcasting |
Continuous drama watching on the playback page |
| Automatic mode, 1 front and 2 rear, covering upper and lower sets |
Media Information Cache |
| Recommended to enable, just reuse within the page |