Audio output to multiple HDMI displays

Hi,

As I explain in another thread, I want to be able to do rhythm games parties and for that, I want to mirror my computer on 2 TVs which are not in the same room. I’ve had some problems for the video, but at least, I have a workaround.

On the other hand, I haven’t found a way to send the sound in both TVs. I can choose any of the two in the gnome menu, but not both.

I also know how to use qpwgraph to send audio to multiple sources, like a TV, my headset and the speakers connected to my PC. But there is only one HDMI output at a given time.

The HDMI output is GA104. If I switch the HDMI audio output, the name changes (HDMI to HDMI2 or HDMI3) but there is still only one output available.

Is there a way to have all the outputs available? I’ve got an nvidia RTX 3070 Ti. It may be a nvidia limitation.

If anyone knows how to do it, I’m really interested.

Thanks.

Please do not open duplicate threads like this. Keep the details and conversation in one topic so everyone sees everything and avoid confusion.

I am joining this back to the previous topic since it seems directly related.

AFAIK there is only one audio output active at a time, and definitely when using audio via HDMI it seems able to be directed to only one port.

It’s not really the same problem. The video problem is a bug, probably due to Wayland. The second one is just a question about outputing audio to multiple hdmi outputs. I run into the two problems at the same time, but they are not really linked.

They are linked since it is directly related to the use of the nvidia GPU and output to HDMI. One part is audio and the other is video but it is clearly (to me) related. Both are tied to hdmi outputs.

It is two issues.
One is video, one is audio.

It is because there are two underlying systems here. (three if we include the common one, HDMI)

The linux audio stack - pipewire wireplumer and alsa are notoriously complex.

Then the compositor issue - working on X11 but not wayland.

The HDMI trying them together may have something to do with it, or maybe not. We don’t really know yet.

As you wish.

For the “only one audio output active at the same time”, it’s wrong. I use qpwgraph to send the audio to both my headset and my speakers, for example. I even use it to only output the audio of Rock Band to my speakers, because it can be annoying for my wife to only hear the sound of the drums without the music, and I keep the audio of the game and sometimes also of a podcast in my headset.

If you feel that I will move it back.
:man_facepalming:

Leave it like that. I think I have my answer for the video problem. I need to test more and report the bug. Maybe I should change the title to focus on the audio part.

Ok, back to the topic. I found this:

I’m going to try to adapt this for pipewire.

Edit: It looks like it’s working. I need to connect one of my tv to my computer to check. It creates new audio outputs and if it’s working as expected, it should be a way to access all the outputs at the same time.

I’ll write something more precise when I will have time to try with my 2 TVs, but at least, it worked with one.

First, you need to find the number of the card and the number of device of each hdmi output with aplay -l | grep card (for me it aplay -l | grep carte because my system is set to french).

I get this:

$ aplay -l | grep carte
carte 0 : NVidia [HDA NVidia], périphérique 3 : HDMI 0 [VE248]
carte 0 : NVidia [HDA NVidia], périphérique 7 : HDMI 1 [VE248]
carte 0 : NVidia [HDA NVidia], périphérique 8 : HDMI 2 [SAMSUNG]
carte 0 : NVidia [HDA NVidia], périphérique 9 : HDMI 3 [HDMI 3]
carte 1 : Wireless [Arctis Nova Pro Wireless], périphérique 0 : USB Audio [USB Audio]
carte 2 : Generic [HD-Audio Generic], périphérique 0 : ALC892 Analog [ALC892 Analog]

The two first are my monitors, the third one is one of my TV and the last one is not plugged.

I created a new output for each hdmi output. It’s useless for the monitors since they don’t have speakers, but it’s just to try.

pactl load-module module-alsa-sink device="hw:0,3" sink_name=vsink_0_3 sink_properties="device.description='HDMI 0 VSINK' device.icon_name='audio-card'"
pactl load-module module-alsa-sink device="hw:0,7" sink_name=vsink_0_7 sink_properties="device.description='HDMI 1 VSINK' device.icon_name='audio-card'"
pactl load-module module-alsa-sink device="hw:0,8" sink_name=vsink_0_8 sink_properties="device.description='HDMI 2 VSINK' device.icon_name='audio-card'"

