Search code examples
javascriptreactjssafariogg

Using external library with React to play .ogg files in Safari


Good evening. I'm trying to implement playing ogg-opus audio in react app in Safari (it doesn't support .ogg format). I use create-react-app to init the project.

I've found "ogv.js" library, that is actually helps to play audio files in almost all modern browsers. But can't actually get it work (https://github.com/brion/ogv.js/issues/525).

I'm requring in the top of my PlayerComponent.js file after all the imports

var ogv = require('ogv');

After that in my play() function (it's being called from onClick event of a button) I'm trying to play an ogg file, that I'm recieving from API:

play = () => {
   var player = new OGVPlayer();
   var blob = new Blob([new Uint8Array(this.props.audioData)]);
   player.src = URL.createObjectURL(blob);
   player.play();
}

I'm getting the below error:

ogv-demuxer-ogg-wasm.js?version=1.6.0-20190226222001-c4648f0:1 Uncaught SyntaxError: Unexpected token ogv.js:1586 Uncaught TypeError: n[e] is not a function at classWrapper (ogv.js:1586) at ogv.js:4593 at ogv.js:1590 at ogv.js:207 at Array.forEach () at HTMLScriptElement.done (ogv.js:206)

Probably the problem is that some library files and especially 'ogv-demuxer-ogg-wasm.js' can't be loaded properly.

Any help would be helpful, maybe someone has a solution to play .ogg files in Safari in other way. Thanks!

[UPDATED] Solution found, check it down below.


Solution

  • Okay, so if anyone would ever want to play in React app .ogg/opus audio in Safari, here is the solution (using ogv.js library).

    First of all, put the library files to your React app. For the opus you will need:

    • ogv-demuxer-ogg.js
    • ogv-demuxer-ogg-wasm.js
    • ogv-demuxer-ogg-wasm.wasm
    • ogv-decoder-audio-opus.js
    • ogv-decoder-audio-opus-wasm.js
    • ogv-decoder-audio-opus-wasm.wasm
    • ogv-worker-audio.js

    After that in your code:

    Require the lib after all imports:

    var ogv = require('ogv');
    

    Set the base path for the files from the PUBLIC folder:

    // process.env.PUBLIC_URL simply a ref for the root folder of the react app
    ogv.OGVLoader.base = process.env.PUBLIC_URL + '/ogv'; 
    

    Then you can use it as follows:

    play = () => {
       var player = new OGVPlayer();
       // this.props.audioData just some audio data
       var blob = new Blob([new Uint8Array(this.props.audioData)]);
       player.src = URL.createObjectURL(blob);
       player.play();
    }
    

    This player has some similar to default HTML5 Audio abilities, for more you can check it in the link above.

    Maybe not the best solution, but at least it works :)