*** 注意 (2018-12-09追記) ***
この記事は古いため以下の記事を参照されたい:
*** 注意ここまで ***
概要
やりたいこと
Linux boxのline-inに接続されているtunerから流れてくるラジオ番組を自動で録音したい
Solution
- line-inから録音してOgg Vorbisにencodingするscriptを書く
- cronに登録して定期的に走らせる
これだけのいたって簡単なお仕事……のはずがどうしてこうなった。
落とし穴と対策
- pipeしたprocessの殺し方にハマる
- cronのdefaultのshellは/bin/sh
- PulseAudio関連のprogramをcronから呼んだ時の挙動にハマる
対策としては:
- parec ... | oggenc ... の組み合わせではなくffmpegで録音する → 1、2
- 環境変数XDG_RUNTIME_DIRを渡す → 3
わかったこと
- pipeでつないだprocessesの殺し方
- parecの他にもffmpegで録音できる
- PulseAudioを使う時は環境変数に注意
結論
こんな感じのscriptをcronで回している:
# 録音
XDG_RUNTIME_DIR=/run/user/1000 /usr/local/bin/ffmpeg -f pulse -ac 2 -ar 44100 -i
alsa_input.pci-0000_00_1b.0.analog-stereo -acodec libvorbis -q 3 "${FILEPATH}" &
RECPID=$!
# 録音停止
sleep ${DURATION}
kill -TERM ${RECPID}
補足
なお、ffmpegではdurationを指定できるので:
... /usr/local/bin/ffmpeg -f pulse -ac 2 -ar 44100 -i alsa_input.pci-0000_00_1b.0.analog-stereo -acodec libvorbis -q 3 -t ${DURATION} ${FILEPATH} &
とかでも良さそう。また、ffmpegのかわりにparecとoggencを組み合わせても良い:
parec --fix-format --fix-rate --file-format=raw --format=s16ne > >(oggenc -B 16
-C 2 -q 3 -o "${FILEPATH}" - >/dev/null 2>&1) &
ただし、この方法 (process substitution)はbashやzshでないと使えないので注意が必要。因みに:
parec ... | oggenc ...
とpipeでつないでも良いが、この場合job単位でprocessesを殺す必要がある (kill %%とかで殺せる)ので少々面倒。
補足2
XDG_RUNTIME_DIR=/run/user/1000 /usr/local/bin/ffmpeg -f alsa -ac 2 -ar 44100 -i
pulse -acodec libvorbis -q 3 "${FILEPATH}" &
で運用していたが、これだとdeviceの認識順と共にdefaultのsourceが変わって、無音の状態になることがあった。そこでdeviceを限定するため以下のように変更:
XDG_RUNTIME_DIR=/run/user/1000 /usr/local/bin/ffmpeg -f pulse -ac 2 -ar 44100 -i
alsa_input.pci-0000_00_1b.0.analog-stereo -acodec libvorbis -q 3 "${FILEPATH}" &
おまけ
また、Debian sidだと/usr/bin/mailは/etc/alternatives/mailへのsymlinkであり、これは更に/usr/bin/mail.mailutilsへのsymlinkで、如何なるpackageにも属していない。
参考URL
- https://wiki.archlinux.org/index.php/PulseAudio
- http://qiita.com/mpyw/items/9293d1bed7d16a9bfe5c
- http://mocha.freeshell.org/audio.html
補足2関連
- [Capture/Desktop – FFmpeg](https://trac.ffmpeg.org/wiki/Capture/Desktop)
- [FFmpeg Devices Documentation](https://www.ffmpeg.org/ffmpeg-devices.html)