Ogv.js
JavaScript media player using Ogg/Vorbis/Theora/Opus/WebM libs compiled with Emscripten
Install / Use
/learn @bvibber/Ogv.jsREADME
ogv.js
Media decoder and player for Ogg Vorbis/Opus/Theora and WebM VP8/VP9/AV1 video.
Based around libogg, libvorbis, libtheora, libopus, libvpx, libnestegg and dav1d compiled to JavaScript and WebAssembly with Emscripten.
Updates
2.0.0 - 202?-??-??
- All libraries using stock source and 128-bit autovectorization
- Requires modern browsers with BigInt, SIMD etc
- Multithreaded versions available experimentally
- using SharedArrayBuffer requires special opt-in HTTP headers
- see
threaded.phpin the demo
Internal updates:
- Bump emscripten compatibility to 4.0.19
- internal API restructuring
- file restructuring
- es6 only
- uses BigInt 64-bit ABI
- updated codec library releases
- dav1d 1.5.2
- libvpx 1.15.2
- ogg 1.3.6
- opus 1.5.2
- vorbis 1.3.7
- theora 1.2.0
1.8.10 - 2022-??-??
- Bump emscripten compatibility to 3.1.17
1.8.9 - 2022-04-06
- Bump yuv-canvas to 1.2.11, further perf improvments for frame drawing
- Workaround gets audio working when ringer is disabled by iOS hardware switch
1.8.8 - 2022-04-04
- Bump yuv-canvas to 1.2.10, fixes WebGL scaling bug in Netscape/macOS; adjustment to prior performance tweaks.
1.8.7 - 2022-03-29
- Bump emscripten compatibility to 3.1.8
- Bump Opus to 1.3.1
- Bump yuv-canvas to 1.2.9, fixes WebGL performance regressions on some browsers
- experimental demo/threaded.php provides a COOP-COEP-CORP environment for testing threaded decoders (top-level frame and all worker JS must opt in to COOP-COEP; CORP or CORS required for most loaded resources)
1.8.6 - 2022-01-12
- Bump to yuv-canvas
- Fix demo for removal of video-canvas mode
1.8.5 - 2022-01-11
- Remove unnecessary user-agent checks
- Remove flaky, obsolete support for faking CSS
object-fit - Remove experimental support for streaming
<canvas>into<video>
1.8.4 - 2021-07-02
- Fix for fix for OGVLoader.base fix
1.8.3 - 2021-07-02
- Fixes for build with emscripten 2.0.25
- Fix for nextTick/setImmediate-style polyfill in front-end
- Provisional fix for OGVLoader.base not working with CDNs
- the fallback code for loading a non-local worker had been broken with WebAssembly for some time, sorry!
1.8.2 - errored out
1.8.1 - 2021-02-18
- Fixed OGVCompat APIs to correctly return false without WebAssembly and Web Audio
1.8.0 - 2021-02-09
- Dropping IE support and Flash audio backend
- Updated to stream-file 0.3.0
- Updated to audio-feeder 0.5.0
- The old IE 10/11 support no longer works due to the Flash plugin being disabled, and so is being removed
- Drop es6-promise shim
- Now requires WebAssembly, which requires native Promise support
- Build & fixes
- Demo fixed (removed test files that are now offline)
- Builds with emscripten 2.0.13
- Requires latest meson from git pending a fix hitting release
See more details and history in CHANGES.md
Current status
Note that as of 2021 ogv.js works pretty nicely but may still have some packagine oddities with tools like webpack. It should work via CDNs again as of 1.8.2 if you can't or don't want to package locally, but this is not documented well yet. Improved documentation will come with the next major update & code cleanup!
Since August 2015, ogv.js can be seen in action on Wikipedia and Wikimedia Commons in Safari and IE/Edge where native Ogg and WebM playback is not available. (See technical details on MediaWiki integration.)
See also a standalone demo with performance metrics at https://brooke.vibber.net/misc/ogv.js/demo/
- streaming: yes (with Range header)
- seeking: yes for Ogg and WebM (with Range header)
- color: yes
- audio: yes, with a/v sync (requires Web Audio or Flash)
- background threading: yes (video, audio decoders in Workers)
- GPU accelerated drawing: yes (WebGL)
- GPU accelerated decoding: no
- SIMD acceleration: no
- Web Assembly: yes (with asm.js fallback)
- multithreaded VP8, VP9, AV1: in development (set
options.threadingtotrue; requires flags to be enabled in Firefox 65 and Chrome 72, no support yet in Safari) - controls: no (currently provided by demo or other UI harness)
Ogg and WebM files are fairly well supported.
Goals
Long-form goal is to create a drop-in replacement for the HTML5 video and audio tags which can be used for basic playback of Ogg Theora and Vorbis or WebM media on browsers that don't support Ogg or WebM natively.
The API isn't quite complete, but works pretty well.
Compatibility
ogv.js requires a fast JS engine with typed arrays, and Web Audio for audio playback.
The primary target browsers are (testing 360p/30fps and up):
- Safari 6.1-12 on Mac OS X 10.7-10.14
- Safari on iOS 10-11 64-bit
Older versions of Safari have flaky JIT compilers. IE 9 and below lack typed arrays, and IE 10/11 no longer support an audio channel since the Flash plugin was sunset.
(Note that Windows and Mac OS X can support Ogg and WebM by installing codecs or alternate browsers with built-in support, but this is not possible on iOS where all browsers are really Safari.)
Testing browsers (these support .ogv and .webm natively):
- Firefox 65
- Chrome 73
Package installation
Pre-built releases of ogv.js are available as .zip downloads from the GitHub releases page and through the npm package manager.
You can load the ogv.js main entry point directly in a script tag, or bundle it through whatever build process you like. The other .js files must be made available for runtime loading, together in the same directory.
ogv.js will try to auto-detect the path to its resources based on the script element that loads ogv.js or ogv-support.js. If you load ogv.js through another bundler (such as browserify or MediaWiki's ResourceLoader) you may need to override this manually before instantiating players:
// Path to ogv-demuxer-ogg.js, ogv-worker-audio.js, etc
OGVLoader.base = '/path/to/resources';
To fetch from npm:
npm install ogv
The distribution-ready files will appear in 'node_modules/ogv/dist'.
To load the player library into your browserify or webpack project:
var ogv = require('ogv');
// Access public classes either as ogv.OGVPlayer or just OGVPlayer.
// Your build/lint tools may be happier with ogv.OGVPlayer!
ogv.OGVLoader.base = '/path/to/resources';
var player = new ogv.OGVPlayer();
Usage
The OGVPlayer class implements a player, and supports a subset of the events, properties and methods from HTMLMediaElement and HTMLVideoElement.
// Create a new player with the constructor
var player = new OGVPlayer();
// Or with options
var player = new OGVPlayer({
debug: true,
debugFilter: /demuxer/
});
// Now treat it just like a video or audio element
containerElement.appendChild(player);
player.src = 'path/to/media.ogv';
player.play();
player.addEventListener('ended', function() {
// ta-da!
});
To check for compatibility before creating a player, include ogv-support.js and use the OGVCompat API:
if (OGVCompat.supported('OGVPlayer')) {
// go load the full player from ogv.js and instantiate stuff
}
This will check for typed arrays, web audio, blacklisted iOS versions, and super-slow/broken JIT compilers.
If you need a URL versioning/cache-buster parameter for dynamic loading of ogv.js, you can use the OGVVersion symbol provided by ogv-support.js or the even tinier ogv-version.js:
var script = document.createElement('script');
script.src = 'ogv.js?version=' + encodeURIComponent(OGVVersion);
document.querySelector('head').appendChild(script);
Distribution notes
Entry points:
ogv.jscontains the main runtime classes, including OGVPlayer, OGVLoader, and OGVCompat.ogv-support.jscontains the OGVCompat class and OGVVersion symbol, useful for checking for runtime support before loading the mainogv.js.ogv-version.jscontains only the OGVVersion symbol.
These entry points may be loaded directly from a script element, or concatenated into a larger project, or otherwise loaded as you like.
Further code modules are loaded at runtime, which must be available with their defined names together in a directory. If the files are not hosted same-origin to the web page that includes them, you will need to set up appropriate CORS headers to allow loading of the worker JS modules.
Dynamically loaded assets:
ogv-worker-audio.jsandogv-worker-video.jsare Worker entry points, used to run video and audio decoders in the background.ogv-demuxer-ogg-wasm.js/.wasmare used in playing .ogg, .oga, and .ogv files.ogv-demuxer-webm-wasm.js/.wasmare used in playing .webm files.ogv-decoder-audio-vorbis-wasm.js/.wasmandogv-decoder-audio-opus-wasm.js/.wasmare used in playing both Ogg and WebM files containing audio.ogv-decoder-video-theora-wasm.js/.wasmare used in playing .ogg and .ogv video files.ogv-decoder-video-vp8-wasm.js/.wasmandogv-decoder-video-vp9-wasm.js/.wasmare used in playing .webm video files.*-mt.js/.wasmare the multithreaded versions of some of the above modules. They have additional support files.
If you know you will never use particular formats or codecs you can skip bundling them; for instance if you only need to play Ogg files you don't need ogv-demuxer-webm-wasm.js or ogv-decoder-video-vp8-wasm.js which are only used for WebM.
Performance
(This section is somewhat out of date.)
As of 2015, for SD-or-less resolution basic Ogg Theora decoding speed is reliable on desktop and newer high-end mobile devices; current high-end desktops and laptops
