在 while 循环中处理时吞下来自监控回调的输入

问题描述 投票:0回答:1

我正在尝试创建一个脚本来监视管道音频源,并提供与音量“百分比”相关的输出。由于我使用的是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
循环中添加睡眠,但这没有意义,因为它只会延迟
pw-mon
标准输出行的读取,而不是阻止读取所有这些行。

对于我能做什么有什么想法或想法吗?为了清楚起见,这里有一些来自

pw-mon
的输出,这样你就可以看到每个事件回调发生了什么:https://hastebin.com/share/agajayosoq.rust(它不是 rust,我不知道为什么这么说)。

编辑:让我澄清一下我想要做什么

每次检测到音频设备发生更改(音量调高/调低/静音)时,

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"
shell unix posix pipewire
1个回答
0
投票

从问题中得到了一些想法,例如查找特定于初始调用和每个回调的数据,我找到了它。由于 Pipewire 将打印发生更改的设备的设备 ID,因此我可以简单地匹配该行。

我首先使用

wpctl inspect @DEFAULT_AUDIO_SINK@
,然后通过
awk -F"\"" "/device.id/{print \$2}"
通过 awk 进行管道传输,找到 device.id 输出并提取数字。然后,使用它,我运行
pw-mon -oa
来删除额外的输出(刚刚了解了这个命令),将 device.id 作为它打印出来的少数道具之一,因为这是改变的设备。最后,我再次通过 awk 进行管道传输以找到带有我的 id 的行,从而减少 while 调用。

完整代码如下所示:

DEVICE_ID=$(wpctl inspect @DEFAULT_AUDIO_SINK@ | awk -F"\"" "/device.id/{print \$2}")
pw-mon -oa | awk "/id: $DEVICE_ID/{print; fflush()}" | while read; do
    wpctl get-volume @DEFAULT_AUDIO_SINK@ | awk "{print \$2 * 100}"
done
© www.soinside.com 2019 - 2024. All rights reserved.