Enitoni / pulseshitter

An overengineered workaround to Discord not supporting audio when screensharing on Linux.
Mozilla Public License 2.0
349 stars 8 forks source link

Pulseshitter streams the microphone when the process closes its sink #19

Closed LyesSaadi closed 1 year ago

LyesSaadi commented 1 year ago

Hello !

We have that annoying issue with games which closes their audio sink when using pulseshitter, either by closing the game or because the game itself just stops playing sounds and closes its sink when it does. When those games do that, pulseshitter begins to stream the microphone's audio creating annoyance for everyone in voice chat.

Although, I've noticed that this is sometimes inconsistent ? I don't know exactly what triggers that, but, if pulseshitter could avoid switching to the microphone, or could try to only capture audio from a single process, and just not stream anything when this process closes its sink, and restreams it when that process reopens a sink, that would be great !

Examples to try to reproduce this are Firefox or the Henry Stickmin Collection.

The process also appears in yellow when that happens for some reason.

Enitoni commented 1 year ago

Pulseshitter has a mechanism in place to kill the stream as soon as the sink input is closed, because it is actually not pulseshitter changing to the microphone, but parec (the process recording your game). This is an issue with the original pulsecord (that this project was inspired by), that pulseshitter is supposed to fix.

This is not an issue me or my friend can reproduce. Can you give me some steps to reproduce the issue? It shouldn't be happening. Also tell me what audio devices you have, and the version of pulseaudio/pipewire on your system.

The yellow process means that the sink input is closed/gone. pulseshitter displays it in yellow and allows you to still select it so that once it comes back, it can continue the stream. This is to fix issues where for example seeking in a video or muting and unmuting will cause the sink input to change.

Emik03 commented 1 year ago

Works fine for me on both Firefox and Henry Stickmin Collection, I suspect you have an outdated version of pipewire, or perhaps some quirk with pulseaudio?

What distro do you use? I have never run into this issue on popOS 22.04 or Fedora 38, both on pipewire.

It should look like this when you have closed the sink input that is currently streaming.

image

LyesSaadi commented 1 year ago

Hi ! This is weird, then...

So, I'm on Fedora Silverblue 39, so, prolly not a pipewire version issue.

❯ pipewire --version
pipewire
Compiled with libpipewire 0.3.80
Linked with libpipewire 0.3.80

Can you give me some steps to reproduce the issue?

There isn't any difficult process to reproduce it from my side, really. I just finished playing with friends henry stickmin, and the issue is triggered after a few seconds without any sound from the game, but it could also be just the game closing the sink at that time.

Maybe some quirks with Silverblue ?

LyesSaadi commented 1 year ago

So, a bit more testing, so, it's actually properly seeing that the sink is closed. The UI just "defocuses" all entries, but pulseshitter outputs my sound.

Here are some steps I did on Firefox:

Test 2:

With any other game I played, when I closed the game, it would begin to output my voice.

Enitoni commented 1 year ago

Just to be sure, you're on the latest version of pulseshitter, correct?

If that is the case, can you run this command and tell me what you get? pactl --version

I also checked with my friend, and they are on pipewire 0.3.83 not 0.3.80 so it's possible this is a Fedora regression. If possible, can you try upgrading to that version and see if that works?

Your steps to reproduce do not seem to work. pulseshitter stops outputting when the sink is closed as intended. So this has to be caused by a difference in your system and ours.

Enitoni commented 1 year ago

This is the line that determines whether or not to clear the stream (aka, stop it). This assumes that the device stays the same, and that the stream has not moved (for example, to your microphone).

https://github.com/Enitoni/pulseshitter/blob/06670f9beee363f052cc5011413fb92b7ca82dc4/src/audio/parec.rs#L65

My suspicion so far is that you have a version of pipewire that does not properly send this event.

LyesSaadi commented 1 year ago

I think I was on the latest pulseshitter, recompiled it just to be sure, and it didn't change anything.

For pactl :

❯ pactl --version
pactl 16.1
Compilé avec libpulse 16.1.0
Lié avec libpulse 16.1.0

I'll try to rebase to the testing repos of Fedora 39 for latest pipewire, as updates is currently in a freeze.

LyesSaadi commented 1 year ago

Tested with 0.3.83, it doesn't solve the problem :/...

Enitoni commented 1 year ago

That is very strange. Could you try running the parec command that pulseshitter runs and see if it detects the sink input closing properly? It should start with "Stream moved to" and is outputted to stderr. Show me the logs of what that looks like after you have reproduced the issue. Just be sure to direct stdout to /dev/null as it will spam your console with raw audio if not.

https://github.com/Enitoni/pulseshitter/blob/06670f9beee363f052cc5011413fb92b7ca82dc4/src/audio/parec.rs#L74-L91

LyesSaadi commented 1 year ago

How to get the device and source ids ?

LyesSaadi commented 1 year ago

Okay, so tried to do it manually with Helvum:

Ouverture d’un flux enregistrement avec une spécification d’échantillon « s16le 2ch 44100Hz » et un plan des canaux « front-left,front-right ».
Connexion établie.
Création du flux réussie.
Mesures du tampon : maxlength=4194304, fragsize=352800
Utilisation de la spécification d’échantillon « s16le 2ch 44100Hz », plan des canaux « front-left,front-right ».
Connecté au périphérique alsa_input.pci-0000_00_1f.3-platform-skl_hda_dsp_generic.HiFi__hw_sofhdadsp_6__source (index : 52, suspendu : no).
Flux déplacé vers le périphérique Firefox (344, non suspendu).
^CSignal obtenu, fermeture.ce : 1788757 µsec.        

"Flux Déplacé" means Stream moved. That message appeared only when first connecting Firefox to parec at step 3, but not when closing the connection at step 4.

Enitoni commented 1 year ago

You can get the commands from here:

https://github.com/Enitoni/pulseshitter/blob/06670f9beee363f052cc5011413fb92b7ca82dc4/src/audio/pulse.rs#L633-L649

Enitoni commented 1 year ago

I think I see the issue already. Your output is in french. pulseshitter cannot properly detect the events if the output is in french. There might be an environment variable you can run to get it to output in english.

LyesSaadi commented 1 year ago

Oh that would be hilarious if that's the issue.

Enitoni commented 1 year ago

Try running pulseshitter with this environment variable: LANG=C

LyesSaadi commented 1 year ago

Yup, that was the issue :laughing: ! This is hilarious.

Enitoni commented 1 year ago

I'll hopefully get around to updating pulseshitter later (currently don't have my setup) so I'll commit a fix by then. In the meantime, you'll have to run the binary with that environment variable.

LyesSaadi commented 1 year ago

Seems like a pretty trivial fix for me, and I have a setup ready, will try to send a pull request your way !

Enitoni commented 1 year ago

Sure, go for it!