LIBPIPEWIRE-MODULE-COMBINE-STREAM(7)
π libpipewire-module-combine-stream β Combine Stream π
okay bestie, so this is a page from the Miscellaneous Information Manual and it's about libpipewire-module-combine-stream, and honestly? it's giving main character energy for your audio setup. let's get into it π
β¨ NAME β¨
libpipewire-module-combine-stream β Combine Stream. that's it, that's the name, short and iconic π
πΈ DESCRIPTION πΈ
the combine stream module can make:
- a new virtual sink that forwards audio to other sinks
- a new virtual source that combines audio from other sources
the sources and sink that need to be combined can be selected using generic match rules. which is lowkey the best part, because it means you can combine static nodes, or nodes based on certain properties. no cap. π¦
π MODULE NAME π
libpipewire-module-combine-stream
β¨ MODULE OPTIONS β¨
node.nameβ a unique name for the stream. make it cute, make it yours.node.descriptionβ a human readable name for the stream (aka the one your friends will actually see).combine.mode = capture | playback | sink | source, defaultsinkβ pick your fighter.combine.latency-compensateβ use delay buffers to match stream latencies. yes, it lines them up, gorgeous.combine.on-demand-streamsβ use metadata to create streams on demand.combine.props = {}β properties to be passed to the sink/source.stream.props = {}β properties to be passed to the streams.stream.rules = {}β rules for matching streams, usecreate-streamactions.
π GENERAL OPTIONS π
options with well-known behavior. the classics, the OGs.
remote.nameaudio.channelsaudio.layoutaudio.positionmedia.namenode.latencynode.namenode.descriptionnode.groupnode.virtualmedia.class
π¦ STREAM OPTIONS π¦
audio.positionβ set the stream channel map. by default this is the same channel map as the combine stream. you can also useaudio.layout. periodt.combine.audio.positionβ map the combine audio positions to the stream positions. combine input channels are mapped one-by-one to stream output channels. you can also usecombine.audio.layout. iykyk πΈ
π EXAMPLE CONFIGURATION π
okay so here's the first one, a whole little config for you. slay.
# ~/.config/pipewire/pipewire.conf.d/my-combine-stream-1.conf
context.modules = [
{ name = libpipewire-module-combine-stream
args = {
combine.mode = sink
node.name = "combine_sink"
node.description = "My Combine Sink"
combine.latency-compensate = false
combine.props = {
audio.position = [ FL FR ]
}
stream.props = {
}
stream.rules = [
{
matches = [
# any of the items in matches needs to match, if one does,
# actions are emitted.
{
# all keys must match the value. ! negates. ~ starts regex.
#node.name = "~alsa_input.*"
media.class = "Audio/Sink"
}
]
actions = {
create-stream = {
#combine.audio.position = [ FL FR ]
#audio.position = [ FL FR ]
}
}
}
]
}
}
]
below is an example configuration that makes a 5.1 virtual audio sink from 3 separate stereo sinks. the way that it just... combines three whole sinks into one?? obsessed. π
# ~/.config/pipewire/pipewire.conf.d/my-combine-stream-2.conf
context.modules = [
{ name = libpipewire-module-combine-stream
args = {
combine.mode = sink
node.name = "combine_sink_5_1"
node.description = "My 5.1 Combine Sink"
combine.latency-compensate = false
combine.props = {
audio.position = [ FL FR FC LFE SL SR ]
}
stream.props = {
stream.dont-remix = true # link matching channels without remixing
}
stream.rules = [
{ matches = [
{ media.class = "Audio/Sink"
node.name = "alsa_output.usb-Topping_E30-00.analog-stereo"
} ]
actions = { create-stream = {
combine.audio.position = [ FL FR ]
audio.position = [ FL FR ]
} } }
{ matches = [
{ media.class = "Audio/Sink"
node.name = "alsa_output.usb-BEHRINGER_UMC404HD_192k-00.pro-output-0"
} ]
actions = { create-stream = {
combine.audio.position = [ FC LFE ]
audio.position = [ AUX0 AUX1 ]
} } }
{ matches = [
{ media.class = "Audio/Sink"
node.name = "alsa_output.pci-0000_00_1b.0.analog-stereo"
} ]
actions = { create-stream = {
combine.audio.position = [ SL SR ]
audio.position = [ FL FR ]
} } }
]
}
}
]
and below is an example configuration that makes a 4.0 virtual audio source from 2 separate stereo sources. she flipped it, we love a source moment. π₯
# ~/.config/pipewire/pipewire.conf.d/my-combine-stream-3.conf
context.modules = [
{ name = libpipewire-module-combine-stream
args = {
combine.mode = source
node.name = "combine_source_4_0"
node.description = "My 4.0 Combine Source"
combine.props = {
audio.position = [ FL FR SL SR ]
}
stream.props = {
stream.dont-remix = true
}
stream.rules = [
{ matches = [
{ media.class = "Audio/Source"
node.name = "alsa_input.usb-046d_HD_Pro_Webcam_C920_09D53E1F-02.analog-stereo"
} ]
actions = { create-stream = {
audio.position = [ FL FR ]
combine.audio.position = [ FL FR ]
} } }
{ matches = [
{ media.class = "Audio/Source"
node.name = "alsa_input.usb-046d_0821_9534DE90-00.analog-stereo"
} ]
actions = { create-stream = {
audio.position = [ FL FR ]
combine.audio.position = [ SL SR ]
} } }
]
}
}
]
π«Ά quick vibe check bestie: go forth and combine your streams. you literally cannot mess this up, you have the whole config.
okay and that's a wrap on the libpipew...ne-stream(7) page π
this came to you from PipeWire version 1.6.11 β mwah, love that for you, go stream something (literally). bye bestie!! ππβ¨π
π¦ where this page comes from
- fedora 44: pipewire-libs 1.6.11-1.fc44 Β· MIT AND GPL-2.0-or-later AND BSD-2-Clause AND LGPL-2.0-or-later
- fedora 44: pipewire-libs 1.6.11-1.fc44 Β· MIT AND GPL-2.0-or-later AND BSD-2-Clause AND LGPL-2.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms