Migrating 250M Videos to Tencent Cloud VOD: Architecture, Web Integration & Key Lessons
This article details how Tencent Classroom moved 2.5 million videos to Tencent Cloud VOD, covering the overall solution, video upload and playback processes, web integration steps, encountered issues, code implementations, and monitoring strategies, all resulting in improved performance and user experience.
Overall Introduction
Tencent Classroom provides online education through live and on‑demand video services. Since its launch in 2014 it has stored 2.5 million videos (600 TB, 1.5 million hours). To prevent piracy of MP4 links, the video‑on‑demand (VOD) service was migrated from Tencent Video to Tencent Cloud VOD.
Overall Solution
The migration was split into two phases because of the large amount of existing videos and the need to keep the old upload path operational during the transition.
Phase 1: integrate Tencent Cloud upload, transcoding and playback for newly uploaded videos while still mirroring them to Tencent Video for fallback.
Phase 2: migrate all legacy videos to the cloud, enable AI‑based content moderation, and retire the old solution once stable.
Video Upload Process
The upload workflow consists of three main steps:
Obtain a signature from the business backend.
Call the cloud SDK to upload the video.
The cloud server transcodes the video.
The SDK upload step is the most error‑prone because it directly affects the upload success rate and can be impacted by the user's network conditions. Detailed client‑side logging is recommended for troubleshooting.
Video Playback Process
Previously videos were unencrypted, which allowed easy piracy. After migration, encrypted HLS with Key anti‑leech and DRM is used, so even if the URL is obtained it cannot be replayed without the proper token.
Token: anti‑leech token that limits URL expiration, allowed IPs, etc.
DK: decryption key for AES‑128 encrypted TS segments, provided by Tencent Cloud KMS.
Web Integration Process
Video Upload
Access Method
Upload relies on
vod-js-sdk-v6written in TypeScript, which internally uses
cos-js-sdk-v5for object storage.
Two integration steps are required:
Pass a function that fetches a signature; the SDK calls it before, during, and after upload.
Call the SDK
uploadmethod to send the video.
import TCVod from 'vod-js-sdk-v6';
const uploader = new TCVod({ getSignature });
function getSignature() {
return fetch('FAKE_CGI_URL').then(r => r.sign);
}
function uploadVideo(videoFile) {
const upVideo = uploader.upload({ videoFile });
upVideo.on('video_progress', info => {/* log progress */});
upVideo.done().then(result => {/* handle success */}).catch(error => {/* handle error */});
}During the gray‑release we discovered issues and added extensive logging for signature acquisition and upload status.
Encountered Issues
1. Default upload region was Chongqing
The upload URLs were all pointing to the Chongqing COS endpoint because the region setting was not enabled in the console. Enabling the appropriate region in the COS configuration resolves this.
2. SDK upload errors
Initial upload success rate was 97 % (target 99 %). Two root causes were identified:
Client clock drift caused COS authentication failures (403).
Network jitter triggered signature handling bugs in
vod-js-sdk-v6, also resulting in 403.
Both issues are fixed in the latest SDK version, raising the success rate above 99.5 %.
PC & H5 Video Playback
The playback flow is straightforward: obtain the
m3u8URL, then let the player play it.
After adding the anti‑leech token, the
m3u8URL becomes time‑limited, preventing unrestricted sharing. However, the raw
m3u8file can still be downloaded. To mitigate this, each TS segment is encrypted with AES‑128 using a key supplied by KMS, and the key URI in the
m3u8includes the DRM token.
Code Implementation
Fetching the
m3u8list with token:
async getM3U8List(fileId: string) {
const { termId, onError } = this.props;
try {
const urlParams = await getUrlToken({ termId, fileId });
const videoInfo = await getPlayInfo(fileId, urlParams);
const m3u8List = getPlayListWithToken(videoInfo, { termId });
return m3u8List;
} catch (e) {
onError(e);
}
}Playback is then delegated to a player component (e.g., Super Player or tcplayerlite).
Playback Quality Monitoring
Monitoring uses an internal
monitorservice together with
tdwfor reporting and
badjsfor error tracing.
Mini‑Program Video Playback
Two challenges exist for mini‑programs: no built‑in cloud player component and lack of cookies for authentication. The solution is a custom
<cloud-player-video>component that receives four key parameters (appId, tokenObj, drmToken, fileId) and constructs an encrypted
m3u8URL.
tokenObj: anti‑leech token (expiry, signature, etc.). drmToken: authentication token for decrypting TS segments. The component builds the final m3u8 URL and passes it to the native <video> element.
Component usage example:
<cloud-player-video
player-id="course-video-player{{r}}"
file-id="{{fileId}}"
app-id="{{appId}}"
token-obj="{{tokenObj}}"
drm-token="{{drmToken}}"
safety
poster="{{poster && tools.renderUrl(poster)}}"
bindplay="onPlay"
bindpause="onPause"
binderror="onVideoError"
bindended="onEnded"
bindmedianotsup="onMediaNotSup" />Key methods inside the component:
function getPlayInfo() { /* request play info using appId, tokenObj, fileId */ }
function formatUrlWithToken(m3u8 = '', drmToken) {
const reg = /(\/drm\/)/g;
let tokenUrl = m3u8.replace(/http:/, 'https:');
tokenUrl = tokenUrl.replace(reg, `$1voddrm.token.${drmToken}.`);
return tokenUrl;
}Conclusion
Despite encountering several issues during the migration, all were resolved, resulting in higher upload success rates, faster transcoding, and a more secure playback experience. The improvements in data stability and user experience demonstrate the benefits of embracing cloud services.
Tencent IMWeb Frontend Team
IMWeb Frontend Community gathering frontend development enthusiasts. Follow us for refined live courses by top experts, cutting‑edge technical posts, and to sharpen your frontend skills.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.