FFPLAY - 循环播放声音直到收到信号

FFPLAY - 循环播放声音直到收到信号

我有一个 bash 脚本,它ffplay在后台启动,无限循环一个短的声音样本。然后它做了一些其他的工作,最后它杀死了ffplay。

foo() {
    ffplay -loop 0 sound.wav &>/dev/null &
    trap "kill $!" RETURN

    (do work...)
}

我希望 ffplay 完成当前播放的样本的播放,然后才死亡。这可能吗?

答案1

您可以获得连续的统计信息或调试输出,ffplay其中包含以回车符 (^M) 结尾的行,如下所示:

    nan M-A:    nan fd=   0 aq=    0KB vq=    0KB sq=    0B f=0/0   ^M
  -0.07 M-A: -0.000 fd=   0 aq=    0KB vq=    0KB sq=    0B f=0/0   ^M
  -0.01 M-A: -0.000 fd=   0 aq=    0KB vq=    0KB sq=    0B f=0/0   ^M
   0.02 M-A:  0.000 fd=   0 aq=    0KB vq=    0KB sq=    0B f=0/0   ^M

看起来第一列是“nan”,不是数字,或者在循环开始时为负数。您可以检查这一点并在看到它时终止该进程。以下 bash 脚本演示了这一点。

#!/bin/bash
sound=somefile.wav
touch flagfile
(sleep 4; rm -f flagfile) &
ffplay -nodisp -stats -loop 0 "$sound" 2>&1 |
while read -d $'\r' time rest
do  case $time in
    nan|-*|0.00) [ ! -f flagfile ] && exit ;;
    esac
done

它创建一个文件flagfile,您需要删除该文件才能停止循环。在这个演示中,4 秒后就完成了。 ffplay使用选项运行-stats。统计信息写在 stderr 上,因此我们将其重定向到 stdout 2>&1。统计数据通过管道传送到一个 while 循环,该循环使用read分隔符回车符 ( $'\r') 将第一个单词放入变量中 time,其余单词放入 中rest

case第一个单词与模式nan或以 或数字 0 开头的任何内容进行比较-,如果标志文件不再存在,则脚本退出。

再写入几次统计数据后,ffplay 将被信号 SIGPIPE 杀死。您必须决定这个短暂的延迟是否适合您。这取决于声音文件的前几毫秒的噪音有多大。


如果您ffplay没有响应 SIGPIPE,您可以通过在临时文件中记下该命令的进程 ID 来运行您自己的终止命令 pidfile。请注意使用$BASHPID而不是$$,因为后者在子 shell 内不会改变。

#!/bin/bash
sound=somefile.wav
touch flagfile
(sleep 4; rm -f flagfile) &
( echo $BASHPID >pidfile
  exec ffplay -nodisp -stats -loop 0 $sound 2>&1 ) |
while read -d $'\r' time rest
do  case $time in
    nan|-*|0.00) [ ! -f flagfile ] && break ;;
    esac
done
kill -hup $(<pidfile)
rm -f pidfile

相关内容