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

Video delay, and visualisations (and playback speed) #750

Closed
RJVB opened this issue Jul 9, 2024 · 25 comments
Closed

Video delay, and visualisations (and playback speed) #750

RJVB opened this issue Jul 9, 2024 · 25 comments

Comments

@RJVB
Copy link
Contributor

RJVB commented Jul 9, 2024

I just noticed that visualisations do not take the configured delay into account, causing a noticeable lag when listening over my BT speaker. It's a nice speaker for the place it's in (Klipsch The One Mk2) but it uses the basic audio codec, so I have to set a "video delay" (it's actually a transport delay of course) of +0.3 seconds.

More importantly, I wonder if there's something that can be done to improve the experience at the beginning.

  • In videos where the sound track plays at frame 0 it sounds as if a tiny bit of sound gets lost when first starting the video
  • Curiously, the video always starts first

That latter symptom is something I cannot really get my head around when the correct transport has been set, and if I were to guess I'd say that this initial bit of "silent movie" is actually longer than those 0.3 seconds.

EDIT: something strange goes on when reducing playback speed, regardless of whether this is done keeping the audio pitch constant or not. At 0.75x speed I need to configure a transport delay of about 0.1 seconds only, and at 0.5x it has to be set to 0.
It looks like speeding up the playback doesn't require changing the transport delay though of course it becomes increasingly difficult to detect sync issues.

@RJVB RJVB changed the title Video delay, and visualisations Video delay, and visualisations (and playback speed) Jul 11, 2024
@zaps166
Copy link
Owner

zaps166 commented Jul 11, 2024

Bluetooth speakers has variable audio latency - depends on codec and on signal strength - low signal might increase latency because of larger buffer to prevent audio stuttering (and also can lower the bitrate).

Use cable whenever possible (many BT speakers has JACK input). With cable you're always full quality, lowest and fixed latencies and you can see your "signal" range.

Visualizations doesn't respect video latency - I don't want to buffer it there and complicate things. It's not video anyway 😄

About playback speed - I don't know, but I think when speed is too low, the latency doesn't matter that much. When speed is too high, you should still hear the latency. Also rubberband filter has latency, but it should be implicitly added to video delay.

@RJVB
Copy link
Contributor Author

RJVB commented Jul 12, 2024

Use cable whenever possible (many BT speakers has JACK input). With cable you're always full quality, lowest and fixed latencies and you can see your "signal" range.

Well, DOH, but a cable isn't always feasible, is it. Can't just span one the middle of a (kitchen) table across the space to where my speaker sits...

Visualizations doesn't respect video latency - I don't want to buffer it there and complicate things. It's not video anyway 😄

For visualisations it's one thing, for the FFT spectrum another, IMHO. I don't know how you implemented the former, but I suspect you have to buffer for the latter anyway.

About playback speed - I don't know, but I think when speed is too low, the latency doesn't matter that much.

I don't see how that could make sense, unless the slowing down introduces its own delay w.r.t. the audio. Which might be the case since there is indeed a noticeable sync problem when I play the audio of a slowed-down video over the builtin speakers.

When speed is too high, you should still hear the latency. Also rubberband filter has latency, but it should be implicitly added to video delay.

Is the rubberband filter always in the loop, with just an on/off switch to determine whether it does something to pitch? Because that noticeable sync problem mentioned above is there whether I keep audio pitch constant or not.

I think I had actually noticed it before, as the slowed-down playback isn't as helpful in figuring out what musicians are doing with their hands (which is what I hoped to use the constant-pitch feature for).

I'm attaching the audio/video sync test I use - and just FWIW: visualisations and FFT appear to be completely out of sync with the audio for me.

Audio.Video.Sync.Test.60.FPS.mp4

@zaps166
Copy link
Owner

zaps166 commented Jul 12, 2024

For me this video plays perfect in QMPlay2 regardless of keep pitch and playback speed (using PC's sound card and pipewire).

Is the rubberband filter always in the loop, with just an on/off switch to determine whether it does something to pitch?

Rubberband filter is running only when your playback speed != 1.0 and you have keep pich enabled. Otherwise it's unused, resources are freed.

visualisations and FFT appear to be completely out of sync with the audio for me.

How about video? As I told before - video delay parameter doesn't work in visualizations .

For visualisations it's one thing, for the FFT spectrum another, IMHO.

What do you mean? The only buffer there is to grab enough samples to display and/or calculate FFT. They should display at same time (I mean some milliseconds doesn't matter like 1-2x screen refresh rate or so).

@RJVB
Copy link
Contributor Author

RJVB commented Jul 12, 2024 via email

@RJVB
Copy link
Contributor Author

RJVB commented Jul 13, 2024 via email

@zaps166
Copy link
Owner

zaps166 commented Dec 11, 2024

Notes about Bluetooth audio: yes, this method has variable audio latency (depends on devices, codec used, signal strength). You can compensate it manually for video playback in QMPlay2, but not for visualizations. Visualizations in QMPlay2 doesn't have additional buffering, so it's impossible. Adding this is possible, but too much work and too much code for this use-case. Sorry, I can't complete every feature request 😞

Also bluetooth audio latency can change at "random" in some cases, so you'll have to compensate it again manually.


Once I had two Bluetooth mono speakers (no JACK cable input...) and I wanted to use them as stereo. After manual latency synchronization between them (in PipeWire), they played quite well. After some time they desynced and echo appeared again.

@zaps166 zaps166 closed this as completed Dec 11, 2024
@RJVB
Copy link
Contributor Author

RJVB commented Dec 12, 2024 via email

@zaps166
Copy link
Owner

zaps166 commented Dec 12, 2024

Hmm. I experience it on HDMI when HDMI is in... power-saving mode? One it wakes-up, it plays normally, but usually I lost begin of audio. Maybe same with bluetooth? Is your issue related to QMPlay2 or it's a general issue?

@RJVB
Copy link
Contributor Author

RJVB commented Dec 12, 2024 via email

@zaps166
Copy link
Owner

zaps166 commented Dec 12, 2024

QP2 playback uses an "ALSA Plugin"

I think for PulseAudio you should use PulseAudio plugin. ALSA is for hw: or when use use their dmix (no need to use ALSA API to pass audio to PulseAudio - I think better directly).

I'm still using Pulseaudio

I forgot about it long time ago and my sound issues are gone with PipeWire.

the 1st note swells into existence after a short initial silence. When I just start the playback with +0.3s latency it starts abruptly, also when I stop and restart the video so nothing is supposedly gone into standby. But when I just drag the cursor back to the beginning I do hear that initial silence and the swelling of the note.

Exactly same here on HDMI regardless of player used. I noticed that the latency when audio starts to be hear depends on connected hardware (sometimes is 1 second, sometimes more). I rarely use HDMI, so workaround is unknown so far. If you add additional latency via pavucontrol, you simply has more time to "wait" for the audio device to be ready to output sound. I still don't know if it's hardware issue or driver issue.

@zaps166
Copy link
Owner

zaps166 commented Dec 14, 2024

it certainly doesn't interfere with QMplay2's correction

QMPlay2 corrects A/V sync only.


You need to add about 0.5 seconds silence on playback start (when your audio device is open or resumed) to workaround hardware/driver issue.

@RJVB
Copy link
Contributor Author

RJVB commented Dec 15, 2024 via email

@zaps166
Copy link
Owner

zaps166 commented Dec 15, 2024

Still, after some more testing right now it does seem like the PA latency offset is to blame?!

Latency in pavucontrol shouldn't be used for your issue. It may generate other issues.


Found solution, it's here for PipeWire with WirePlumber >= 0.5.0.

You shouldn't set it for all devices, just set for your device (you can use pw-top to obtain the name) or maybe set the config for bluetooth devices only. pw-top will show you is it suspends or not.

My config for HDMI (~/.config/wireplumber/wireplumber.conf.d/51-disable-suspension.conf):

monitor.alsa.rules = [
  {
    matches = [
      {
        node.name = "~alsa_output.*.hdmi*"
      }
    ]
    actions = {
      update-props = {
        session.suspend-timeout-seconds = 0
      }
    }
  }
]

Your first audio playback in system will be cut, but every other will not cut the sound.

@RJVB
Copy link
Contributor Author

RJVB commented Dec 15, 2024 via email

@zaps166
Copy link
Owner

zaps166 commented Dec 15, 2024

Meanwhile, my BT device is seen as a USB DAC by the system, and the LEDs on it go a bit duller after about 5 seconds of not receiving any signal.

Yes, this is probably the reason why you can't hear begin of the audio - the device is waking-up from sleep. If it's a USB DAC, just set node.name according to what pw-top sees on your device.

Also, I can reproduce the issue with the internal sound device too. Not for small latency offsets nor for long ones >= 900ms or so, so it's not something like a glitch in a different code path that's taken when lat.offset!=0 .

🤔 Don't understand.

Sorry, I can't make sense of that. You mean the 1st time I play audio, or the 1st device in the list?

I mean - when you start any playback on your device when suspend is disabled in PipeWire - the device will not go sleep anymore, so it'll work. However the device has to be accessed at least once to wake-up, so first audio you play after device connection or PC boot - begin of the audio will not be emited (only once).


Also you can try (not working for HDMI to me):

echo 0 | sudo tee /sys/module/snd_hda_intel/parameters/power_save
echo 0 | sudo tee /sys/module/snd_hda_intel/parameters/power_save_controller

@RJVB
Copy link
Contributor Author

RJVB commented Dec 15, 2024 via email

@zaps166
Copy link
Owner

zaps166 commented Dec 15, 2024

You don't understand my words or what I describe?

On your internal sound - are you adding latency offset in pavucontrol? Do you have any issues when you don't add any latency in pavucontrol?

I'm not convinced, because I can see the device wake up while QMPlay2 still seems to be starting the playback. There may be the tiniest bit of an artefact when I start playback from the standby state without latency correction but it's definitely more pronounced when there is a latency correction.

I don't know, I can't see/touch this 😄 Maybe it's waiting and after this still not playing from the begin. I have only HDMI, same behavior (all applications, not only QMPlay2). Sometimes it "cuts" 1 sec of audio, sometimes 4 sec of audio...

Would it be an invasive change to open the configured audio channel (and send "something" into it?) as soon as the user hits play, if that's not already being done? That might fix or alleviate the issue in >75% of the cases. And I'm guessing the same issue will exist on platforms where you can't configure suspension like you showed for pipewire

I don't know how long the silence must be sent - it depends on hardware/driver. Also it must be send on every resume from pause, because I don't know when device really suspends (maybe can ask PipeWire for suspend time, but it's not universal way and much more complicated). And finally it'll be done for QMPlay2 only, other software will still have this problem.

If you just push 1 sec silence before first audio write, QMPlay2 will discard begin on audio due to video sync.

@RJVB
Copy link
Contributor Author

RJVB commented Dec 15, 2024 via email

@zaps166
Copy link
Owner

zaps166 commented Dec 15, 2024

Even if you pretend the video also starts with the same duration of something else - say a dissolve effect of the rest screen?

Video needs to be informed about it somehow. Need to look at code, don't remember (also it's very old code).

except on MSWin when I use Foobar2000 for audio

😄

But isn't there a way to keep the device from suspending when playback is paused?

PipeWire metod as I gave you before (also PulseAudio can do this).

QMPlay2 - need to play silence all the time when paused.


Alternative - play silence somewhere in background process all the time - it'll never suspend.

@RJVB
Copy link
Contributor Author

RJVB commented Dec 19, 2024 via email

@zaps166
Copy link
Owner

zaps166 commented Dec 19, 2024

Nothing to do with delays or latencies, but I just read that PW resamples everything to a "central frequency" and from there to whatever the output device is set to.

You can bypass PipeWire and use ALSA output in QMPlay2 set to hw:n to use the device directly, so you'll have bit-perfect exclusive access (all other streams must shutdown before playback). "Force samplerate" in QMPlay2 must be disabled.

Another solution is to create config in /etc/pipewire/pipewire.conf.d/ and set array of allowed frequencies (set freq you want, you can set more than one):

context.properties = {
     default.clock.allowed-rates = [ 48000 ]
}

Restart services and observe pw-top what will happen.

@RJVB
Copy link
Contributor Author

RJVB commented Dec 19, 2024 via email

@zaps166
Copy link
Owner

zaps166 commented Dec 20, 2024

Try this command watch -t -n 1 cat /proc/asound/card*/pcm*p/sub*/hw_params and see sample rates - it comes from audio driver.

Also open pw-top - it shows what PipeWire is doing with samplerate. If all are the same - I guess there's no resampling from the player to the audio device.


Does that work with PW? With PA you can't unless you exclude the device you want. I think it has to do with the compulsory "monitor of XXX" devices.

If PW closes audio device (suspend must be enabled), you can open it using ALSA plugin using hw:n,m device in settings. It's direct access to the device, it skips PipeWire/JACK/Pulseaudio/whatever completely.

@RJVB
Copy link
Contributor Author

RJVB commented Dec 20, 2024 via email

@zaps166
Copy link
Owner

zaps166 commented Dec 21, 2024

That's what I'd hope too, but I suppose it depends what that internal frequency is - probably not 2116mHz (44.1k * 48k) ;)

What driver or hardware is doing is - let's say - out of scope. I'm talking about not using PipeWire/PulseAudio for this. Or configure PipeWire/PulseAudio to use different sample rate to match your audio file (so it'll depend on driver/hardware, PipeWire will not resample).


This ALSA settings works for my integrated audio device:

Zrzut ekranu_20241221_092107

In this case, PipeWire is not used:

Zrzut ekranu_20241221_092444

192kHz stereo samplerate in QMPlay2, the driver hw_params:

Zrzut ekranu_20241221_092215

I can measure high frequencies (generated by Tone generator in QMPlay2) e.g. 80kHz on JACK output, so it's really 192kHz (or around 192kHz - idk what driver/hardware is doing).

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

No branches or pull requests

2 participants