oto icon indicating copy to clipboard operation
oto copied to clipboard

`player.IsPlaying()` returns false before hardware finishes playing

Open ZYDeng91 opened this issue 1 year ago • 4 comments

Oof, my audio keeps getting cut off before the last second.

If I guessed correctly, player.IsPlaying() does not account for the hardware and will return false once it has emptied its internal buffer. And makes my program exit prematurely.

Apart from sleeping a duration of BufferSize, is there any way to tell if the player really finished playing?

ZYDeng91 avatar May 29 '24 13:05 ZYDeng91

Unfortunately there is no way to detect whether the buffer that is sent to hardware is already played or not. Let me think...

hajimehoshi avatar May 29 '24 16:05 hajimehoshi

maybe guss duration of the buffer somehow and use time.Sleep? (I think its how all of us workaround that at the moment)

gucio321 avatar Jul 21 '24 09:07 gucio321

maybe guss duration of the buffer somehow and use time.Sleep

I think that's what I meant by "sleeping a duration of BufferSize". Was wondering how it can be done more elegantly upstream.

And uh, not really a workaround but setting the buffer size to default does it for me.

ZYDeng91 avatar Jul 21 '24 11:07 ZYDeng91

I think it would be interesting to have per-driver guesstimates about the hardware playback position. It could be interesting to figure out what AudioContext.currentTime does.

One idea, for example, is that ALSA works with periods. Say that at the moment when we just finished sending a period of audio to ALSA, and given that n periods are filled, we could make an assumption that at that time the speaker is playing sample number x. Using the samplerate we can extrapolate the sample number at later times. But keep updating the measurements.

Then if you need the hardware position of the player, just account for the player's buffer size in between.

This could later be expanded to allow other scheduling based playback.

I don't have time for it right now but I would be happy to make a POC for ALSA at some point, and maybe Windows.


I think it would be good to have a difference between player.IsPlaying() and player.HardwareIsPlaying() for different use-cases. If you call player.Play(), player.HardwareIsPlaying() will still return false for a number of milliseconds.

MarkKremer avatar Aug 10 '24 10:08 MarkKremer