How to simultaneously play audio via 2 separate HDMI output devices connected to one GPU?

I have a dual monitor setup with each monitor capable of playing audio, connected to a single RX5700XT GPU.

Right now I can select either one from the Sound settings to be the Output device.

enter image description here enter image description here

What I'm trying to do is to combine the two into one Output device so I can play audio with the two monitors simultaneously. What's the easiest way to achieve this?

Thank you.


Solution 1:

First of all, backup your PulseAudio configuration $sudo cp /etc/pulse/default.pa /etc/pulse/default.pa.bak

Once it's done, we'll check our list of hardware playback devices and take note of the ones we are looking for using $ aplay -l. Your output should look like this:

aplay -l outuput

Take note of the Card ID AND the Device ID of the outputs you want to sink together. Now we'll try and make a new sink for each one of those outputs using the alsa-sink module (you should really follow this link). Open any text editor and copy/paste:

load-module module-alsa-sink device="hw:[CARD_ID],[DEVICE_ID]" sink_name=vsink_[CARD_ID][DEVICE_ID] sink_properties="device.description='HDMI [DEVICE_ID] VSINK' device.icon_name='audio-card'"

Change the [CARD_ID] and the [DEVICE_ID] with the ones you took note in the last step. You should have as many lines of this code as outputs that you want to combine, with their respective CARD_ID and DEVICE_ID.

Once this step is done, we'll use the combine-sink module (you should follow this one too) so we can "glue" our outputs together. Copy and paste this in your editor:

load-module module-combine-sink sink_name=combined_vsink slaves=[first vskink name],[second vsink name],[n vsink name] sink_properties="device.description='[a name for your combined vsink' device.icon_name='audio-card-symbolic'"

In the end you should have something like this:

your code should look like this

Once you have your configuration done, we'll have to load it into the PulseAudio configuration (we've made a backup of it as the first thing). Open it for editing using gedit admin:///etc/pulse/default.pa and search for this section:

### Load audio drivers statically
### (it's probably better to not load these drivers manually, but instead
### use module-udev-detect -- see below -- for doing this automatically)
#load-module module-alsa-sink
...
...

You section my have a couple more commented lines if you never edited this file before. Right after the last line of that section, paste your lines. Bellow you'll find my mock ones in way that your file should look like after pasting:

### Load audio drivers statically
### (it's probably better to not load these drivers manually, but instead
### use module-udev-detect -- see below -- for doing this automatically)

load-module module-alsa-sink device="hw:0,0" sink_name=vsink_00 sink_properties="device.description='HDMI0:0 VSINK' device.icon_name='audio-card'"
load-module module-alsa-sink device="hw:0,1" sink_name=vsink_01 sink_properties="device.description='HDMI0:1 VSINK' device.icon_name='audio-card'"
load-module module-combine-sink sink_name=combined_vsink0 slaves=vsink_00,vsink_01 sink_properties="device.description='HDMI0:0 + HDMI0:1' device.icon_name='audio-card-symbolic'"

Now that we've done that, for it to work consistently we'll have to deactivate the PulseAudio udev-detect module (that's the last one, I promise) so it doesn't override the changes we did manually while trying to configure the system. You'll find a section like this one, make sure to comment all of its lines:

### Automatically load driver modules depending on the hardware available
#.ifexists module-udev-detect.so
#load-module module-udev-detect
#.else
### Use the static hardware detection module (for systems that lack udev support)
#load-module module-detect
#.endif

Now, to finish our editing, just set your new sink as the default one in the very last line of your file:

set-default-sink combined_vsink0

Save the file and then let's restart PulseAudio and check if everything is working using pulseaudio --kill && pulseaudio --start and then make sure to check if your levels are set right at alsamixer as it sometimes load new outputs muted by default. Once you're done, check your system settings to select the newly created output.

If you face any problems, you can always revert your PulseAudio configuration using the backup file I'm sure you created as your first step.

Solution 2:

Simplifying the brilliant accepted answer, copy-paste the following function:

# $@:   List of sinks to combine, as `CARD_ID:DEVICE_ID`
__os_audio_sinks_combine() {
  unset sink_names
  for i; do
    curr_sink_id="${i%%:*}"
    curr_device_id="${i#*:}"
    
    curr_device_name="hw:${curr_sink_id},${curr_device_id}"
    
    curr_sink_name="vsink_${curr_sink_id}${curr_device_id}"
    
    test -n "${sink_names}" && sink_names="${sink_names},"
    sink_names="${sink_names}${curr_sink_name}"
    
    curr_device_desc="HDMI ${curr_device_id} VSINK"
    
    echo "load-module module-alsa-sink device=\"${curr_device_name}\" sink_name=${curr_sink_name} sink_properties=\"device.description='${curr_device_id}' device.icon_name='audio-card'\""
  done

  echo "load-module module-combine-sink sink_name=combined_vsink slaves=${sink_names} sink_properties=\"device.description='comb_vsink' device.icon_name='audio-card-symbolic'\""
}

Then, as above, (1) backup the config, (2) find the respective sinks you want to combine, (3) generate config (it's automatically copied to the clipboard using xclip) and (4) edit as above:

sudo cp /etc/pulse/default.pa /etc/pulse/default.pa.bak
aplay -l

__os_audio_sinks_combine 0:9 0:10 | xclip -sel clipboard
sudo editor /etc/pulse/default.pa