How We Eliminated Video Stutter on a 3000‑User Learning Platform
This article details how a team tackled frequent video playback stutter on an internal learning platform by evaluating multiple player options, optimizing encoding parameters, adopting HLS streaming, and implementing a front‑end chunked upload workflow, ultimately reducing load times from several seconds to under one.
Background
In the internal learning platform "Zhuanzhuan School" more than 3000 employees watch training videos. Large MP4 files caused frequent playback stutter, especially during seeking, prompting a technical investigation.
Problem
Multiple users reported video lag, long loading (3‑5 s) and poor learning efficiency.
Solution Overview
The final solution combined a new player (Tencent Cloud TCPlayer), video‑parameter standardization, and HLS (m3u8) streaming. Three implementation options were evaluated; the simplest path—replace the H5 player with TCPlayer and serve videos as HLS—was adopted.
1. TCPlayer
TCPlayer provides high‑performance playback, support for MP4/FLV/HLS/M3U8, adaptive bitrate, cross‑platform APIs and full control over playback actions.
Integration example:
2. Video Parameter Optimization
Encoding settings were standardized to reduce file size and improve load speed:
Video bitrate – balance quality vs size.
Key‑frame interval – affects compression efficiency and seek performance.
Frame rate – smoother playback vs larger files.
Audio bitrate – 64 kbps (low‑bandwidth), 128 kbps (default), 192 kbps+ (high‑fidelity).
Audio sampling rate – 44.1 kHz (CD) or 48 kHz (broadcast).
All uploaded videos now pass through a conversion step using FFmpeg.
3. HLS Streaming
HLS splits a video into small .ts segments referenced by an .m3u8 playlist, enabling adaptive bitrate and faster initial loading. A 6‑minute, 290 MB MP4 demo loaded in several seconds, while the same video delivered as HLS loaded in under one second.
FFmpeg command used for conversion:
ffmpeg -i input.mp4 -hls_time 10 -hls_list_size 0 -y output.m3u8Resulting .ts segments are uploaded to cloud storage and the .m3u8 URL is returned to the front‑end.
4. Front‑end Chunked Upload (optional)
When large files are uploaded, a simple chunked upload can be used:
// Front‑end chunk upload
function chunkFile(file, chunkSize) {
const fileSize = file.size;
let offset = 0;
while (offset < fileSize) {
const chunk = file.slice(offset, offset + chunkSize);
uploadChunk(chunk);
offset += chunkSize;
}
}
function uploadChunk(chunk) {
const formData = new FormData();
formData.append('chunk', chunk);
fetch('/upload', {method: 'POST', body: formData})
.then(response => {/* handle */})
.catch(error => {/* handle */});
}
const fileInput = document.getElementById('file-input');
fileInput.addEventListener('change', () => {
const file = fileInput.files[0];
const chunkSize = 1024 * 1024; // 1 MB
chunkFile(file, chunkSize);
});Technical Pitfalls
License URL error – the basic web player requires an annual license; obtain a license to remove the warning.
Console error – upgrade tcplayer.js to version 5.1.0 to eliminate the message.
Pagination issue – destroying all player instances also removes videos sharing the same DOM ID. Resolve by forcing a template re‑render (toggle v‑if) on page change.
Result
After deployment, stutter reports ceased. Video load time dropped from 3‑5 seconds to under 1 second, significantly improving the learning experience.
大转转FE
Regularly sharing the team's thoughts and insights on frontend development
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.
