サウンド設定
OctoPrintはラズベリーパイであり、動いているOSはraspbian(Jessie)だ。手元にはUSB-DACがあるので、 これを繋いで音を出す様にしてみる。
USB-DACは秋月電子のAKI.DAC-U2704。 USB接続だが、USBコネクタがMicroUSBではなくMiniUSBとなかなか厄介なシロモノ。いまどきは見なくなったMiniUSBコネクタなので、 ケーブルを探すのが大変。100均でも今は売ってない。
これに小型アンプと100均のスピーカーを繋いで、 単体で音が出るようにした。

USB-DAC接続
まずはUSBを繋いで、認識状況の確認。
$ lsusb Bus 001 Device 006: ID 067b:2303 Prolific Technology, Inc. PL2303 Serial Port Bus 001 Device 007: ID 08bb:2704 Texas Instruments Audio Codec #これっぽい Bus 001 Device 004: ID 0411:0261 BUFFALO INC. (formerly MelCo., Inc.) Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
2番めに「Texas Instruments Audio Codec」として認識されている。問題なさそうだ。
次にサウンドカードとしての認識確認。
$ cat /proc/asound/cards 0 [ALSA ]: bcm2835 - bcm2835 ALSA bcm2835 ALSA 1 [Camera ]: USB-Audio - BUFFALO BSW20KM15 USB Camera Novatek BUFFALO BSW20KM15 USB Camera at usb-3f980000.usb-1.3, high speed 2 [DAC ]: USB-Audio - USB Audio DAC Burr-Brown from TI USB Audio DAC at usb-3f980000.usb-1.4, full speed
なるほど2番めにはWebカメラが認識されており、3番めとして「TI USB Audio DAC」として認識されている。
次に優先順位の確認
$ cat /proc/asound/modules 0 snd_bcm2835 1 snd_usb_audio 2 snd_usb_audio
まだ何もしてないので、内蔵音源のbcm2835が優先となっている。USB-DACは3番めと思われる。
では、ここから、USB-DACの優先順位を上げていく。 「/usr/share/alsa/alsa.conf」の編集。 ディレクトリを移動して
cd /usr/share/alsa
まずは元のファイルをバックアップ。
sudo cp -p alsa.conf alsa.conf_org
その後、内容編集
sudo nano alsa.conf
最初のページの以下の箇所をコメントアウト。
~ # pre-load the configuration files @hooks [ { func load files [ { @func concat strings [ { @func datadir } "/alsa.conf.d/" ] } "/etc /asound.conf" # "~/.asoundrc" ] errors false } ] ~
次に2ページくらい下のページの以下の箇所を「0」から「2」に修正。
~ defaults.ctl.card 2 defaults.pcm.card 2 ~
これでalsa.confの修正は完了。ctrl+oとctrl+xでnanoを終了する。
では、一旦このままリブートを行う。
sudo reboot
再起動後、音を出してみる。ちゃんとUSB-DAC経由のスピーカから音が出ればOK。
aplay /usr/share/sounds/alsa/Front_Center.wav
alsaの設定は不明点多く、うまくいかないときは何が悪いかわからないので、諦める他無い。 今回はうまく音が出てくれた。よかった。
OpenJTalk設定
音が出るようになったので、音声合成が出来るようにOpenJTalkを入れる。 まずはapt-getでインストール実施。
sudo apt-get install -y open-jtalk open-jtalk-mecab-naist-jdic hts-voice-nitech-jp-atr503-m001 libhtsengine1
終了したら、喋らせるスクリプトを準備。
nano jtalk.sh
#!/bin/bash HV=/usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice tempfile=`tempfile` option="-m $HV \ -s 16000 \ -p 100 \ -a 0.03 \ -u 0.0 \ -jm 1.0 \ -jf 1.0 \ -x /var/lib/mecab/dic/open-jtalk/naist-jdic \ -ow $tempfile" if [ -z "$1" ] ; then open_jtalk $option else if [ -f "$1" ] ; then open_jtalk $option $1 else echo "$1" | open_jtalk $option fi fi aplay -q $tempfile rm $tempfile
作成したら保存して実行してみよう。
echo “只今の時刻は、`date +%k`時`date +%-M`分です” | sudo sh ./jtalk.sh
うまく男の声で今の時刻を喋ってくれた。 若干音量小さめなので、少し大きくしておこう。
sudo alsamixer
ゲイン-8くらいが、妥当なところだろうか。

