FFPLAY - 信号が受信されるまでサウンドを繰り返します。

FFPLAY - 信号が受信されるまでサウンドを繰り返します。

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

関連情報