What is important is to use hw:[CARD_NUMBER],[DEVICE_ID]. For the 4th hdmi output, I will have to use hw:0,9.

It creates outputs that I can see with qpwgraph:

I tried connecting an audio source to HDMI-2, which is my TV and it worked.

I need to try with both TVs connected, but it seems to work. I think I’ll do a script that creates the outputs when I launch the game and then that destroys them when I quit.

When you create a new ouput, you get a number that is displayed. To destroy the output, you just have to do pactl unload-module [THE_NUMBER_OF_THE_SINK].

I’ve tried with the audio sent to 2 Tvs, my headset and my speakers and it works perfectly.

Here is my solution. I made 2 scripts. The first one creates the audio sinks and the second one destroys them. I’m using environment variables to keep the ids of the sinks created.

creation_sink_audio.sh:

#!/bin/sh

if [[ "$HDMI0" == "" ]]
then
    echo "Création de la sortie HDMI0"
    export HDMI0=$(pactl load-module module-alsa-sink device="hw:0,3" sink_name=vsink_0_3 sink_properties="device.description='HDMI0 VSINK' device.icon_name='audio-card'")
else
    echo "HDMI0 existe déjà"
fi

if [[ "$HDMI1" == "" ]]
then
    echo "Création de la sortie HDMI1"
    export HDMI1=$(pactl load-module module-alsa-sink device="hw:0,7" sink_name=vsink_0_7 sink_properties="device.description='HDMI1 VSINK' device.icon_name='audio-card'")
else
    echo "HDMI1 existe déjà"
fi

if [[ "$HDMI2" == "" ]]
then
    echo "Création de la sortie HDMI2"
    export HDMI2=$(pactl load-module module-alsa-sink device="hw:0,8" sink_name=vsink_0_8 sink_properties="device.description='HDMI2 VSINK' device.icon_name='audio-card'")
else
    echo "HDMI2 existe déjà"
fi

if [[ "$HDMI3" == "" ]]
then
    echo "Création de la sortie HDMI3"
    export HDMI3=$(pactl load-module module-alsa-sink device="hw:0,9" sink_name=vsink_0_9 sink_properties="device.description='HDMI3 VSINK' device.icon_name='audio-card'")
else
    echo "HDMI3 existe déjà"
fi

if [[ "$TOUTES_SORTIES" == "" ]]
then
    echo "On fusionne toutes les sorties"
    export TOUTES_SORTIES=$(pactl load-module module-combine-sink sink_name=combined_vsink slaves=vsink_0_3,vsink_0_7,vsink_0_8,vsink_0_9,alsa_output.usb-SteelSeries_Arctis_Nova_Pro_Wireless-00.iec958-stereo,alsa_output.pci-0000_28_00.4.analog-stereo sink_properties="device.description='Toutes_sorties' device.icon_name='audio-card-symbolic'")
else
    echo "On a déjà fusinné toutes les sorties."
fi

suppression_sink_audio.sh:

#!/bin/sh

if [[ "$TOUTES_SORTIES" != "" ]]
then
    echo "Suppression de la fusion des sorties"
    pactl unload-module $TOUTES_SORTIES
    export TOUTES_SORTIES=""
fi

if [[ "$HDMI0" != "" ]]
then
    echo "Suppression de HDMI0"
    pactl unload-module $HDMI0
    export HDMI0=""
fi

if [[ "$HDMI1" != "" ]]
then
    echo "Suppression de HDMI1"
    pactl unload-module $HDMI1
    export HDMI1=""
fi

if [[ "$HDMI2" != "" ]]
then
    echo "Suppression de HDMI2"
    pactl unload-module $HDMI2
    export HDMI2=""
fi

if [[ "$HDMI3" != "" ]]
then
    echo "Suppression de HDMI3"
    pactl unload-module $HDMI3
    export HDMI3=""
fi

I’ve made an alias to launch rpcs3 with these scripts:

alias rpcs3alloutputs='source creation_sink_audio.sh; PULSE_LATENCY_MSEC=1 PATH_TO_RPCS3/rpcs3; source suppression_sink_audio.sh'

I just need to find a way to automaticaly switch the output from the command line.