Closed DeeBeeDouble closed 8 months ago
A request though: can we have it as an option in the settings menu?
I did not want to make it visible, as I'm aware it would be complicated for most end-users and the current behavior would not be expected for the end-users. This flag is more like you enable this, but don't blame me if it sucks (and it will).
So, to summarize our possibilities, we can now implement this further in a few other ways:
asar
archive, would work in the renderer
process and furthermore would be revolutionary for Node in general, as it would probably be implemented as separate package published into NPM. Something similar I saw to be implemented for pulseaudio
, althrough for some reason it did not work via socket (it threw Permission denied on PipeWire PulseAudio server if I modified the code to successfully connect to the socket; normally it lack the proper logic to even use socket for communication). Currently blocked as I either need to find the source code of the library and understand it or the socket documentation, that seems to be nonexistent as of today. Maybe actually request that from PipeWire developers?Personally, I would love to implement the 3rd option (I'm a bit experienced with Buffer operations in Node, so creating a packaged and encoding a data for it would not be a problem for me), but lack of the resources is what stopped me from doing anything on that. And it sucks that both PipeWire and PulseAudio seems to lack a documentation for their sockets/packets or at least I couldn't find it right now.
If anyone got any clues on that, I would be more than thankful for sharing an information about this.
I saw this one day on Reddit, I don't know if this can be useful for you about PipeWire : https://www.reddit.com/r/linux_gaming/comments/wthqee/pipewire_tools_guide/
If anyone got any clues on that, I would be more than thankful for sharing an information about this.
I saw this one day on Reddit, I don't know if this can be useful for you about PipeWire : https://www.reddit.com/r/linux_gaming/comments/wthqee/pipewire_tools_guide/
I need more specific information about the socket, at least that's what I believe I need to reimplement the library on PipeWire. I may also work with pulseaudio instead, I think I found why it always failed to connect. I could fork the library mentioned in this comment and easily adapt it to support UNIX sockets. The only think I'm unsure is the PulseAudio cookie path – I think I've found it on my system at ~/.config/pulse/cookie
, but I'm unsure if this path is specific to my distribution or not...
Oh damn, okay. By the way, I also have this path .config/pulse/cookie
on Pop!_OS 22.04 if it helps.
(And if I'm not mistaken, Pop!_OS is based on the Ubuntu distribution.)
Got some Pulse cookie path under Fedora 36
Oh damn, okay. By the way, I also have this path
.config/pulse/cookie
on Pop!_OS 22.04 if it helps. (And if I'm not mistaken, Pop!_OS is based on the Ubuntu distribution.)Got some Pulse cookie path under Fedora 36
Looks like these are defaults then. I believe you can replace these paths with some env variables, but I'll work on that later.
Also I've made a Pull Request on the tmigone/pulseaudio: #34, hopefully it will be merged rather quickly or I'll plan to fork this project in case the author will reject the changes for some reason (but as I've contacted him, he's at least willing to still maintain his project, maybe I'll help him to make it a worth WebCord dependency 😉).
Awesome to see tmigone/pulseaudio: https://github.com/tmigone/pulseaudio/pull/34 merged, keep up the good work!
I'm currently learning how to use the pipewire library, @SpacingBat3 are you interested in the development of an NAPI-based pipewire wrapper?
I'm currently learning how to use the pipewire library, @SpacingBat3 are you interested in the development of an NAPI-based pipewire wrapper?
I've personally wanted to implement this via @tmigone/pulseaudio
library. Currently I'm stuck with the authentication (which doesn't sound promising), but at least the connection itself to the socket and the unauthenticated communication works OK.
You're free to work on NAPI implementation through. Probably it should be made as separate Node dependency,
can you at least create the sink the way https://greasyfork.org/en/scripts/436013-screenshare-with-audio does for now? That way we can use webcord to make it work as described in this video https://www.youtube.com/watch?v=zX0pGSOfwzc
can you at least create the sink the way https://greasyfork.org/en/scripts/436013-screenshare-with-audio does for now? That way we can use webcord to make it work as described in this video https://www.youtube.com/watch?v=zX0pGSOfwzc
As said earlier, I both don't want from the users to configure anything when implementing a sound share (I want to achieve a smooth experience; audio configuration on Linux should be as easy as in case of Windows) nor integrate with any third-party software. And I don't like the idea of providing another binary in WebCord that would make packaging WebCord much more complex and possibly would require more work on preparing package system. Executing outside binaries is not the best idea as well for security reasons. I also don't want to modify streams without spoofing them as legitimate ones (as an anti-trust action to Discord; WebCord's philosophy is to avoid doing changes that can mean Discord has been modified, to keep it thinking it is a regular Chromium browser), which would require much more work to implement it right.
This is why this issue is open for a such long time. It should be also said that both Chromium and Electron devs might eventually fix this on upstream, making all work meaningless there.
You might be interested at looking on WebCord's Chromium extensions until I'll came with better extension format. While extensions right now can't replace CSP, they should be able to tweak site contents and therefore apply needed changes.
There's also already a "dirty hack" to force enable audio sharing on unsupported platforms (See https://github.com/SpacingBat3/WebCord/issues/154#issuecomment-1201444954 and https://github.com/SpacingBat3/WebCord/commit/4e585153ad9a17e26f1f81c7a851f9c3814c324b for details).
What you want won't be possible until xdg-desktop-portal implements it https://github.com/flatpak/xdg-desktop-portal/issues/751
As of now, the only way to get desktop audio of particular apps is to have the user route the audio themselves. You can't do what obs does and just record from the monitor of the default device because then you will pick up audio from the voice channel.
What you want won't be possible until xdg-desktop-portal implements it
I don't think you're right.
Window enviroment is a separate thing to sound enviroment. Think about that Wayland limits what specific application can access graphically, but otherwise it doesn't block app from connecting to any socket nor accessing whole filesystem, there's another software for that purpose.
You should also consider that on X11 we can both have PulseAudio and PipeWire. PipeWire can also replace the PulseAudio, which is why it makes sense to develop a stuff for PulseAudio if we want to support both PipeWire and pulse. Many noted that the concept of streams is non-existant in pulse, but somehow pavucontrol
makes me to believe the opposite.
I want also mix streams, but as the source WebCord should access the pulse or PipeWire socket, either via library or directly with JS/TS client implementation as I was expermienting.
(...) pick up audio from the voice channel.
This is already happening on Windows. But since we have an access to the web, I think this would be eventually fixed as well.
You should also consider that on X11 we can both have PulseAudio and PipeWire. PipeWire can also replace the PulseAudio, which is why it makes sense to develop a stuff for PulseAudio if we want to support both PipeWire and pulse. Many noted that the concept of streams is non-existant in pulse, but somehow pavucontrol makes me to believe the opposite.
You can have both running in the same wayland session.
it makes sense to develop a stuff for PulseAudio if we want to support both PipeWire and pulse.
It only makes sense if you want to "support" PipeWire and just truly support PulseAudio. Accessing PipeWire through pipewire-pulse
will not expose, for example, JACK clients, and possibly future native PipeWire clients too. Sure, the vast majority of application runs based off libpulse
but I'd prioritize native PW over PA + PW over compatibility layer.
I'd want to be able to stream DAWs to Discord too, let me just say.
Accessing PipeWire through pipewire-pulse will not expose, for example, JACK clients, and possibly future native PipeWire clients too.
To be honest, the majority of software designed for the desktop still implements stuff for PulseAudio. On my DE if pipewire-pulse
would not exists, I would probably no longer use PipeWire at all (as you noted).
(...) but I'd prioritize native PW over PA + PW over compatibility layer.
There's still a major group of users that use WebCord and are using PulseAudio, maybe even bigger than those using PipeWire. How I know that? These are RPi users and RPiOS for now only provides PulseAudio by the default. For some time (quite recently, at least that was in times I was using my RPi) RPiOS actually used ALSA and was not designed to work with Pulse. This shows that PipeWire is not well adopted for everyone and for sake of keeping the compatibility, I'd prefer working on PA + PW over only native PW.
To be honest, the majority of software designed for the desktop still implements stuff for PulseAudio.
That's exactly what I said, and it basically covers most normally used applications. However it won't cover digital audio workstation software (native and through Wine, since WineASIO maps to JACK), and there is also a possibility of it not covering Minecraft, when OpenAL is set to use JACK for some reason. It also won't possibly cover GStreamer pipes using pipewiresink
.
@ImUrX I believe I've seen this meme originally on r/linuxmemes
, but made me smile to see it in the wild.
I don't really think PulseAudio is as bad, but PipeWire is definitely an improvement. As of the stability, they're both similary stable in my eyes, I had a breakages on both PipeWire and PulseAudio after updates.
As of the stability, they're both similary stable in my eyes, I had a breakages on both PipeWire and PulseAudio after updates.
There's a noticeable difference between the two though. PipeWire handles latency better than Pulse, resulting in way less crackling even in complicated graph setups. When I was using Pulse, having a single loopback sink was enough to have persistent crackling, and I don't have a weak system by any means.
However it won't cover digital audio workstation software
I don't really think WebCord should care much about the specialised audio subsystems (like I've never used JACK for my system audio; PulseAudio is quite the only choice for me, even when using PipeWire I'm still forced to rely on the PulseAudio protocol due to compatibility reasons), but rather focus on what average Linux user has configured by the default. Since Pulse are basically defaults, I wouldn't focus on developing code that only minority would find useful. Instead, IMO we should focus on the code for the majority of the users that is already lacking and then work on the code for the others as a bonus.
Maybe I could or should work on the extensions first through. Implementing better extensions would mean that it would be at least possible to mess up with the site's code the way extensions does.
No matter what I decide, it requires from me a lot of time to invest, which unfortunately I am very limited with now.
I don't really think WebCord should care much about the specialised audio subsystems.
This is really not the problem here. If a user has a Pulse configuration, they will only use PulseAudio, and then WebCord will work with 100% of the apps.
The problem surfaces when the user has a PipeWire configuration, since PipeWire doesn't just "emulate" a Pulse server, but it also interfaces with apps made for JACK, and it can also have native (not Pulse, not JACK) clients if they use GStreamer as a backend.
I am not suggesting to support JACK here, but to support PipeWire properly.
A related note on this: PipeWire is taking over all the default user configurations. Fedora switched to it, and so did Arch Linux, suggesting people who were using PulseAudio already to move to PW; Ubuntu and Debian probably the only major distributions who still use PulseAudio, and I am sure PipeWire will be there for future Ubuntu releases because it is needed on Wayland setups and GNOME is now Wayland-first.
I will be making the pipewire
NAPI package, so that part will be done btw.
IMO we should focus on the code for the majority of the users
On that note I feel different. From what I gather, PipeWire is already used by most Linux users. According to Steam Hardware Survey (let's be real,if you use Discord you're most likely also on Steam) the most popular Linux distros to be used are Arch Linux, Manjaro Linux, Ubuntu and Linux Mint.
Apart from Linux Mint the other distributions already use or will use Pipewire by default.
Looking at current movement pipewire seems that it will be the default for future to come on Linux distributions. I get your sentiment that you want to have wider support as of current date, but in long term supporting pipewire instead seems to be the wiser choice because this wind doesn't stop for years to come. Pipewire is the future from what I see.
@NyaomiDEV @Snaggly those examples are / might be correct for x86, but ARM world has its own rules. RPiOS is a great example: they're terrible at switching to newer/better audio subsystems, I remember times when it used ALSA by the default. And since I can see WebCord is used by a major group of users that owns Raspberries, I still care about people using the older software no matter if I use it myself.
I just recommend PulseAudio for the development for compatibility, when it does not break much for PipeWire users. And to be honest, how many apps are there that connects directly to PipeWire rather than its implementation of PulseAudio protocol? In my setup, I don't think there's any outside of tools specifically made for tweaking the PipeWire streams like EasyEffects.
I'm not against of PipeWire, but for me it has the same issue as Wayland: the linux world is still unprepared for it and many apps only care about PulseAudio, no matter if it is implemented via PipeWire's compatibility protocol or directly via PulseAudio server. PipeWire might be the future, but the future is not today. As the developers, we can't always think about ourselves, we also need to think about the opposite side of the barricade and the users that preffer older and well-adopted implementations. This is why I preffer implementing PulseAudio clients over implementation of PipeWire-only support. I'll accept both made by the community, as long as they can behave right in the enviroments lacking of the APIs.
So @ImUrX consider pipewire
as optional dependency and be sure to code the logic for pulse users as well (probably you want to show the unsupported message on sound share button like it is done right now). If you consider working on NAPI module, I would recommend you to publish it to NPM, surely other packages would make a use of it.
yeah, I'm currently implementing the code for pipewire on clap
and checking if pipewire-rs
requires help. When I finish that code I will be comfortable enough to know what I'm doing and make a good lib for Node
And to be honest, how many apps are there that connects directly to PipeWire rather than its implementation of PulseAudio protocol?
Aside from EasyEffects and JamesDSP, which act in the middle of the graph and are not relevant as "apps to grab the audio from", there's every other app that relies on GStreamer that can theoretically be working as a native client. Strawberry Music Player comes to mind because I use that and it relies on GStreamer for all I know. Is there a reason to screenshare a music player? I don't know, but that is an app for general use so I guess that's plenty of reasoning to investigate.
With --force-audio-share-support
, I managed to get audio sharing to work on Wayland with pipewire-pulse, the only problem is that it's impossible to tell which of Chromium input is microphone input and which is getUserMedia(?) input. I know it's not officially supported but would it be possible to label them?
Hi, I'm currently working on a native nodejs pipewire module, but for dependencies I need to install pipewire-devel and others (I'm on fedora).
That means that every user needs to have pipewire (devel, and other libraries...) to build webcord?
How can electron handle all this?
BTW, I’m using Rust with Neon to build the module.
Ok, feel free to try my module. https://github.com/kakxem/node-pipewire
There are few options, but it's possible to connect nodes, so this could solve one of our problems.
Update: I have managed to get it to work! (Although with "npm run start")
Needs to be more polish, but anyway, I'll leave the fork here in case anyone is interest: https://github.com/kakxem/WebCord
Things that need to be done:
Surely there are more things missing, feel free to comment.
To get it work, check the requirements in the README.md from the node-pipewire repo.
@kakxem Hey, I just checked out your build and it seems to work fine. Does with your current implementation filter out Discord's Audio when recording the entire Desktop Audio?
Also do you think and implementation would be possible to have automatically chosen the right Window audio source given by the Pipewire Window selection? Like the desktop portal reports back this or that Window ID was selected and you automatically get to pick the right sound source if sound sharing was activated.
@Snaggly
Hey, I just checked out your build and it seems to work fine. Does with your current implementation filter out Discord's Audio when recording the entire Desktop Audio?
In my build you can select the output audios that you want to share with your screen (I'm in Wayland so I didn't try the build in X11 but it should be the same)
My solution has the next problem. We don't know what audio node is from Webcord, the only thing we know is that Webcord uses Chromim, so the node is "Chromium". The problem will come if the user want to share another "Chromium" application (Microsoft Edge, Google Chrome and other chromium based browsers have other names), because Webcord (aka. Chromium) will be attached to the screenshare audio.
Maybe we can send our call node and the screenshare audio node to the "blacklistInputNodes" (sources/code/main/main.ts, line 44) and then filter it some way... idk...
Also do you think and implementation would be possible to have automatically chosen the right Window audio source given by the Pipewire Window selection? Like the desktop portal reports back this or that Window ID was selected and you automatically get to pick the right sound source if sound sharing was activated.
Tbh, I don't know. I put in PipewireNode the key "props" which has all the node data. Example:
{"factory.id":"6","media.class":"Stream/Input/Audio","application.name":"Chromium input","node.name":"Chromium input","object.serial":"1009","client.id":"99"}
If you know some way, tell me and I'll try implement.
But I prefer my solution cause we can share the screen we want and share other audio with others. As example, you could share your game screen with the game and YT audio.
Another update: I can build the package without doing anything special in Linux (only "npm run make") and it works! But...
In the .deb/.rpm installers we should indicate the dependencies but no clue how to do it. Idk how AppImages works and Idk what should be done.
Any suggestions?
Ok, I had a weird idea.
I've created a "fake-module" that contains same functions as node-pipewire module, but all of them return null or empty arrays.
With this we can solve the problem of build Webcord in other systems, but that means we need another version only for pipewire users...
I pushed the changes in my fork with new scripts and the new fake module:
@SpacingBat3, what do you think?
Ok, I had a weird idea.
I've created a "fake-module" that contains same functions as node-pipewire module, but all of them return null or empty arrays.
With this we can solve the problem of build Webcord in other systems, but that means we need another version only for pipewire users...
I pushed the changes in my fork with new scripts and the new fake module:
* "npm run enablePW": Will install node-pipewire * "npm run disablePW": Will install the fake-module to replace node-pipewire.
@SpacingBat3, what do you think?
From what I know about the Rust is that some things or even dependencies can be set for a specific platform, which means that native code could be configured to work differently across different platforms and e.g. display an error or actually return an empty functions that does nothing and is only to comply with the types.
With JavaScript side of the module, that's probably possible as well. You can if(process.platform === "linux")
and that could be used to return different results for different platforms. But from my experience with Neon, all JS code and types are generated from the Rust code, so doing that on Node's side is probably going to be a bit harder than achieving the same with Rust (you probably wouldn't want to use Neon for that purpose).
As of acceptance and native module support in WebCord, Electron Forge does build them on their own, but it can be configured to do otherwise and this is what I'm actually doing (I don't Forge to check for them to be rebuild if there's no native modules being used). And before merging any change with native modules, I would probably have to adapt webcord-git
in AUR as it lacks of the logic to detect, build and unpack the modules if they exists.
And as your module lacks of the logic for non-PipeWire users, I doubt I will accept it. It needs to be functional in some way for users without the libraries installed in the OS (at least after WebCord being compiled), optimally including development libraries/headers as a dependency. I'd love for my app to be able to build it without any additional build environment installed system-wide, other than Node with any Node package manager (excluding the toolkit that is installed on npm i
and git
for actually fetching the source code).
From what I know about the Rust is that some things or even dependencies can be set for a specific platform, which means that native code could be configured to work differently across different platforms and e.g. display an error or actually return an empty functions that does nothing and is only to comply with the types.
Yeah this is actually possible, but the most preferable way should be to actually detect if pipewire is available from the node library because it loads the rust library dynamically. So you should add a check if pipewire's shared objects are available, then you can add a function that returns if you can actually use pipewire
From what I know about the Rust is that some things or even dependencies can be set for a specific platform, which means that native code could be configured to work differently across different platforms and e.g. display an error or actually return an empty functions that does nothing and is only to comply with the types.
I'll look for information to see if it's possible, but it seems strange to me cause it would be the same as if we don't install "node-pipewire" in Webcord and then we try to build without expecting any error from "tsc". Anyway, I'll try to search a solution.
And as your module lacks of the logic for non-PipeWire users, I doubt I will accept it. It needs to be functional in some way for users without the libraries installed in the OS (at least after WebCord being compiled), optimally including development libraries/headers as a dependency.
That's why I created the "fake-module", to be able to compile the Webcord without having Rust and the Pipewire-devel, only Node. (And of course, It'll not work audio-sharing but you'll be able to compile in Windows/MacOS and Linux without PipeWire)
My proposal was to create 3 .deb/.rpm/AppImage only for PipeWire users and 3 .deb/.rpm/AppImage for non-PipeWire users. You can build each of them changing between "npm run enablePW" and "npm run disablePW". You could set the "fake-module" as default installation in package.json so you can run without tweaking anything.
I'd love for my app to be able to build it without any additional build environment installed system-wide
You mean without having "pipewire-devel" and Rust installed? I don't think you could do that cause is a native module...
BTW, I'm not an expert in Rust, so if anyone know where could I start, I'll appreciate it.
Yeah this is actually possible, but the most preferable way should be to actually detect if pipewire is available from the node library because it loads the rust library dynamically. So you should add a check if pipewire's shared objects are available, then you can add a function that returns if you can actually use pipewire
I'll try it, thanks.
You mean without having "pipewire-devel" and Rust installed? I don't think you could do that cause is a native module...
@SpacingBat3 I think requiring rust when pipewire is already installed is not bad, now-a-days more people are using rust (even linux now has support for rust in 6.1 on their codebase!)
My proposal was to create 3 .deb/.rpm/AppImage only for PipeWire users and 3 .deb/.rpm/AppImage for non-PipeWire users. You can build each of them changing between "npm run enablePW" and "npm run disablePW". You could set the "fake-module" as default installation in package.json so you can run without tweaking anything.
Nah, I don't accept that… I'm pretty sure libraries can be dynamic in most non-script based programming languages (even in script based ones they usually are), you can give hints to the compiler how it behaves if given lib is available or not (in case of development libs) or even probably detect that at the runtime.
I made an update in feat/ignore-pw-dependence branch:
Now it's not necessary the "fake-module" cause by default, at "node-pipewire" installation with npm, the functions will return undefined/empty-array.
But the problem persists:
In the package.json of "node-pipewire" I created a new script that makes the module with and without pipewire.
Maybe I'm missing something so I'll wait to @ImUrX with his fork of "node-pipewire" before merging my new branch to main.
can you join the webcord discord so we can discuss what I think in there?
Any progress on this?
@Smoukus Hi, I need to solve two problems.
The first one that I almost finished, is upload the library for aarch64 (ARM processors) of the node-pipewire module I made.
The second one, I found a bug that when you are sharing screen and you want to "change window" (The discord option), the shared sound stop working, so I'm thinking about a way to make it work.
It happen cause when you change the window, the node audio from the share screen is removed and then electron creates a new one, but it appears instantly and I can't get the new node from the function "waitForNewNode" (This is called in my node-pipewire module to see if a new node is created).
That's it, I'm doing this in my free time so if anyone want to do something, I guess u can create a pull request in my fork and if it works I'll merge it in my branch.
Hey! I was wondering if there is any more help needed ft get this working. This feature is the only reason I am not using linux full time and I would love to be able to help with it!
Hey! I was wondering if there is any more help needed ft get this working. This feature is the only reason I am not using linux full time and I would love to be able to help with it!
Another thing I want to be possible to implement like this is an ArRPC integration, you should be able to use it instead of DisConnection in WebCord (or any other implementation, including null ones) once there will be a module for that.
A lot of details are (yet) undecided, I'll be contacting devs for what really should be provided by third-parties and what WebCord will just handle and reuse across different implementations. I might also build then 2 releases of WebCord: Community Edition with 3rd party modules passing simple tests and Official for my own implementations and modules I trust and verified to be working/non-malicious.
That being said, there's a lot work to be done before even I will come with something usable (even the build structure of such project might be complex) and things might not be fully-featured at the beginning, but if I finish it, it would be more safe to accept PRs without complete review of all modules (at that could take quite a time, especially for native ones).
As a reminder, the current official implementation has a way to enforce the audio recording (even through it is not supported by Chromium) with a command-line flag and (on Linux) by setting the default stream in OS setting. It might be also possible to assign a stream via the patchbay. Unlike to what PR does, official implementation also works with PulseAudio (it does not depend on PipeWire at all), but has more limitations and is way less user-friendly.
Looks like Chromium devs have finally implemented this for a while! :tada:
This means, it is a matter of time (or flags) to have this supported in WebCord. It should also be said, the implementation will be similar to the one within Windows (there's only single loopback device that can be used as an audio source).
This also means, given I would prefer to use standard APIs in Electron and support PulseAudio, the screen share PR might be closed sooner or later. I will be also moving to the new getDisplayMedia()
handling API, so there won't be that much of IPC communication anymore just to screen share stuff.
Also link to (much prettier) commit info on Github mirror: https://github.com/chromium/chromium/commit/9a3d5ea818e66821c8a87b11b842dfd47c023608.
You might also find there a tag list which contains versions of Chromium that contains this change, so I guess you might as well use that to estimate whenever this reaches stable Chromium/Electron.
MOD edit / notes
This issue ticket was previously a request to integrate with the existing solution, which I didn't want to work on – mostly as both JavaScript / TypeScript based client and native Node modules would better integrate with the code and build system (i.e. a such binary I would have to provide would likely has to be somehow rebuilt outside of Electron Forge and probably depend on more libraries / binaries which normally would not be needed for packaging of my application). However it quickly became one of the most popular topics in WebCord and became a bit more generic about sound screen sharing on Linux. It is also very special for me because of the large community interest about resolving it, making it much closer to be finally resolved once and for good. So thank you all for participating in it!
MOD EDIT2: This is now resolved in Chromium, awaiting to be merged to Chromium stable and/or Electron. Right now this is a feature behind the flags, hopefully it will be enabled by the default and will work just fine. See bugs.chromium.org#1143761 and Chromium commit
9a3d5ea
for more details on it.Original message by @DeeBeeDouble: