【问题标题】:Write mplayer's output to fifo and read it将mplayer的输出写入fifo并读取
【发布时间】:2012-10-28 18:19:43
【问题描述】:

我正在尝试在 bash 中编写简单的通知应用程序。我想从 mplayer 读取输出,解析并通过 notify-send 显示。

我可以使用这个从 mplayer 获得所需的信息:

mplayer <url> | grep ICY

然后使用 sed 解析。

我创建命名管道,告诉 mplayer 编写它,然后我从中读取。不幸的是,它不起作用。这是我的脚本:

$fifo=~/.rp/fifo
mkfifo $fifo

mplayer <url> 2>/dev/null | grep ICY 1> $fifo &

while read line < $fifo; do
    echo $line
done

wait

程序一直在等待来自 $fifo 的输入。当这个脚本正在运行时,我尝试在其他终端中进行以下操作:

  1. 运行

    echo "Test" > .rp/fifo
    

    带有运行脚本的终端显示“Test”

  2. 运行

    echo "ICY" | grep ICY > .rp/fifo
    

    也可以。

  3. 运行

    mplayer <url> | grep ICY > .rp/fifo
    

    不起作用

我上面说的是mplayer的组合| grep 工作正常。 grep > $fifo 工作正常。我不明白为什么mplayer | grep > $fifo 不起作用。

【问题讨论】:

    标签: bash shell pipe


    【解决方案1】:

    我怀疑您可能正在体验 C 库的流的完全缓冲模式。你没有说你正在运行 GNU 用户空间,但如果你是,你可以查看stdbuf(1) 来修改缓冲机制。

    您可以先尝试将 grep 作为 stdbuf(1) 的子级运行,如下所示:

    mplayer <url> | stdbuf -o L grep ICY > .rp/fifo
    

    如果这不起作用,moar is bettar!

    stdbuf -o 0 mplayer <url> | stdbuf -o L grep ICY > .rp/fifo
    

    如果这仍然不起作用,那么mplayer 可能没有写入标准输出,而是直接写入/dev/tty。在这种情况下,您需要阅读expect(1)

    【讨论】:

    • 一个标准缓冲区就足够了。谢谢!
    • 对于 grep 的 --line-buffered 选项或 sed 的 -u 选项,使用 stdbuf -o 0 是多余的!
    【解决方案2】:

    您可以使用以下方法执行无缓冲 grep:

    $ mplayer ...  2>&1 | grep --line-buffered "ICY"
    

    或更好:

    $ mplayer ...  2>&1 | sed -une 's/^.*ICY[^:]*: //p'
    

    甚至,为什么不呢(sed 非常适合 grep 和格式化), 这将 grep ICY 行,甚至将包含 - 的行拆分为 30 个字符长度的第一个字段,由第二个字段中的 : 分隔:

    $ mplayer ...  2>&1 |
        sed -une "
            /ICY/{
                s/^.*ICY[^:]*:.*'\([^']*\)';/\1/;
                s/^\(.*\) - /\1                              - /;
                s/^\(.\{30\}\) *- /\1: /;
                p;
        }"
    

    可以给出类似的东西:

    Artist name                  : Song title
    Other artist                 : Other song
    Unsplited line
    Artist                       : Title
    

    【讨论】:

    • 感谢您的回答! “--line-buffered”对我有用。 :-)
    【解决方案3】:

    我以从属模式启动 mplayer,使用 FIFO 文件。

    mkfifo /tmp/mpfifo
    
    mplayer -slave -input file=/tmp/mpfifo video.mp4
    

    我可以从另一个终端控制视频播放器。

    echo "pause" >> /tmp/mpfifo
    echo "volume 50" > /tmp/mpfifo
    

    我想获得价值(例如播放视频的当前位置)。所以我尝试了:

    echo "get_time_pos" > /tmp/mpfifo
    

    但是没有返回值。 我搜索了几个小时,但没有成功。 然后我想将 mplayer 输出重定向到一个文件:

    mplayer -slave -input file=/tmp/mpfifo video.mp4 > /tmp/mpout.txt
    

    之后执行如下命令:

    echo "get_time_pos" > /tmp/mpfifo
    echo "get_property length" > /tmp/mpfifo
    

    /tmp/mpout.txt 中的输出如下:

    .......
    .......
    ANS_TIME_POSITION=113.6
    ANS_length=2534.602031
    

    如果每条命令的结果都能返回到命令行就好了。即使它可能需要一些工作,但可以解析输出文件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多