katspaugh / wavesurfer.js

Audio waveform player
https://wavesurfer.xyz
BSD 3-Clause "New" or "Revised" License
8.74k stars 1.62k forks source link

Can you instantiate a Wavesurfer with a MediaElement which is already playing, without interrupting its playback? #1704

Closed abrahamian closed 1 year ago

abrahamian commented 5 years ago

If an audio tag is already present on the page, can an instance of Wavesurfer be created to visualize that element's waveform (and subsequently control navigation/playback), but without reloading or otherwise interrupting the playback of the existing element?

My attempts so far have left me with the impression that, using the MediaElement backend, calling .load(mediaElement) forces the existing media element to reload and restart its playback. Is there any way around this, if the audio is already present and loaded?

Thanks for any help.

thijstriemstra commented 5 years ago

@abrahamian looks like this is your problem? https://github.com/katspaugh/wavesurfer.js/blob/master/src/mediaelement.js#L132 Can you comment that (and/or other relevant stuff in that method) out, check what happens?

thijstriemstra commented 5 years ago

yo @abrahamian, any feedback?

abrahamian commented 5 years ago

@thijstriemstra, I’m still working on this.

For context: My specific use case relies on another library (cassette) to instantiate the MediaElement and initiate playback. I’ve had some success implementing what I want by simply commenting out some lines of code (such as the one you referenced, and others that pause/unpause) in my fork of wavesurfer, but only in Chrome. In Firefox and Safari I get bugs that I am still working to understand.

will report back soon!

abrahamian commented 5 years ago

@thijstriemstra, I have pushed some changes to a branch in my fork of wavesurfer.js.

I've included a rudimentary example , in which a wavesurfer instance is created for an existing <video> element, which is ready and playing prior to wavesurfer initialization. You can run this example if you clone my branch enhancement/load_existing_media_element_without_playback_interruption , and run the development server.

I spent considerable time trying to include code that would look at the MediaElement, determine its 'readiness' state, and behave accordingly (avoiding calling load() on the element, and not messing with its playback state, if it was found to already be loaded/playing; otherwise follow the existing behaviour). I discovered this to be very challenging: attributes like networkState or readyState seem to be inconsistent across browsers. I also found that I couldn't leverage listening to loadedData or similar events, because in some cases the event listener would be attached too late.

Eventually I gave up on trying to do this. Thankfully, in the real-world use case for which I need this behaviour, I'm able -- thanks to the React library Cassette -- to take for granted that the MediaElement has loaded enough of the resource, before mounting a component that instantiates Wavesurfer.

Cassette makes it easy to have a global audio player in a React app. Used in combination with my fork of Wavesurfer, it's allowed me to build a Soundcloud-like user experience (something I've noticed a lot of people opening issues in this repo have been looking to do) where the playback of a waveform rendered at a specific route of a SPA isn't interrupted (this also optimized through careful caching of peaks data on the client-side) when the user leaves/returns to that route.

I could mock up an example of this (React, React Router, Cassette, Wavesurfer) stack in a JSFiddle if there is interest -- though this will take me some time.

vade commented 4 years ago

TL:DR

I am enabling and disabling audio tracks on a html 5 video Dom element interactively. I cant get wavesurfer to update the audio graph without reloading the source media and having the default tracks enabled. Does wavesurfer let me 'hot reload' the graph based on the state of a media element?


Hi all.

Firstly, thank you for Wavesurfer - its great and ive been able to very quickly do some fun things.

My current situation is such that I have a video element which contains multiple tracks in the container video mov / mp4. These are 'broadcast masters' from a major streaming provider and contain 20 tracks of AAC discrete mono audio channels. My web app toggles certain channels on and off for a 'quality control' reason (we listen to tracks in isolation).

My intent is to use wavesurfer.js to visualize the audio which is helpful to identify track assignment and encoding issues.

However, wavesurfer doesnt appear to have a facility to update the audio being previewed if the the active audio track of a video element is changed interactively. Is there a way to tell wavesurfer to not 'reload' the media - but to re-build /re-reference the video elements audio context?

Im by no means a web dev - I'm a multimedia engineer normally working on pro desktop apps in c / c++ so im admittedly out of my element - so forgive me if this is trivial.