1. Insert a container and mount an OGV-style player
Code:
<div id="player">
Result:
Source
Waiting for player
Rendering target
Canvas, not native video chrome
Debug
Enabled
2. Canvas playback avoids manufacturer video overlays
Code:
<div class="player-shell">
<canvas id="canvasDecode" width="667" height="375"></canvas>
<div class="comment-layer">
<span class="bullet">Bullet comments stay visible</span>
<span class="bullet">No forced fullscreen button</span>
<span class="bullet">Canvas is just normal page content</span>
</div>
</div>
<button id="canvasToggle">Pause</button>
Result:
Bullet comments stay visible
No forced fullscreen button
Canvas is just normal page content
Article problem
Some Android browsers add native floating buttons over video.
ogv.js idea
Decode frames in JavaScript and paint them into canvas.
3. Native video can have a different compatibility result
Code:
<div class="player-shell">
<div class="video-sim">
<strong>Native <video> WebM test</strong>
<span id="nativeMessage">Choose a device profile.</span>
</div>
<div class="native-overlay">
<span class="native-badge">DL</span>
<span class="native-badge">FULL</span>
</div>
</div>
<select id="deviceProfile">
<option value="iphone">iPhone Safari / WeChat</option>
<option value="newAndroid">New Android browser</option>
<option value="oldAndroid">Older Android browser</option>
</select>
Result:
Native <video> WebM test
Choose a device profile.
Choose a device profile.
Native result
Waiting
Canvas decoder result
Waiting
4. Fall back when WebAssembly is unavailable
Code:
function choosePlaybackMode(hasWebAssembly) {
if (hasWebAssembly) {
return {
mode: 'ogv.js canvas decoder',
detail: 'Use JavaScript/WebAssembly decoding for WebM.'
};
}
return {
mode: 'native <video> fallback',
detail: 'Avoid the decoder and let the browser try normal playback.'
};
}
var support = document.getElementById('wasmSupport');
var output = document.getElementById('fallbackOutput');
support.addEventListener('change', function () {
var result = choosePlaybackMode(support.checked);
output.innerHTML = '<strong>' + result.mode + '</strong><br>' + result.detail;
});
Result:
The article suggests falling back to the native video element when the device cannot support the decoder path.
5. Build the player controls yourself
Code:
<div class="manual-player">
<div class="player-shell">
<canvas id="manualCanvas" width="667" height="375"></canvas>
</div>
<div class="control-bar">
<button id="manualPlay" class="primary">Play</button>
<button id="manualPause">Pause</button>
<div class="timeline">
<span class="time-text" id="currentTime">0:00</span>
<input id="seekBar" type="range" min="0" max="100" value="0">
<span class="time-text">0:20</span>
</div>
</div>
</div>
Result:
6. Compare the format tradeoff
Code:
var formatSelect = document.getElementById('formatSelect');
var formatOutput = document.getElementById('formatOutput');
var formatNotes = {
webm: 'WebM is open and royalty-free. With ogv.js, it can become playable on iPhone through canvas decoding.',
mp4: 'MP4 has the broadest practical support, so it is still the simplest default choice for many products.',
hevc: 'HEVC/H.265 can be very compact, but browser support is uneven and often Safari-centered.'
};
formatSelect.addEventListener('change', function () {
formatOutput.innerHTML = '<strong>' + formatSelect.value.toUpperCase() + '</strong><br>' + formatNotes[formatSelect.value];
});
Result: