停止arecord录制而不停止脚本的其余部分

时间:2014-07-02 15:53:51

标签: bash

我正在使用使用谷歌语音到文本API的脚本。 api需要flac编码的文件,因此脚本的录制部分如下所示:

arecord -q -t wav -d 0 -f S16_LE -r 16000 | flac - -f --best --sample-rate 16000 -s -o "$TEMP_FILE"

此命令将记录,直到用户退出ctrl-c并且wav记录的格式应通过管道传输到flac程序以进行flac格式的输出,然后脚本应该继续。

我遇到的问题是按ctrl-c完全结束脚本并切断一些音频(仍然输出flac文件)。如果我在没有管道的情况下运行脚本:

arecord -q -t wav -d 0 -f S16_LE -r 16000 some.wav

然后按ctrl-c将仅结束录制并继续使用脚本。

如何解决这个问题,以便ctrl-c只停止arecord命令并允许脚本的其余部分(包括管道flac编码)完成?

2 个答案:

答案 0 :(得分:3)

意识到你想要做的事情无法完成

免责声明:以下是基于我自己在Ubuntu 12.04上的实验,只有一小部分研究。如果我错了,请告诉我。

症结:

  • 在管道运行时按 Ctrl-C 会向管道中的所有进程发送信号SIGINT
  • 进程收到信号的订单 无法保证
  • 除非管道中的所有进程陷阱信号,否则脚本将作为一个整体中止(尽管脚本本身可以使用trap命令捕获信号 - 但是这样的shell陷阱在管道进程收到信号之后 之后才会执行,并且通常已被信号终止。

在您的具体情况下,arecord 设计陷阱 SIGINT并以有序的方式退出。 相比之下,flac似乎没有 - 它被强制终止 但是,即使flac 陷阱SIGINT要完全关闭,根据相关流程收到信号的不确定顺序,您也无法安全使用带有 Ctrl-C 的管道,同时期望整体处理以有序的方式完成。

(暂时不说:arecord报告以 Ctrl-C 结尾时退出代码1,这让我想知道如何将其与真正的失败区分开来,例如磁盘空间不足。)

因此:

  • arecord作为单独命令 调用,并将输出捕获到(临时)文件中。
  • 之后,将(临时)文件传递给flac(并在完成后删除临时文件)。

答案 1 :(得分:0)

我会这样试试:

# Create a fifo
FIFO=/tmp/my_fifo
mkfifo $FIFO

# Start arecord in background and redirect its output into the fifo
arecord ... > $FIFO &

# Get the arecord PID
PID=$!

# Trap the SIGINT to send SIGINT to arecord
trap "kill -INT $PID" INT

# Start flac and redirect its input with the fifo.
flac - ... < $FIFO

# The script should be blocked here, and a CTRL+C will run
# the kill -INT to the arecord process only.
# But I don't know how flac will react after ...
# If flac exit correctly, just restore the SIGINT
trap - INT