Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gapless playback #31

Open
2 tasks
martpie opened this issue Sep 11, 2015 · 18 comments
Open
2 tasks

Gapless playback #31

martpie opened this issue Sep 11, 2015 · 18 comments

Comments

@martpie
Copy link
Owner

martpie commented Sep 11, 2015

What

  • Reduce sound interuption between two songs

Currently, when a song is over, the src of the audio tag is changed, but the tag has to preload the file a bit. So there is a micro interruption of a few miliseconds.

  • Crossfading option between song ?

How

Instead of having a single Audio object, need to have an array of 3: [previous, current, next]. Then when playing next or previous, it should be faster, cause tracks will already be loaded + Pop/Shift audio when needed. not working :[

@martpie martpie changed the title Try to reduce sound interuption between two songs Improve tracks transitions Jan 11, 2016
@martpie martpie modified the milestones: 0.6, 1.0 Jul 6, 2016
@martpie
Copy link
Owner Author

martpie commented Jul 6, 2016

This could be done by using an array of Audio objects, less dirty than only two audio tags

@martpie martpie modified the milestones: 0.7, 1.0 Jul 26, 2016
@martpie
Copy link
Owner Author

martpie commented Aug 2, 2016

I might consider a switch to Web Audio API instead of the current Audio element implementation. Might be a first step to #114

@YurySolovyov
Copy link
Collaborator

I wonder if it is enough to have 2 elements - current + next.
We can start playing audio on next element, and when current track is over, we just swap pointers, to next becomes new current and we allocate a new next.

@martpie
Copy link
Owner Author

martpie commented Aug 3, 2016

The problem is the next sont can be the previous one. I've done some test, and there's still a microcut between the ended event and the next track play start. As mentioned, I think I'll switch to the Web Audio API with an AudioContext, but it's a huge work, and I don't know well this API.

@YurySolovyov
Copy link
Collaborator

The problem is the next song can be the previous one.

I still don't quite get why this is a problem.

there's still a microcut between the ended event and the next track play start

As I understand, if we have say 1000ms overlap/crossfading duration, we should not worry about these conks of microcuts, because transition period is still much longer.

@martpie
Copy link
Owner Author

martpie commented Aug 4, 2016

I still don't quite get why this is a problem

You need to preload three songs: the current one, the next one, and the previous one. If they are preloaded, then the microcute should be smaller.

As I understand, if we have say 1000ms overlap/crossfading duration, we should not worry about these conks of microcuts, because transition period is still much longer.

Yes sure, but what if there is a 0ms crossfade (the user will be able to choose a value), there would still be one ;)

@martpie martpie removed this from the 0.7 milestone Aug 9, 2016
@martpie martpie mentioned this issue Sep 21, 2016
18 tasks
@martpie
Copy link
Owner Author

martpie commented Mar 3, 2019

https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/audioTracks

Trough an experimental flag though :/

@DrEVILish
Copy link

Could you not have an array
var nowPlaying = ['previous','current','next']
of which you can
nowPlaying.shift() the first element out, once the current song has finished playing.
nowPlaying.push(nextTrack) the next song to play onto the end of the array.

This should always leave the previous track as nowPlaying[0], Current playing as nowPlaying[1] and next track nowPlaying[2].

probably won't work knowing me :D

@martpie
Copy link
Owner Author

martpie commented May 30, 2019

I tried it, the result is unfortunately the same, there's still a mini-gap :(

@DrEVILish
Copy link

I tried it, the result is unfortunately the same, there's still a mini-gap :(

I'd not realised the mini-gap before :( just played War of the Worlds and there it was...

@DrEVILish
Copy link

A gapless JavaScript/CSS audio player for HTML5

PROBLEM: There are 2 modern APIs for playing audio through the web, and both of them have problems:

  • HTML5 Audio: the last chunk of audio gets cut off, making gapless transitions impossible
  • WebAudio: can't play a file until it's fully loaded

SOLUTION: Use both!

  • If WebAudio hasn't fully loaded yet, it begins playback with HTML5 Audio, then seamlessly switches to WebAudio once loaded.
  • NOTE: Most mobile browsers don't fully support HTML5 Audio objects in js, so we're stuck with only WebAudio in that case.

http://github.com/regosen/Gapless-5
Might be able to replace the whole player engine with a single JS app. Designed for browser-based usage.

@DrEVILish
Copy link

Just tested this in chrome and the gap is still there but it's a lot lot smaller.
It still does this weird click.

@DrEVILish
Copy link

DrEVILish commented Jun 20, 2019

This project looks interesting:
https://github.com/astoeckel/opus_gapless/
which is bundled into
https://github.com/astoeckel/http_audio_server

It currently triggers an FFmpeg process upon a single audio file and streams it into OPUS blocks.

https://somweyr.de/opus/demo.html -> Demo of actual different tracks being played back gaplessly.

Using the Electron client purely as an Open stream connected to an application that pulls each file and blockifys each file into a folder, this means the process can become multithreaded transcoding the previous.
Each block can be continually streamed out to the client one after the other.
As each block would have a crossfade between it and the previous one, we can have that as a client setting that would set the size of the overlap of each block.

If each block contains only 2seconds worth of data could a crossfade be longer than the length of a block?

@martpie martpie changed the title Improve tracks transitions Gapless playback Sep 5, 2019
@martpie
Copy link
Owner Author

martpie commented Sep 5, 2019

@s0
Copy link

s0 commented Feb 24, 2020

I've been playing around with the WebAudio API in Musseks for a slightly different reason (accurate timestamps for synchronizing audio with lighting with my synesthesia project), which it turned out the HTML <audio> tag was insufficient for (see https://github.com/synesthesia-project/synesthesia/tree/master/precise-audio). I'd be willing to attempt implementing gapless playback in Museeks using web audio, though I cannot provide a timescale.

@s0
Copy link

s0 commented Feb 24, 2020

This is also a useful article: http://dalecurtis.github.io/llama-demo/index.html

@martpie
Copy link
Owner Author

martpie commented Feb 24, 2020

@s0 great to hear! #128 is a blocker for that though. I really want to solve this so I will try to find myself some time to work on AudioContext.

I would also like to try https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement/audioTracks as maybe Gapless playback comes baked in.

@s0
Copy link

s0 commented Mar 13, 2020

Made progress with updating my precise-audio library for gapless playback with a small POC in the browser. Seems to work relatively well in chrome when playing LAME encoded MP3 files:

After I've tightened up the library a bit more, I'll work on pulling the functionality into museeks, and hopefully open a PR soon.

s0 added a commit to s0/museeks that referenced this issue Mar 15, 2020
PreciseAudio provides an API for gapless playback, and presents
mostly the same interface as Audio, so switching to this library
didn't require too many changes, and paves the way for martpie#31

PreciseAudio also uses an AudioContext internally,
and makes the audio graph available for mutation via
getAudioNodes(), which will allow for features such as
equalizers (martpie#127) or visualizers / analyzers.

Fixes martpie#128
s0 added a commit to s0/museeks that referenced this issue Mar 15, 2020
Use the gapless API from PreciseAudio to enable gapless playback.
Most of the work is done in the player reducer, to ensure that
PreciseAudio has the latest queue whenever a state change happens
to either the queue or the player.

Fixes martpie#31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants