Skip to content

Conversation

@david672orford
Copy link

@david672orford david672orford commented Apr 8, 2024

Description

The PulseAudio plugin currently supplies only audio inputs and capture of outputs using their monitor sources. This PR implements output to sinks. It can also create a virtual audio cable using PulseAudio modules and tear it down when the output is stopped.

Change summary:

  • New file pulse-output.c: implements pulse_output
  • New file pulse-utils.c common functions extracted from pulse-input.c
  • Existing file pulse-wrapper.c: new functions to get sink info, load and unload Pulseaudio modules
  • No changes to pulse input code (other than moving some to pulse-utils.c so we can use it in pulse_output too)
  • No UI changes. See PR for Lua scripts to test.

The pulse_output takes two properties:

  • device -- the name of the PulseAudio sink. Start with "obs-" to dynamically create a virtual audio cable
  • description -- Displayname of virtual audio cable

Scripts to demonstrate the audio output:

Motivation and Context

Existing program audio outputs either stream over the Internet or require special hardware such as Decklink. Users who use OBS at events held in person or in video conferences would like to feed the mixed audio into speakers or a virtual cable. Source audio monitoring is currently widely suggested as a substitute, but setting it up can be error-prone and it lacks certain features such as fade transitions.

Here are ideas pages where user request these features:

How Has This Been Tested?

Tested on Ubuntu 22.04 using both Pulseaudio 15.99.1 and Pipewire 1.0.3. Output to speakers and to Zoom through virtual cable both tested. No clicking or other signs of buffering problems.

Types of changes

  • New feature (non-breaking change which adds functionality)

Checklist:

  • My code has been run through clang-format.
  • I have read the contributing document.
  • My code is not on the master branch.
  • The code has been tested.
  • All commit messages are properly formatted and commits squashed where appropriate.
  • I have included updates to all appropriate documentation.

@david672orford david672orford marked this pull request as draft April 8, 2024 17:47
@david672orford david672orford force-pushed the pulseaudio-output branch 2 times, most recently from 404dd26 to 07ffdb4 Compare April 8, 2024 18:39
@david672orford david672orford marked this pull request as ready for review April 8, 2024 19:00
@david672orford david672orford force-pushed the pulseaudio-output branch 2 times, most recently from 619bd67 to 6f04ed1 Compare April 8, 2024 20:02
@david672orford
Copy link
Author

david672orford commented Apr 8, 2024

Caught some places where I had moved existing code around for no good reason. Fixed and repushed with cleaner diffs.

@kkartaltepe kkartaltepe added the Linux Affects Linux label Apr 9, 2024
@kkartaltepe
Copy link
Collaborator

Thanks for the PR, FYI we generally recommend larger changes to go through RFCs (https://github.com/obsproject/rfcs) so authors can get feedback before implementing things.

Considering pulseaudio is nearly unmaintained in OBS (and has been phased out of most distros over the last few years) is there a particular reason you implemented this against pulseaudio?

@david672orford
Copy link
Author

david672orford commented Apr 9, 2024

@kkartaltepe Thanks for your response. You are correct, major Linux distributions adopted Pipewire several years ago, but they are still transitioning. The first long-term-support release of Ubuntu which uses Pipewire by default will not come out until later this month.

More importantly though, the native Pipewire API's for playing and recording audio are not yet stable. As Pipewire creator Wim Taymans said in a November 2023 interview on the occasion of the release of Pipewire 1.0:

Q: So when PipeWire got merged into Fedora the message was that the official audio APIs for PipeWire would be the PulseAudio and JACK APIs. We have seen some projects come along since then using the PipeWire stream API instead. Is the message still to use the PulseAudio and JACK APIs for new development, or has your thinking on that changed over the last couple of years?

The message is still to use the PulseAudio and JACK APIs. They are proven and
they work and they are fully supported.

I know some projects now use the pw-stream API directly. There are some advantages for using this API such as being lower latency than the PulseAudio API and having more features than the JACK API. The problem is that I came to realize that the stream API (and filter API) are not the ultimate APIs. I want to move to a combination of the stream and filter API for the future.

--PipeWire 1.0 – An interview with PipeWire creator Wim Taymans

The direct Pipewire support in OBS is for cameras and screen capture. #6207 is a draft PR for native Pipewire audio capture to take advantage of the reduced latency. Audio monitoring (in libobs/audio-monitoring) still uses the PulseAudio API and there seem to be no plans to change that.

I attempted to start a discussion about implementing audio output on the OBS Virtual Camera audio page back in June 2021, January 2023, and again in May 2023, but it went nowhere. I tried again last month in the discussion of #8171, but still could not attract interest to the issue. After three years of waiting I went and did the research and implemented the backend part on my own. That gets me what I need for my own use.

If others would like to particate, I would be happy to discuss a possible UI or even propose something and write an RFC. I don't know QT, but might still be able to implement it with guidance from a frontend developer.

@norihiro
Copy link
Contributor

If you release this as a 3rd party plugin at https://obsproject.com/forum/plugins/, I think it would be welcome.

To me, the output (obs_output_t) type is interesting because the monitor can just monitor each source. So the user cannot listen actual streaming or recording sound. For example if the track assignment is unintentional, the audio could fails to go to the live without noticed by the monitor. On the other hand, the output-type will let user to listen to the mixed track. Probably, #4741 is another hope of the compatible feature.

However, I don't know this PR is worth to be merged for now. Especially, I think these points would be the major concerns.

  • No UI is provided.
  • Windows and macOS are not supported.

@kkartaltepe
Copy link
Collaborator

However, I don't know this PR is worth to be merged for now. Especially, I think these points would be the major concerns.

* No UI is provided.

* Windows and macOS are not supported.

I think these are a concern for the virtual cam audio support in general and not necessarily for this PR. Personally I don't know what folks were considering for the actual implementation whether its an output or something new.

If you release this as a 3rd party plugin at https://obsproject.com/forum/plugins/, I think it would be welcome.

I would also like to see bugs shaken out earlier rather than later which is easier to get as a plugin than a PR historically. This is what the pipewire application capture has done for example. Of course feel free to just wait as at least I am still not sure if this a direction I would want to see merged, other folks may have other opinions.

@david672orford
Copy link
Author

I am just looking for a way to move this forward. I love OBS and am amazed by the work done on it, but am still frustrated by the lack of audio output. I sense that the maintainers are streamers who don't see a need.

But there is a considerable base of users who are using it for other things and they have been complaining about the lack of audio output. Sure, you can set up monitoring on all of your sources and connect them to a virtual cable which you create before starting OBS, but this is error prone and not very reliable. The monitor streams tend to get disconnected from the virtual cable for various reasons. I have had to write non-trivial scripts to get them reconnected quickly. And you point out, norihiro points, this would benefit streamers too since they could monitor the final audio mix.

You, kkartaltepe, refer to some issues surrounding virtual cameras. I don't know what these are, but the solution I intended to use on Linux is to install this plugin and the Lua script above to start audio output on a virtual cable whenever the virtual camera is running.

If the maintainers feel that a 3rd party plugin is the best way forward, I would respect that. I submitted this as a PR because it is non-disruptive and the recommendation is to implement major features in pieces through a series of PR's. My hope is that once there is audio output on Linux, others will be motived to implement it on Windows and MacOS.

I am not able to add audio output to the Windows and MacOS plugins myself. However, I do intent to continue working on PulseAudio support in OBS as long as it continues to use the PulseAudio API's on Linux. For example, I would like it if OBS could set metadata on audio streams so that we could see more distinctive labels in the volume control and Pipewire patchbays. I also want to look into whether the mute state of a microphone can be syncronized with the mute state in the PulseAudio/Pipewire mixer so that the mute lamp on the microphone will show the correct status. So this is not a one-off PR that I am trying to push into the project and then abandon.

@tt2468
Copy link
Member

tt2468 commented Apr 13, 2024

Please update your commits to remove the submodule changes.

@WizardCM WizardCM added the New Feature New feature or plugin label Apr 13, 2024
@david672orford
Copy link
Author

The submodule changes have been removed.

The pulseaudio plugin previously supported only audio inputs and
capture of outputs using their monitor sources. This PR adds output
to sinks. It can also create a virtual audio cable and tear it down
when the output is stopped.

* New pulse-output.c: implements pulse_output
* New pulse-utils.c common functions extracted from pulse-input.c
* pulse-wrapper.c: new functions to get sink info, load and unload
  modules
* No changes to pulse input code (other than moving some to
  pulse-utils.c)
* No UI changes. See PR for lua scripts to test.

The pulse_output takes two properties:

* device -- the name of the PulseAudio sink. Start with "obs-" to
  dynamically create a virtual audio cable
* description -- Displayname of virtual audio cable
@ogmkp
Copy link

ogmkp commented Sep 23, 2024

Thanks for the PR, FYI we generally recommend larger changes to go through RFCs (https://github.com/obsproject/rfcs) so authors can get feedback before implementing things.

Considering pulseaudio is nearly unmaintained in OBS (and has been phased out of most distros over the last few years) is there a particular reason you implemented this against pulseaudio?

What's more, there are still problems with pulseaudio (sound lag on VLC source or with the ndi plugin, for example), so what would be really good would be a pipewire implementation in the backend instead of pulseaudio.

I didn't quite understand this attempted PR, as pulseaudio wrapper for pipewire already creates nodes to monitor sources that can be routed.

@david672orford
Copy link
Author

I didn't quite understand this attempted PR, as pulseaudio wrapper for pipewire already creates nodes to monitor sources that can be routed.

My motive for creating this PR is that I wanted to be able to use OBS's audio mixer at in-person events and with the virtual camera.

The source monitoring provided in OBS can be used as a workaround for the missing output, but it is clunky. You have to turn it on for each source. Audio transitions will not be heard. And you need to use a patchbay program to route the microphones separately and you can't use OBS filters on them. This makes the OBS mixer pretty useless, so I just hide it.

I will post here when I have repacked this PR as a plugin.

@ipatix
Copy link

ipatix commented May 9, 2025

I would really love if this were added to OBS. For me it is the same case: In person events and the ability to output audio. Ideally with the ability to select which track (1-6) to output. Something that I'd also really like is to simultaneously output the different tracks to different PA evices.

The last two years I've been cherry-picking and rebasing various PR commits to make this possible. Though, the maintenance work for this is really annoying every time a new OBS version releases.

My own bits about various discussed points:

  • PulseAudio is a good API to choose, since compatibility is very good (legacy PulseAudio & newer PipeWire).
  • I wouldn't necessarly expect good latency with PA. Perhaps JACK or native PipeWire API would be better. Though, monitoring in OBS currently works with PA only, so it wouldn't be a downgrade either way.
  • Hopefully latency buildup / desync will be solved by libobs: Implement asynchronous sample rate conversion for audio #6351
  • As for Windows and Mac OS not supported: Well, no PA available on those platform, so no point in supporting that. Though, it'd certainly be handy to have WASAPI output on Windows and CoreAudio on Mac.

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

Labels

Linux Affects Linux New Feature New feature or plugin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants