bvibber / ogv.js

JavaScript media player using Ogg/Vorbis/Theora/Opus/WebM libs compiled with Emscripten
https://brooke.vibber.net/misc/ogv.js/demo/
Other
1.19k stars 99 forks source link

Issues with audio recorded with HTML5 audio recorder #530

Open AndreSteenbergen opened 4 years ago

AndreSteenbergen commented 4 years ago

I have recorded audio/webm;codec=opus using firefox and also testing in chrome. In firefox I can't seem to seek, duration seems infinite and after playback the position is not reset to the start. Error: Cannot seek a non-seekable stream

I recorded using react-mic, and the source is a bloburl. The issue does not occur when I use the regular html5 audio tag.

Chrome does reset the stream after onended is called. But duration is infinite as well. Am I doing something wrong?

AndreSteenbergen commented 4 years ago

When I choose to record to audio/ogg I do get a duration in google chrome; still no duration in firefox; and also no reset of currentTime

AndreSteenbergen commented 4 years ago

Tried some more debugging, but I can't seem to figure out what is going on. I attached an image showing the stream is not seekable; I would have assumed audio/ogg is seekable.

image

bvibber commented 4 years ago

I believe not all browsers allow using a faux HTTP Range header on XMLHttpRequest to blob URIs, which would prevent seeking. (The native audio element has no such limitation because it can get at the underlying resource.)

For Ogg, seeking is required to get the duration unless it's specified in skeleton header data (which is unlikely for audio, but possible).

Note that Safari does support range requests on blob URIs, so if you're using ogv.js as a Safari compatibility shim it should work there.

If you for some reason need to use ogv.js in Chrome and Firefox too, a possible but ugly workaround is to create a custom StreamFile-compatible object that chops up the blob with blob.slice() to read chunks, and setting that as options.stream instead of using URL.createObjectURL() and passing that into the src attribute.

Unfortunately I'm not sure I can make that transparent as there's no way I know of to get the original Blob back from the URL string; there may be though that I just haven't realized yet. :)

AndreSteenbergen commented 4 years ago

Ah ok, thanks. I do have the original blob. But I guess I will do things more simple ;)

getAudioPlayer(recording) {
    let player = new Audio;
    let elementCanPlayType = player.canPlayType(recording.options.mimeType);
    if (!elementCanPlayType) {
      player = new ogv.OGVPlayer();
    }

    player.src = recording.blobURL;
    player.type = recording.options.mimeType;

    player.ontimeupdate = (evt) => {      
      this.setState( {
        currentTime : player.currentTime,
        duration : player.duration
      } );
    }

    player.onended = () => this.stopAudio();
    return player;
  }