On windows some laptops have the option to enable the playback of different audio streams on different audio outputs, for example you could listen to a video call in the browser through your wired headphones, while playing music from Spotify on the internal speakers.
Such option can have a different name depending on the sound card or laptop's vendor, for my laptop, an HP Omen 15-dc100xxx with a ALC295 card it is called multistreaming and can be enabled from the OMEN Audio Control program.
Here's some screenshot showcasing that feature on Windows:
And this is how you route programs' audio to an individual output:
On Linux I didn't have such an option, so can only listen one output at a time
That is:
- You have to unplug your wired speakers/headphones to be able to play anything from the internal speakers,
- And if you connect a wired speakers/headphones:
If you follow until the end of section 2 disable Headphone jack detection for speakers
- Allow switching between ports Speakers and Headphones (only one port can play audio at a time)
- Previously unavailable port becomes available for selection e.g Speakers port while Headphones are connected
If you follow till the end (the real deal)
- Have a separate audio sink for each output (ports become actual sinks)
- Per sink volume control
- Play different audio streams on each output, simultaneously (e.g. Spotify on speakers and Firefox on Headphones)
Note: The program used in above screenshots is pavucontrol-qt
- Software
- PipeWire
- alsa-card-profiles
- alsa-utils
- alsa-tools
- pavucontrol
- Patience
Important
It is recommended that you keep these the output of these commands organized in a file somewhere in case you get stuck and need help.
When requesting help you must follow the Help request issue template.
Run pactl list cards and save the output somewhere, bellow is a stripped
version of mine to keep the important things
Card #46
Name: alsa_card.pci-0000_00_1f.3
Driver: alsa
Properties:
api.alsa.path = "hw:0"
device.product.id = "0xa348"
device.vendor.id = "0x8086"
...
Profiles:
output:analog-stereo+input:analog-stereo: Analog Stereo Duplex (sinks: 1, sources: 1, priority: 6565, available: yes)
output:analog-stereo: Analog Stereo Output (sinks: 1, sources: 0, priority: 6500, available: yes)
input:analog-stereo: Analog Stereo Input (sinks: 0, sources: 1, priority: 65, available: yes)
pro-audio: Pro Audio (sinks: 4, sources: 1, priority: 1, available: yes)
Active Profile: output:analog-stereo+input:analog-stereo
Ports:
analog-output-speaker: Speakers (type: Speaker, priority: 10000, latency offset: 0 usec, availability group: Legacy 3, availability unknown)
Properties:
port.type = "speaker"
port.availability-group = "Legacy 3"
device.icon_name = "audio-speakers"
card.profile.port = "2"
Part of profile(s): output:analog-stereo, output:analog-stereo+input:analog-stereo
analog-output-headphones: Headphones (type: Headphones, priority: 9900, latency offset: 0 usec, availability group: Legacy 4, availability unknown)
Properties:
port.type = "headphones"
port.availability-group = "Legacy 4"
device.icon_name = "audio-headphones"
card.profile.port = "3"
Part of profile(s): output:analog-stereo, output:analog-stereo+input:analog-stereoCard details:
Name: alsa_card.pci-0000_00_1f.3
Ports: analog-output-speaker analog-output-headphones
Profiles: output:analog-stereo input:analog-stereo output:analog-stereo+input:analog-stereo
device.product.id = "0xa348"
device.vendor.id = "0x8086"As we can see, this laptop has three audio profiles, one for all audio outputs and other for all inputs, with an extra one that has both inputs and outputs (yours may vary)
Run pactl list sinks and save the output, bellow is a stripped
version of mine to keep the important things
Sink #47
State: RUNNING
Name: alsa_output.pci-0000_00_1f.3.analog-stereo
Description: Built-in Audio Analog Stereo
Driver: PipeWire
...
Ports:
analog-output-speaker: Speakers (type: Speaker, priority: 10000, availability group: Legacy 3, not available)
analog-output-headphones: Headphones (type: Headphones, priority: 9900, availability group: Legacy 4, available)
Active Port: analog-output-headphones
Formats:
pcmSink details:
Name: alsa_output.pci-0000_00_1f.3.analog-stereo
Ports: analog-output-speaker analog-output-headphones
Active Port: analog-output-headphonesAs we can see, there is only one audio sink alsa_output.pci-0000_00_1f.3.analog-stereo that can play audio on the two ports analog-output-speaker analog-output-headphones individually (yours may vary)
Note: alsa-card-profile files are provided by alsa-card-profiles package
-
First copy the contents of folder
/usr/share/alsa-card-profile/mixer/paths/to/etc/alsa-card-profile/mixer/paths/mkdir -p /etc/alsa-card-profile/mixer/ sudo cp -r /usr/share/alsa-card-profile/mixer/paths/ /etc/alsa-card-profile/mixer/
-
Next we need to modify the mixer path in
/etc/alsa-card-profile/mixer/paths/that matches the speakers port, in my case isanalog-output-speaker.It is crucial to pick the correct one, to verify you did:
Change
description-keyvalue to something else (e.g. by removing the last letter) and restart pipewire (systemctl restart --user pipewire pipewire-pulse pipewire.socket wireplumber). In my case it'sdescription-key = analog-output-speakerThe mixer path file name will show in pavucontrol or
pactl list sinksinstead of the actual port name andtype:will becomeUnknown:# BEFORE changing description-key Ports: analog-output-speaker: Speakers (type: Speaker, priority: 10000, availability group: Legacy 4, available) # AFTER changing description-key Ports: analog-output-speaker: analog-output-speaker (type: Unknown, priority: 10000, availability group: Legacy 4, available)
Once verified, change the
description-keyback to the default value -
Delete all the other files in
/etc/alsa-card-profile/mixer/paths/leaving only your mixer path (in my case isanalog-output-speaker.conf) and the common file e.g:sudo find /etc/alsa-card-profile/mixer/paths/ -type f ! -name 'analog-output-speaker.conf' ! -name 'analog-output.conf.common' -exec rm -f {} +
-
Edit the mixer path (in my case is
analog-output-speaker.conf) to disable Jack detection and auto-muting:-
Set
state.plugged = unknowninside the Jack section that best matches the wired port name of your card, in my case isanalog-output-headphonesso I use[Jack Headphone]one:[Jack Headphone] state.plugged = unknown state.unplugged = unknown
-
Comment (by adding semi-colon on start of line) the Element section that matches the port
[Jack ...]in my case is[Element Headphone]:; [Element Headphone] ; switch = off ; volume = off
NOTE Depending on the version of your audio related packages (specific package and versions is unknown) this change may not be needed and cause both outputs to play audio at the same time, if it happens to you, revert this change and try step 5 again.
For reference, these are the package versions on my system where the above change wasn't needed:
Expand
$ pacman -Q $(pacman -Qsq "alsa-*|pipewire|wireplumber") alsa-card-profiles 1:1.4.2-1 alsa-lib 1.2.14-1 alsa-plugins 1:1.2.12-4 alsa-tools 1.2.14-1 alsa-topology-conf 1.2.5.1-4 alsa-ucm-conf 1.2.14-2 alsa-utils 1.2.14-1 easyeffects 7.2.3-2 gst-plugin-pipewire 1:1.4.2-1 kpipewire 6.3.5-1 lib32-alsa-lib 1.2.14-1 lib32-alsa-plugins 1.2.12-1 lib32-libpipewire 1:1.4.2-1 lib32-pipewire 1:1.4.2-1 libpipewire 1:1.4.2-1 libwireplumber 0.5.10-1 pipewire 1:1.4.2-1 pipewire-alsa 1:1.4.2-1 pipewire-audio 1:1.4.2-1 pipewire-jack 1:1.4.2-1 pipewire-pulse 1:1.4.2-1 qemu-audio-alsa 10.0.0-5 qemu-audio-pipewire 10.0.0-5 wireplumber 0.5.10-1
-
-
Save the changes and restart the audio server by running:
systemctl restart --user pipewire pipewire-pulse pipewire.socket wireplumber
NOTE Applications that play/record audio need to be restarted every time you run the command above
If everything went well you should have the speaker option available without having to unplug your wired device and:
- Should be able to switch and play sound on both outputs (one at a time)
- Audio streams should still change automatically from speakers to your wired output and vice versa when plugging/unplugging a wired device
Congratulations! We're closer to our final goal, but you may stop here if this was your desired behavior 🙂
Continue to 3 Splitting for simultaneous playback with alsa firmware patch for the real deal
Skip this section if both outputs play sound when you switch ports without having to unplug either of them
In some cards, connecting multiple outputs causes one of them to stop working (see Issue #19: Lineout output doesn't work while headphones are plugged in), setting model=dual-codecs may help:
-
Create the following file:
/etc/modprobe.d/alsa-base.confoptions snd-hda-intel model=dual-codecs
-
Reboot to apply the changes and verify again 2.1 Verify it worked
3 Splitting for simultaneous playback with alsa firmware patch (for different applications on each port)
First we need to identify and check if our card has more than one sub device and test if sound comes out of them
Run
aplay -lYou'll get something like the following
**** List of PLAYBACK Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: ALC295 Analog [ALC295 Analog]
Subdevices: 1/1
Subdevice #0: subdevice #0
...At this point, my card card 0 (ALC295), has only one sub device, you may have more, take note of this information as we'll need it later
We can confirm the playback (output) and capture (input) streams the card currently has with cat /proc/asound/pcm
00-00: ALC295 Analog : ALC295 Analog : playback 1 : capture 1
...- Run
hdajackretask - In the Select a codec drop-down select your card
- In the Options section check
Parser hints - In the Hints list set
indep_hpand `` to yes with double click on them. - Press
Install boot override - Open the file
/lib/firmware/hda-jack-retask.fwand addvmaster=nobelowindep_hp=yes - Reboot to apply the changes
Run
cat /proc/asound/card*/codec#* | grep -E 'Codec|Vendor Id|Subsystem Id|Address'You'll get the codecs in the following format, pick the one that matches your card (mine is the Realtek ALC295):
Codec: Realtek ALC295
Address: 0
Vendor Id: 0x10ec0295
Subsystem Id: 0x103c8575
...With the above we can start creating our patch file:
-
Create the following file (don't copy as is, modify according to explanation bellow):
/lib/firmware/hda-jack-retask.fw[codec] 0x10ec0295 0x103c8575 0 [hints] indep_hp=yes vmaster=no
Below
[codec]line we should put the values ofVendor Id, theSubsystem IdandAddressof the card, separated by spaces.Below
[hints]we need to add what is called hint strings-
indep_hp=yesthis will make for our jack output to be detected as an independent PCM stream with its own controls (meaning it will split away from internal speakers as a separate audio sink for us to play specific app stream on it). -
vmaster=nowill disable the virtual Master control so we can control volume on each port individually.
-
-
Create/edit the following file:
/etc/modprobe.d/alsa-base.confoptions snd-hda-intel patch=hda-jack-retask.fwNOTE If you have
options snd-hda-intel model=dual-codecsfrom 2 disable Headphone jack detection for speakers keep it and add the above one below it. -
Reboot to apply the changes
For immutable distros /lib/firmware/ is not writable. As a workaround you can use an udev rule that sets the hints on boot. This method may cause some noises during boot and is not guaranteed to be as reliable as the firmware one, if that's the case for you, suggestions to improve it are welcome
-
Create the file
/etc/udev/rules.d/91-pipewire-alsa-port-split.rules(don't copy as is, modify according to explanation bellow)SUBSYSTEM!="sound", GOTO="pipewire_end" ACTION!="change", GOTO="pipewire_end" KERNEL!="card*", GOTO="pipewire_end" SUBSYSTEMS=="pci", ATTRS{vendor}=="0x8086", ATTRS{device}=="0xa348", \ RUN+="/usr/local/bin/alsa-split-ports.sh" LABEL="pipewire_end"
Replace
0x8086and0xa348with the values ofdevice.vendor.idanddevice.product.idthat you got frompactl list cardsin 1.1 Gather some information about the card -
Create the script
/usr/local/bin/alsa-split-ports-hints.shand setVENDOR_IDandSUBSYSTEN_IDwith the ones from your card fromcat /proc/asound/card*/codec#* | grep -E 'Codec|Vendor Id|Subsystem Id|Address'.#!/usr/bin/env bash VENDOR_ID="0x10ec0295" SUBSYSTEN_ID="0x103c8575" HINTS="indep_hp = yes vmaster = no " # log output to system log exec 1> >(logger -s -t "$(basename "$0")") 2>&1 get_codec() { local vendor_id=$1 local subsystem_id=$2 [[ -z "$vendor_id" || -z "$subsystem_id" ]] && { echo "ERROR: Not enough arguments given"; return; } for hw in /sys/class/sound/card*/hwC*D*; do if grep -q "$vendor_id" "$hw/vendor_id" && grep -q "$subsystem_id" "$hw/subsystem_id"; then echo "Found matching codec: $hw $(cat "$hw"/vendor_name) - $(cat "$hw"/chip_name) Vendor Id: $(cat "$hw"/vendor_id) Subsystem Id: $(cat "$hw"/subsystem_id)" codec=$hw break fi done } codec="" get_codec "$VENDOR_ID" "$SUBSYSTEN_ID" if [[ -z "$codec" ]]; then echo "ERROR: Could not get codec for VENDOR_ID: $VENDOR_ID SUBSYSTEN_ID: $SUBSYSTEN_ID" echo "Codecs found:" for hw in /sys/class/sound/card*/hwC*D*; do echo "$hw" "$(cat "$hw"/vendor_name)" - "$(cat "$hw"/chip_name)" Vendor Id: "$(cat "$hw"/vendor_id)" Subsystem Id: "$(cat "$hw"/subsystem_id)" done exit 1 fi while IFS=$'\n' read -r line; do if [[ -z "$line" ]]; then continue fi echo "$line > ${codec}/hints" echo "$line" > "${codec}"/hints done <<< "$HINTS" echo "echo 1 > ${codec}/reconfig" echo 1 > "${codec}"/reconfig # give some time to intialize before restoring sleep 5 alsactl restore
-
Reboot to apply the changes
-
To verify that the udev rule and the script are configured properly check the system logs for the script output:
journalctl -b --no-pager | grep -E 'alsa-split-ports.sh|snd_hda|Sound Card'Example of working output
Sep 15 23:44:44 archlinux kernel: snd_hda_intel 0000:00:1f.3: enabling device (0000 -> 0002)
Sep 15 23:44:44 archlinux kernel: snd_hda_intel 0000:00:1f.3: bound 0000:00:02.0 (ops intel_audio_component_bind_ops [i915])
Sep 15 23:44:44 archlinux kernel: snd_hda_intel 0000:01:00.1: enabling device (0000 -> 0002)
Sep 15 23:44:44 archlinux kernel: snd_hda_intel 0000:01:00.1: Disabling MSI
Sep 15 23:44:44 archlinux kernel: snd_hda_intel 0000:01:00.1: Handle vga_switcheroo audio client
Sep 15 23:44:44 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: ALC295: picked fixup for PCI SSID 103c:0000
Sep 15 23:44:44 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: autoconfig for ALC295: line_outs=1 (0x17/0x0/0x0/0x0/0x0) type:speaker
Sep 15 23:44:44 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: speaker_outs=0 (0x0/0x0/0x0/0x0/0x0)
Sep 15 23:44:44 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: hp_outs=1 (0x21/0x0/0x0/0x0/0x0)
Sep 15 23:44:44 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: mono: mono_out=0x0
Sep 15 23:44:44 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: inputs:
Sep 15 23:44:44 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: Internal Mic=0x12
Sep 15 23:44:44 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: Mic=0x19
Sep 15 23:44:44 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: Mic=0x1b
Sep 15 23:44:45 archlinux alsa-split-ports.sh[1421]: Found matching codec: /sys/class/sound/card0/hwC0D0 Realtek - ALC295 Vendor Id: 0x10ec0295 Subsystem Id: 0x103c8575
Sep 15 23:44:45 archlinux alsa-split-ports.sh[1421]: indep_hp = yes > /sys/class/sound/card0/hwC0D0/hints
Sep 15 23:44:45 archlinux alsa-split-ports.sh[1421]: vmaster = no > /sys/class/sound/card0/hwC0D0/hints
Sep 15 23:44:45 archlinux alsa-split-ports.sh[1421]: echo 1 > /sys/class/sound/card0/hwC0D0/reconfig
Sep 15 23:44:45 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: hda-codec: reconfiguring
Sep 15 23:44:45 archlinux systemd[1]: Starting Save/Restore Sound Card State...
Sep 15 23:44:45 archlinux systemd[1]: Manage Sound Card State (restore and store) was skipped because of an unmet condition check (ConditionPathExists=/etc/alsa/state-daemon.conf).
Sep 15 23:44:45 archlinux systemd[1]: Finished Save/Restore Sound Card State.
Sep 15 23:44:45 archlinux systemd[1]: Reached target Sound Card.
Sep 15 23:44:45 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: autoconfig for ALC295: line_outs=1 (0x17/0x0/0x0/0x0/0x0) type:speaker
Sep 15 23:44:45 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: speaker_outs=0 (0x0/0x0/0x0/0x0/0x0)
Sep 15 23:44:45 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: hp_outs=1 (0x21/0x0/0x0/0x0/0x0)
Sep 15 23:44:45 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: mono: mono_out=0x0
Sep 15 23:44:45 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: inputs:
Sep 15 23:44:45 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: Internal Mic=0x12
Sep 15 23:44:45 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: Mic=0x19
Sep 15 23:44:45 archlinux kernel: snd_hda_codec_realtek hdaudioC0D0: Mic=0x1bRun again
aplay -lYou should get something like the following
**** List of PLAYBACK Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: ALC295 Analog [ALC295 Analog]
Subdevices: 0/1
Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 2: ALC295 Alt Analog [ALC295 Alt Analog]
Subdevices: 1/1
Subdevice #0: subdevice #0Now the card ALC295 (card 0), has an extra device (2), interesting...
Run cat /proc/asound/pcm, if there is a new sub device and has a playback sub-stream (playback 1) like below you can continue
00-00: ALC295 Analog : ALC295 Analog : playback 1 : capture 1
00-02: ALC295 Alt Analog : ALC295 Alt Analog : playback 1
...-
Stop the audio services (may need to stop it multiple times if it gets automatically restarted):
systemctl --user stop pipewire.service pipewire.socket pipewire-pulse.service pipewire-pulse.socket wireplumber.service
-
Plug-in your wired audio device then run
alsamixer -c0(replace 0 with your card number if needed)- Un-mute any muted device (the ones with MM below the volume slider) by pressing
m - Increase their volume to around 30 if the're on 0
- Enable
Independent HPif is not enabled - Press
Escto exit.
- Un-mute any muted device (the ones with MM below the volume slider) by pressing
-
Finally, save it by running
sudo alsactl store
-
Run
speaker-test -Dhw:0,0 -c2(replace 0,0 with the card number and device numbers from your card fromaplay -l)For the device 0 (speaker-test -Dhw:0,0 -c2) the sound comes out from the speakers, so
device 0is the speakers -
Repeat for all the devices for your card and note which device corresponds to which physical output
So my card's outputs are the following (yours may vary):
- Device
0,0(card 0, device 0) handles Speakers (and also microphones, as we saw incat /proc/asound/pcm) - Device
0,2(card 0, device 2) handles Headphones
Card details:
Name: alsa_card.pci-0000_00_1f.3
Ports: analog-output-speaker analog-output-headphones
Profiles: output:analog-stereo input:analog-stereo output:analog-stereo+input:analog-stereoSink details:
Name: alsa_output.pci-0000_00_1f.3.analog-stereo
Ports: analog-output-speaker analog-output-headphones
Active Port: analog-output-headphonesCard sub devices and playback (outputs) / capture (inputs) location:
**** List of PLAYBACK Hardware Devices ****
card 0: PCH [HDA Intel PCH], device 0: ALC295 Analog [ALC295 Analog]
Subdevices: 0/1
Subdevice #0: subdevice #0
card 0: PCH [HDA Intel PCH], device 2: ALC295 Alt Analog [ALC295 Alt Analog]
Subdevices: 1/1
Subdevice #0: subdevice #000-00: ALC295 Analog : ALC295 Analog : playback 1 : capture 1
00-02: ALC295 Alt Analog : ALC295 Alt Analog : playback 1
...So in my case I have:
- Two ports:
analog-output-speaker analog-output-headphones - Device locations for the card 0 correspond to:
- Device
0,0(card 0, device 0) Speakers (also handles microphones) - Device
0,2(card 0, device 2) Headphones
- Device
-
Rename your mixer path file from 2 disable Headphone jack detection for speakers like below:
sudo mv /etc/alsa-card-profile/mixer/paths/analog-output-speaker.conf /etc/alsa-card-profile/mixer/paths/analog-output-speaker-split.conf
-
Now create the file
/etc/alsa-card-profile/mixer/profile-sets/split-ports-profile.confsudo mkdir /etc/alsa-card-profile/mixer/profile-sets/ sudo touch /etc/alsa-card-profile/mixer/profile-sets/split-ports-profile.conf
-
Open split-ports-profile.conf with your preferred editor, paste the following and adapt it to your system according to the comments:
; This will let alsa generate automatic profiles (e.g internal speaker + microphone) [General] auto-profiles = yes ; device-strings describes the ALSA device string(s) that PulseAudio uses to open the device, where "%f" specifies the card number (should always be present in the string). ; This is the mapping for the internal speaker ; If needed, change the 0 in "hw:%f,0" to your sub device location ; You can change the description for this and other mappings if you want, ; in paths output put the name of the previously created custom mixer path [Mapping analog-stereo-speaker] description = Speakers device-strings = hw:%f,0 paths-output = analog-output-speaker-split channel-map = left,right direction = output ; This is the mapping for the jack output (headphones) ; If needed, change the 2 in "hw:%f,2" to your sub device location, ; in paths output put the name of the port from card details [Mapping analog-stereo-headphones] description = Headphones device-strings = hw:%f,2 paths-output = analog-output-headphones channel-map = left,right direction = output ; This is the mapping that will handle internal and external microphones, as you could see in `cat /proc/asound/pcm`, the card also had a capture port ; in the 0,0 sub device location so let's add it here too (change the 0 in "hw:%f,0" to your sub device location that has the capture port) ; All the paths-input names here came from the default.conf profile set and you may have to adapt it if your input port name is not included [Mapping analog-stereo-input] description = Microphone device-strings = hw:%f,0 channel-map = left,right paths-input = analog-input-front-mic analog-input-rear-mic analog-input-internal-mic analog-input-dock-mic analog-input analog-input-mic analog-input-linein analog-input-aux analog-input-video analog-input-tvtuner analog-input-fm analog-input-mic-line analog-input-headphone-mic analog-input-headset-mic direction = input ; Broken in parts the profile name means to join ; The name of the Mapping containing the analog-output-headphones (output:analog-stereo-headphones) ; The name of the Mapping containing the analog-output-speaker (output:analog-stereo-speaker) ; The name of the Mapping containing the analog-stereo-input (input:analog-stereo-input) ; in output-mappings put the name of the output mappings ; input-mappings put the name of the input mappings ; NOTE: Not to be confused width the paths-output/paths-input values inside the mapping, we're not using those directly ; This is the profile that will have the internal speakers + jack output + all microphones ; in paths output put the name of the from card details [Profile output:analog-stereo-headphones+output:analog-stereo-speaker+input:analog-stereo-input] description = Analog Stereo Duplex output-mappings = analog-stereo-headphones analog-stereo-speaker input-mappings = analog-stereo-input priority = 80 ; This profile will have the internal speakers + jack output, but not microphones [Profile output:analog-stereo-headphones+output:analog-stereo-speaker] description = Analog Stereo Outputs Only output-mappings = analog-stereo-headphones analog-stereo-speaker priority = 70
-
Create the file
/etc/udev/rules.d/91-pipewire-alsa-port-split.rules(don't copy as is, modify according to explanation bellow). Also, if using the udev rule to apply hints from Using script and udev rule for immutable distros you can use the commented rule instead.SUBSYSTEM!="sound", GOTO="pipewire_end" ACTION!="change", GOTO="pipewire_end" KERNEL!="card*", GOTO="pipewire_end" SUBSYSTEMS=="pci", ATTRS{vendor}=="0x8086", ATTRS{device}=="0xa348", \ ENV{ACP_PROFILE_SET}="/etc/alsa-card-profile/mixer/profile-sets/split-ports-profile.conf" # Use this instead for immutable distributions # SUBSYSTEMS=="pci", ATTRS{vendor}=="0x8086", ATTRS{device}=="0xa348", \ # ENV{ACP_PROFILE_SET}="/etc/alsa-card-profile/mixer/profile-sets/split-ports-profile.conf" \ # RUN+="/usr/local/bin/alsa-split-ports.sh" LABEL="pipewire_end"
Replace
0x8086and0xa348with the values ofdevice.vendor.idanddevice.product.idthat you got frompactl list cardsin 1.1 Gather some information about the card -
Reboot to apply the changes
Open pavucontrol and in the Configuration tab select the Analog Stereo Duplex profile for your card
Run
pactl list sinks | grep -E 'Name|Desc|State|Port|device.profile-set'I everything went well you should have a separate audio sink for each output:
State: IDLE
Name: alsa_output.pci-0000_00_1f.3.analog-stereo-headphones
Description: Built-in Audio Headphones
device.profile-set = "/etc/alsa-card-profile/mixer/profile-sets/split-ports-profile.conf"
Ports:
Active Port: analog-output-headphones
State: SUSPENDED
Name: alsa_output.pci-0000_00_1f.3.analog-stereo-speaker.2
Description: Built-in Audio Speakers
device.profile-set = "/etc/alsa-card-profile/mixer/profile-sets/split-ports-profile.conf"
Ports:
Active Port: analog-output-speaker-splitIf there is no device.profile-set = "/etc/alsa-card-profile/mixer/profile-sets/split-ports-profile.conf, double check the vendor and device values in the udev rule.
Now you should be able to play different applications on each sink, you can do that with pavucontrol or KDE's Audio Volume widget. Congratulations! 🎉
If you faced any problems or are stuck please open a new issue, you MUST follow the Help request issue template.
This guide is the result of days of effort hunting for the right information and lots of reading. If it was useful to you consider making a small donation







