我试图创建一个脚本来监控pipewire音频源,并提供与音量的“百分比”有关的输出。由于我使用的是pipewire和wireplumber,所以我决定使用pipewire提供的pw-mon
进行监控,使用wireplumber提供的wpctl
来完成监控。
pw-mon | while read; do
# wpctl returns output as Volume: 0.00 [MUTED] where 0.00 is the volume, and [MUTED] is irrelevant for our case.
# I process via cut to get the second field.
awk '{print $1 * 100}' <<< $(wpctl get-volume @DEFAULT_AUDIO_SINK@ | cut -d" " -f2)
done
这样做的主要问题是pw-mon
返回许多关于其设备状态的标准输出响应,并且作为副作用,awk必须处理数十次,因为while read
从pw-mon
标准输出中获取了许多行。我想防止这种情况,并且只打印一次,所以基本上压缩了pw-mon
的所有标准输出,因此while
只运行一次,然后反过来也只处理我的awk
一次。问题是我不知道该怎么做
我尝试从https://stackoverflow.com/a/68091645/9091276使用tr -d "\r\n"
,但while read
不再运行(我通过执行while read l; do echo $l; done
确保这一点)。我想在while
循环中添加一个sleep,但这没有意义,因为它只会延迟对pw-mon
标准输出行的阅读,而不是阻止对所有行的阅读。
我能做些什么?为了清楚起见,下面是pw-mon
的一些输出,这样您就可以看到它的每个事件回调会发生什么:https://hastebin.com/share/agajayosoq.rust(它不是生 rust idk为什么它说)。
编辑:让我澄清一下我想做的事情pw-mon
每次检测到音频设备的变化(音量增大/减小/静音)时,都会将一些音频设备数据发送到标准输出中。否则,pw-mon
不会输出任何数据。问题是每次发生更改时,pw-mon
都会将大量数据行转储到标准输出,这意味着,对于我当前的脚本,它将多次触发while read
。这不是我想要的,我想在每次发生更改时只运行一次“awk
“部分。我的想法是把所有的标准输出压缩到一行中,这样while read
只会触发一次,但是pw-mon | tr -d "\r\n" | while read
不起作用,因为某种原因while read不会触发。
编辑2:pw-mon
的示例输出:
type: PipeWire:Interface:Core
cookie: 2956247259
user-name: "frontear"
host-name: "frontear-net"
version: "0.3.81"
name: "pipewire-0"
* properties:
* config.name = "pipewire.conf"
* link.max-buffers = "16"
* core.daemon = "true"
* core.name = "pipewire-0"
* module.jackdbus-detect = "true"
* module.x11.bell = "true"
* module.access = "true"
* cpu.max-align = "64"
* default.clock.rate = "48000"
* default.clock.quantum = "1024"
* default.clock.min-quantum = "32"
* default.clock.max-quantum = "2048"
* default.clock.quantum-limit = "8192"
* default.video.width = "640"
* default.video.height = "480"
* default.video.rate.num = "25"
* default.video.rate.denom = "1"
* log.level = "2"
* clock.power-of-two-quantum = "true"
* mem.warn-mlock = "false"
* mem.allow-mlock = "true"
* settings.check-quantum = "false"
* settings.check-rate = "false"
* object.id = "0"
* object.serial = "0"
added:
id: 0
permissions: r-xm-
type: PipeWire:Interface:Core (version 4)
properties:
object.serial = "0"
core.name = "pipewire-0"
added:
... (omitted for brevity)
* id:15 (Spa:Enum:ParamId:Latency)
Object: size 176, type Spa:Pod:Object:Param:Latency (262155), id Spa:Enum:ParamId:Latency (15)
Prop: key Spa:Pod:Object:Param:Latency:direction (1), flags 00000000
Id 0 (Spa:Enum:Direction:Input)
Prop: key Spa:Pod:Object:Param:Latency:minQuantum (2), flags 00000000
Float 0.000000
Prop: key Spa:Pod:Object:Param:Latency:maxQuantum (3), flags 00000000
Float 0.000000
Prop: key Spa:Pod:Object:Param:Latency:minRate (4), flags 00000000
Int 0
Prop: key Spa:Pod:Object:Param:Latency:maxRate (5), flags 00000000
Int 0
Prop: key Spa:Pod:Object:Param:Latency:minNs (6), flags 00000000
Long 0
Prop: key Spa:Pod:Object:Param:Latency:maxNs (7), flags 00000000
Long 0
properties:
port.id = "0"
port.direction = "out"
object.path = "xdg-desktop-portal-hyprland:capture_0"
port.name = "capture_1"
port.alias = "xdg-desktop-portal-hyprland:capture_1"
node.id = "74"
object.id = "75"
object.serial = "377"
1条答案
按热度按时间rsl1atfo1#
从问题中得到了一些想法,比如找到初始调用和每次回调的特定数据,我找到了。由于pipewire将为我的设备打印设备id,所以我可以简单地匹配该行。
我首先使用
wpctl inspect @DEFAULT_AUDIO_SINK@
,然后通过awk -F"\"" "/device.id/{print \$2}"
将其传输到awk,以查找device.id输出并提取数字。然后,使用这个命令,我运行pw-mon -oa
来删除额外的输出(刚刚了解了这个命令),留下device.id作为它打印出来的少数几个 prop 之一,因为这是改变的设备。最后,我再次通过awk来查找带有我id的行,减少while调用。完整的代码看起来像这样: