VR360 Video Playback Demo
This example plays a 360° video whose view can be moved by mouse or touch. Use a real panoramic source: a monoscopic equirectangular video (ERP), commonly 2:1. erp360 is the SDK setting that turns on VR360 viewing; it cannot turn an ordinary flat video into a panorama.
The current public SDK includes VR360 APIs such as
set_projection(). If an older cached bundle does not expose them, update the SDK version. See VR360 Video Playback API for the complete contract.
1. Prepare the files
Put the SDK files and your 360° MP4 in this layout, then serve it over HTTP instead of opening file://. For a known source, download the self-generated VR360 H.264 + AAC test video as media/vr360.mp4. Other formats and FFmpeg live-publishing commands are on Test Media and FFmpeg.
demo/
├── index.html
├── media/vr360.mp4 ← replace with your monoscopic 360° video
└── output/
├── h265web.js
├── h265web_wasm.js
└── h265web_wasm.wasm2. Copy index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>VR360 playback demo</title>
<!-- The SDK JS and both WASM files must come from the same build. -->
<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="left">Look left</button>
<button id="right">Look right</button>
<button id="flat">Flat view</button>
<button id="vr">VR360 view</button>
<button id="sound">Enable sound</button>
<p id="status">Loading…</p>
<script>
const status = document.getElementById('status');
const playButton = document.getElementById('play');
const player = H265webjsPlayer();
// Bind callbacks before build() and load_media(). Ready means a frame exists, not that playback started.
player.on_ready_show_done_callback = () => {
playButton.disabled = false;
status.textContent = 'First frame ready. Press Play; the source may start with a black frame.';
};
player.on_error_callback = (error) => {
if (error.domain === 'vr' && error.fatal === false) {
// A VR-only failure can fall back to flat video; do not rebuild the decoder.
status.textContent = `VR360 unavailable; flat playback attempted: ${error.code}`;
return;
}
status.textContent = `Playback error: ${error.message || error.code}`;
};
// erp360 changes how a panorama is viewed; it does not convert the file.
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,
projection: 'erp360',
vr: {yaw: 0, pitch: 0, fov: 75, mouse_control: true, touch_control: true}
});
if (ok) {
player.set_voice(0); // Start muted, but keep audio available for the sound button.
player.load_media('./media/vr360.mp4'); // Replace with your 360° video URL.
} else {
status.textContent = 'Player build failed: check SDK paths and Console.';
}
playButton.onclick = () => player.play();
document.getElementById('pause').onclick = () => player.pause();
document.getElementById('left').onclick = () => player.rotate_vr_view({yaw: -30});
document.getElementById('right').onclick = () => player.rotate_vr_view({yaw: 30});
document.getElementById('flat').onclick = () => player.set_projection('flat');
document.getElementById('vr').onclick = () => player.set_projection('erp360');
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 autoplay off, press Play after the first frame is ready; some other sources may have a black first frame, which does not mean loading failed. A cross-origin video needs CORS permission for VR360. If you see VR_SOURCE_CORS, start with QA WIKI.
For a VR360 live stream, keep projection: 'erp360' and replace load_media('./media/vr360.mp4') with a live URL carrying real ERP frames, for example http://127.0.0.1/live/vr360.live.flv. The stream must actually contain 360° panoramic video. See the live playback demo for publishing and the WebRTC playback demo for WebRTC URLs.