ffplay
バックグラウンドで始まり、短いサウンドサンプルを無限に繰り返すbashスクリプトがあります。その後、他のタスクを実行し、最後に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
。統計は、read
区切り文字キャリッジリターン($'\r'
)を使用して最初の単語を変数に入れ、残りの単語
time
をに入れるwhileループにパイプされますrest
。
case
最初の単語をパターンnan
または数字0で始まるすべての項目と比較し-
、フラグファイルがもう存在しない場合はスクリプトが終了します。
統計をさらに数回作成した後、SIGPIPE シグナルによって ffplay が終了します。この短い遅延があなたに適しているかどうかを判断する必要があります。これは、サウンドファイルの最初の数ミリ秒がどれほど騒々しいかによって異なります。
SIGPIPEに応答しない場合は、一時ffplay
ファイルにコマンドのプロセスIDを書き込むことで、独自のkillコマンドを実行できます
pidfile
。後者はサブシェル内で変更されませんので、代わりに$BASHPID
使用することに注意してください。$$
#!/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