VOD Playback Demo (MP4)
This is the common “MP4 URL → play, pause, seek” example. It uses automatic core selection, so you do not need to choose MSE, WebCodec or WASM first. Try a known-good MP4 before substituting your own file.
1. Prepare the files
Use this layout and serve it over HTTP. Download the self-generated ordinary H.264 + AAC test video as media/video.mp4, or use your own file; the code URL must match the real filename. See Test Media and FFmpeg for the VR360 and HEVC samples.
demo/
├── index.html
├── media/video.mp4 ← replace with your MP4
└── output/
├── h265web.js
├── h265web_wasm.js
└── h265web_wasm.wasmIf MP4 startup is slow, check moov placement and HTTP Range. To move the index without re-encoding, write a new file rather than overwriting the input:
ffmpeg -i ./media/video.mp4 -map 0 -c copy -movflags +faststart ./media/video-faststart.mp4A trailing moov does not always prevent playback; see QA WIKI for the full checks.
2. Copy index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>MP4 VOD demo</title>
<script src="./output/h265web.js"></script>
</head>
<body>
<div id="player"></div>
<button id="play" disabled>Play</button>
<button id="pause">Pause</button>
<button id="seek" disabled>Seek to 10 s</button>
<button id="sound">Enable sound</button>
<p id="status">Loading MP4…</p>
<script>
const mediaUrl = './media/video.mp4'; // Or use a reachable full HTTP(S) URL.
const status = document.getElementById('status');
const playButton = document.getElementById('play');
const seekButton = document.getElementById('seek');
const player = H265webjsPlayer();
// Bind callbacks before build() and load_media(). Ready does not auto-start playback.
player.on_ready_show_done_callback = () => {
playButton.disabled = false;
seekButton.disabled = false;
status.textContent = 'First frame ready. Press Play.';
};
player.video_probe_callback = (info) => console.log('Codec/duration info', info);
player.on_seek_done_callback = (seconds) => {
status.textContent = `Seeked to ${seconds.toFixed(1)} s`;
};
player.on_error_callback = (error) => {
status.textContent = `Playback error: ${error.message || error.code}`;
};
const ok = player.build({
player_id: 'player',
base_url: './output/',
wasm_js_uri: 'h265web_wasm.js',
wasm_wasm_uri: 'h265web_wasm.wasm',
width: '100%', height: 480,
auto_play: false, ignore_audio: false,
// No core field: let the SDK select a path for this file and browser.
});
if (ok) {
player.set_voice(0); // Start muted; enable sound after a user click.
player.load_media(mediaUrl);
} else {
status.textContent = 'Player build failed: check SDK file paths.';
}
playButton.onclick = () => player.play();
document.getElementById('pause').onclick = () => player.pause();
seekButton.onclick = () => player.seek(10); // Seconds; use a smaller value for short clips.
document.getElementById('sound').onclick = () => player.set_voice(1);
window.addEventListener('beforeunload', () => player.release());
</script>
</body>
</html>3. Open and troubleshoot
Run python3 -m http.server 8080 in demo/ and open http://localhost:8080/. With auto_play: false, press Play. If the first frame is ready but looks black, check whether the source begins with a black frame. If ready never fires, inspect the MP4 response status, type and Range in Network and consult QA WIKI.