では、もう少しいい声にするために、音声データをダウンロードする。
wget http://sourceforge.net/projects/mmdagent/files/MMDAgent_Example/MMDAgent_Example-1.4/MMDAgent_Example-1.4.zip
ファイルがダウンロードできたら、解凍。
unzip MMDAgent_Example-1.4.zip
その後、ボイスデータの場所にコピーしてやる。
sudo cp -R MMDAgent_Example-1.4/Voice/* /usr/share/hts-voice/
これで、MMDAgentの声色が使用できる。
では、新しい声色を使用するためにスクリプトを修正しよう。(2行目を修正)
#!/bin/bash HV=/usr/share/hts-voice/mei/mei_happy.htsvoice tempfile=`tempfile` option="-m $HV \ -s 16000 \ -p 100 \ -a 0.03 \ -u 0.0 \ -jm 1.0 \ -jf 1.0 \ -x /var/lib/mecab/dic/open-jtalk/naist-jdic \ -ow $tempfile" if [ -z "$1" ] ; then open_jtalk $option else if [ -f "$1" ] ; then open_jtalk $option $1 else echo "$1" | open_jtalk $option fi fi aplay -q $tempfile rm $tempfile
作成したら保存して実行してみよう。
echo “只今の時刻は、`date +%k`時`date +%-M`分です” | sudo sh ./jtalk.sh
声色が変わったのが確認できた。
ケース準備
USB-DACとアンプのケースを準備する。 Fusion360でなんとなく作成。USB-DACにはネジ止め穴が開いているので、そこだけ計測して位置合わせを実施。 あとは適当な箱にした。高さも適当だったけど、コンデンサの背が高くてギリギリだった。

これを印刷して作成。ケースとフタが準備できた。

できあがったらUSB-DACとアンプをケースにしまう。USB-DACはネジ穴だけ合わせて差し込み棒を用意したけど、 それ以外の固定具はないので、不安定。アンプ側は全くなにもないので、もっと不安定。 でも動かすものじゃないからフタして隠せばなんとかなるか。

USBを繋いだスピーカーキットをX-ONE2の中の奥の方に配置。プリンタヘッドのじゃまにならない位置なので、問題ないはず。 ここで何か喋らせるようにしよう。 しかし、スピーカ丸出しは何とかしなくちゃだな。

しゃべり
では、OctoPrintからのイベントで喋ってもらおう。 OctoPrintoのイベントと言えば、設定の中に何かあったはず。画面のスパナマークをクリックしてみると、 「GCODE Scripts」にイベントごとの設定エリアがあった。でもこれGcode飛ばすやつだな。 GCodeではしゃべってくれず、シェルコマンドを飛ばしてくれないと、何も出来ない。違ったようだ。

もう少し調べてみると、OctoPrintのGithubのWikiに答えがあった。
OctoPrintの設定ファイルであるconfig.yamlファイルをカスタマイズすると、色々と出来る様子。 少し以下を参考に試してみよう。
記事だと音声合成にAquesTalkを使用しているが、こちらはOpenjTalk。まあ似たようなもんだから問題ないだろう。
まずは、config.yamlの編集
cd ~/.octoprint
うまく移動できたら、ファイルが有るか見てみる。
$ ls -al
合計 60
drwxr-xr-x 13 pi pi 4096 11月 16 23:27 .
drwxr-xr-x 9 pi pi 4096 11月 19 12:39 ..
-rw-r--r-- 1 pi pi 1562 11月 16 23:27 config.yaml
drwxr-xr-x 6 pi pi 4096 11月 19 09:02 data
drwxr-xr-x 4 pi pi 4096 11月 18 23:49 generated
drwxr-xr-x 2 pi pi 4096 11月 15 22:30 logs
drwxr-xr-x 2 pi pi 4096 6月 21 18:49 plugins
drwxr-xr-x 2 pi pi 4096 10月 29 10:47 printerProfiles
drwxr-xr-x 2 pi pi 4096 6月 21 18:49 scripts
drwxr-xr-x 3 pi pi 4096 9月 27 20:49 slicingProfiles
drwxr-xr-x 3 pi pi 4096 11月 19 11:16 timelapse
drwxr-xr-x 2 pi pi 4096 6月 21 18:49 translations
drwxr-xr-x 2 pi pi 4096 11月 19 11:16 uploads
-rw------- 1 pi pi 218 9月 27 20:50 users.yaml
drwxr-xr-x 2 pi pi 4096 9月 27 20:43 watched
問題なく存在していた。まあ当たり前か。では、編集をする前にバックアップしておこう。
cp -p config.yaml config_org.yaml
では編集開始。
nano config.yaml
編集としては最終行に移動して、内容を書き加える。何を記述すればよいかは、こちらのドキュメントが良さそうだ。
Events@OctoPrint’s documentation
では、まずは簡単そうなのを作成してみる。 基本的にはイベントを拾って何かを行うこととなる。簡単に起こせそうなイベントとして、接続イベントを拾って喋ってみよう。 では、config.yamlの最後に以下を書き加えてみる。
events: enabled: True subscriptions: - event: Connected command: echo "こんにちは。`date +%k`時`date +%-M`分、3Dプリンタに接続しました" | sudo sh ~/jtalk.sh type: system
これで、一度OctoPrintを再起動させる。再起動はweb画面の電源マークを押すと出てくる「Restart OctoPrint」を実行してやれば、 OctoPrintのアプリだけ再起動がかかる。1分程度で再接続可能になる。

接続イベントでしゃべりを入れたので、再起動後自動接続時でもしゃべってくれた。いい感じに動作した。
拾えるイベントはかなり多岐にわたる。いろんなことができそうだ。 必要そうなイベントを拾い出して、しゃべらせてみよう。
events: enabled: True subscriptions: - event: Startup command: echo "こんにちは。`date +%k`時`date +%-M`分、3Dプリンタを起動しました。" | sudo sh ~/jtalk.sh type: system - event: Shutdown command: echo "シャットダウンします。さようなら" | sudo sh ~/jtalk.sh type: system - event: PrintStarted command: echo "3Dプリンタの印刷を開始します。" | sudo sh ~/jtalk.sh type: system - event: PrintFailed command: echo "3Dプリンタの印刷に失敗しました。" | sudo sh ~/jtalk.sh type: system - event: PrintDone command: echo "3Dプリンタの印刷が終了しました。" | sudo sh ~/jtalk.sh type: system - event: PrintCancelled command: echo "3Dプリンタの印刷を中止しました。" | sudo sh ~/jtalk.sh type: system
とりあえずこんなところだろうか。
wikiを見ていると、Payloadというパラメータが有り、どうやらこれが動的な情報が入っている変数の様子。 サンプルを探してみると、{}で囲んだら使えそうな雰囲気。 印刷終了時に、印刷時間でもしゃべらせてみよう。
印刷時間は
time: the time needed for the print, in seconds (float)
といった形で返ってくるらしく、小数点有りの秒数。これをそのまま説明されてもわかりづらいので、 やはり○時間○分○秒という形に直したい。しかしシェルで1行では書けそうにないので、 ちょっとC言語を借りよう。
#include <stdio.h> int main(int argc, char **argv) { int in; int h,m,s; if (argc > 1) { in = atoi(argv[1]); } else { in = 0; } h = in / 3600; in %= 3600; m = in / 60; in %= 60; s = in; if (h > 0) printf("%d時間%d分%d秒",h,m,s); else if (m > 0) printf("%d分%d秒",m,s); else printf("%d秒",s); }
秒を時間に直すコードを作成。 ではこれをOctoPrintのスクリプトに利用してみよう。 印刷終了イベントを下記のように書き直す。
- event: PrintDone command: echo "3Dプリンタの印刷が終了しました。印刷時間は `~/.octoprint/sec2time {time}`です。" | sudo sh ~/jtalk.sh type: system
これで、印刷終了時に経過時間も一緒に教えてくれるようになった。
お知らせ
OctoPrintのwikiのCookbookを見ると、スクリプトのサンプルがある。 この中には、メールを飛ばしたりするものがあり、なるほど便利そう。
Cookbook: Useful Eventhooks@OctoPrint
確かに、長い印刷を仕掛けて終了をメールで知らせてくれると、便利かも。 そして、どうせならお知らせはLINEで飛ばそう。
ということで、終了時にLINEを飛ばす。LINEだとメッセージに加えて絵も飛ばせるので、 終了時のスナップショットも送るようにしてみよう。(要LINE Notify)
jtalk.shも.octoprint下に移動し、config.yamlは以下のように修正。
events: enabled: True subscriptions: - event: Startup command: echo "こんにちは。`date +%k`時`date +%-M`分、3Dプリンタを起動しました。" | sudo sh ~/.octoprint/jtalk.sh type: system - event: Shutdown command: echo "シャットダウンします。さようなら" | sudo sh ~/.octoprint/jtalk.sh type: system - event: PrintStarted command: echo "3Dプリンタの印刷を開始します。" | sudo sh ~/.octoprint/jtalk.sh type: system - event: PrintFailed command: echo "3Dプリンタの印刷に失敗しました。" | sudo sh ~/.octoprint/jtalk.sh type: system - event: PrintDone command: sudo sh ~/.octoprint/PrintDone.sh {time} {file} type: system - event: PrintCancelled command: echo "3Dプリンタの印刷を中止しました。" | sudo sh ~/.octoprint/jtalk.sh type: system - event: Error command: echo "エラーが発生しました。エラー内容は {error} です" | sudo sh ~/.octoprint/jtalk.sh type: system
また、呼び出されるシェル側は、以下のようにした。
# save picture curl -o /tmp/printDone.jpg "http://localhost:8080/?action=snapshot" # speak message TM=$(/home/pi/.octoprint/sec2time $1) MES="3Dプリンタの印刷が終了しました。印刷時間は$TMです。" sudo sh /home/pi/.octoprint/jtalk.sh $MES # send message curl -X POST -H 'Authorization: Bearer *****'\ -F "message=$MES"\ -F 'imageFile=@/tmp/printDone.jpg'\ https://notify-api.line.me/api/notify
これで印刷終了後にメッセージと終了直後の画像が届く。

なんだか、LINE Notifyは改行ができない。仕様かな?