この記事の対象マシンはNanoPi NEO/NEO2で、OSは例によってarmbian (debian Jessie)。
と、いうことにしておくけど、おそらくLinuxの多くでほぼそのままで動くだろうしNanoPi NEO/NEO2でなくてもイケる筈。
まずは、NanoPi NEO/NEO2で音声機能が使えるか確認。
# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: Codec [H3 Audio Codec], device 0: CDC PCM Codec-0 []
Subdevices: 1/1
Subdevice #0: subdevice #0
card 1: U0x4b40x307 [USB Device 0x4b4:0x307], device 0: USB Audio [USB Audio]
Subdevices: 1/1
Subdevice #0: subdevice #0
基板のピンヘッダからスピーカーに繋いで音を出す場合はcard 0の出力。USBスピーカーを繋いで音を出すならcard 1の出力となる。USBスピーカーを繋いでいない場合はcard 1:以下の部分は表示されない。
音を出してみる
基板のピンヘッダからスピーカーに出力
# speaker-test -c 2 -D hw:0 # aplay /usr/share/sounds/alsa/Front_Center.wav -D hw:0
USBスピーカーに出力
# speaker-test -c 2 -D plughw:1 # aplay /usr/share/sounds/alsa/Front_Center.wav -D plughw:1
speaker-testではザーッという音が鳴る筈。
aplayの方は喋る筈。指定しているファイルはarmbianに標準で入っているもの。
ALSAの設定変更 (必要なら)
標準の音声の出力先が基板のピンヘッダからスピーカー(card 0)なのでUSBスピーカーに出したい場合は設定を変更する。設定ファイルは何故か/etcには無い。
/usr/share/alsa/alsa.conf
1 2 | defaults.ctl.card 1
defaults.pcm.card 1
|
システム再起動後は標準の音声出力先がUSBスピーカーになっている筈。
Open JTalkの準備
音声合成システムのOpen Jtalkはarmbian (debian)のパッケージが提供されているので簡単。
# apt-cache search jtalk # apt install hts-voice-nitech-jp-atr503-m001 open-jtalk open-jtalk-mecab-naist-jdic
1行目は名前にjtalkを含むパッケージを検索。おそそらくopen-jtalk本体とm001という男性の音声データと辞書の3つのパッケージが表示される筈。
2行目で検索結果として表示されたパッケージ名を指定してインストール。(表示された3つ全て)
実行してみる。
$ echo "こんにちは" | open_jtalk -m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice -x /var/lib/mecab/dic/open-jtalk/naist-jdic -ow /tmp/tmp.wav && aplay --quiet /tmp/tmp.wav
あまりに簡単に喋るのでびっくり。
ちょっと問題があって、男性声のm001は何故か特定の条件で発声が遅くなることがある。かなりホラーな声になるのであまり使いたくない。女性声のMeiが良さげ。
Meiのインストールはこちらを参照。現在はそのページの内容のMMDAgent_Example-1.6.zipのバージョンが1.6から1.7に変わったくらい。
jtalk.sh1 2 3 4 5 6 7 8 | TMP=/tmp/tmp.wav
# Voice m001
# echo "$1" | open_jtalk -m /usr/share/hts-voice/nitech-jp-atr503-m001/nitech_jp_atr503_m001.htsvoice -x /var/lib/mecab/dic/open-jtalk/naist-jdic -ow $TMP && aplay --quiet $TMP
# Voice Mei
echo "$1" | open_jtalk -m /usr/share/hts-voice/mei/mei_normal.htsvoice -x /var/lib/mecab/dic/open-jtalk/naist-jdic -ow $TMP && aplay --quiet $TMP
rm -f $TMP
|
$ chmod +x jtalk.sh $ ./jtalk.sh "こんにちは"
2行目を実行して「こんにちは」と言えばOK.
このスクリプトは後で使う
PHPの準備
「がとらぼ」の中の人が頭の硬いオッサンで最近はPHPくらいしか使わなくなってるのとPythonとかRubyは殆ど触ったことがないのでPHPを使う。
PHPを使うけど、よくあるようなウェブサーバにするだとか大掛かりにするつもりはないので必要最低限だけインストールする。
今回はPHP5のコマンドラインとCURL(と国際化)モジュールが使えれば良い筈。
# apt install php5-cli php5-curl php5-intl
TwitterOAuthの準備
Twitterとの連携は腕に覚えがあるなら1から自力で作れば良いだろうが、「がとらぼ」の中の人はプログラム力が無いことにかけては右に出るものがいないというくらいカスなので既存のものを使う。
GitHubのtwitteroauthというプロジェクト。定番中の定番。
$ wget https://github.com/abraham/twitteroauth/archive/master.zip $ unzip master.zip $ mv twitteroauth-master twitteroauth
これでtwitteroauthは準備完了。twitteroauth/twitteroauth.phpを呼び出すだけで殆ど何も考えずにタイムラインを取得したりツイートできる。
↑の方法は古いTwitterOAuthでは有効だが、TwitterOAuth 2.0以降ではTwitterOAuthのドキュメントに従ってphp composerでTwitterOAuthをインストールするのが無難。↑の圧縮ファイルを任意の場所に展開して使う方法はTwitterOAuth 2.0以上だとcaBubdleが無いだののエラーを解決するのに苦しみそう。
今回の記事で一番難しいのはおそらくTwitterのAPIを利用するためのキーとかアクセストークンの取得。
慣れてりゃ簡単だろうけど、初めてだと何が何やらって感じ。今回はWordPressの投稿時の自動ツイート用以来ということでかなり久しぶりに取得しようとしたら9割方忘れてたので迷いそうになった。
ツブヤクンデス作成
NanoPi NEOでの発声は簡単だった。Twitterとの連携もtwitteroauthのおかげでアホみたいに簡単。後は組み合わせるだけ。
以下、作成するtsubuyakundesu.phpというファイルは先に用意したjtaik.shとtwitteroauthと同じディレクトリに置く。後で作成するtweet_id_stamp.txtも同じディレクトリ。
(twitteroauthディレクトリの中じゃないよ)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 | <?php
//mb_internal_encoding("UTF-8");
require_once("./twitteroauth/autoload.php");
use Abraham\TwitterOAuth\TwitterOAuth;
date_default_timezone_set('Asia/Tokyo');
$idfile = './tweet_id_stamp.txt';
$id_old = file_get_contents($idfile);
//以下4行に取得したTwitterのAPI用のキーやトークンを入れる
$consumerKey = 'xxxxxxxxxxxxxxxxxxxxxxxxx';
$consumerSecret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$accessToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
$accessTokenSecret = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
//接続
$connection = new TwitterOAuth($consumerKey, $consumerSecret, $accessToken, $accessTokenSecret);
//タイムライン取得
$timeline = $connection->get('statuses/home_timeline', ['count' => '10']);
// var_dump($timeline);
$timeline = array_reverse($timeline); //タイムラインを逆順に
foreach($timeline as $tw){
if ($tw->id > $id_old){
$id = $tw->id;
echo $tw->user->name . "\n";
// echo date('Y-m-d H:i:s', strtotime($tw->created_at)) . "\n";
$twname = preg_replace("/[^ぁ-んァ-ンー0-9一-龠0-9]+/u",'' , $tw->user->name);
echo $twname . "\n";
exec("./jtalk.sh $twname");
//ツイート本文
$speech = preg_replace('/https?:\/\/[-_.!~*\'()a-zA-Z0-9;\/?:@&=+$,%#]+/', '', $tw->text);
$speech = str_replace('Twitter', 'ツイッター', $speech);
$speech = preg_replace('/^RT \@.*?:/', 'リツイート', $speech);
$speech = preg_replace('/(\r\n|\r|\n)/', ' ', $speech);
$speech = preg_replace("/[^ぁ-んァ-ンーa-zA-Z0-9一-龠0-9\-\s]+/u",'' ,$speech);
$cmd = './jtalk.sh "' . $speech . '"';
exec($cmd);
//分解するなら上の1行をコメントにして次の5行を非コメント化
//$ar_sp = preg_split("/[\s]+/", $speech, -1, PREG_SPLIT_NO_EMPTY);
//foreach($ar_sp as $sp){
// echo "\n----\n$sp\n----\n";
// exec("./jtalk.sh \"$sp\"");
//}
}
}
if ($id > $id_old){
file_put_contents($idfile, $id);
}
?>
|
TwitterOAuth 2.0以降のバージョンをcomposerでインストールして使用する場合は3行目のPathを適切に変更。それ以外は(Twitterの取得の処理部分は)少なくともTwitterOAuth 3.1まで問題なく動く。
タイムラインの最新のツイートのIDを保存するファイルを作成。ダミーのIDとして0を登録。
$ echo 0 > ./tweet_id_stamp.txt
実行してみる。
$ php ./tsubuyakundesu.php
仕組みとしてはTwitterOAuthでタイムラインを取得(最大10個まで)。
配列からツイートID (id)と発信者の名前(user->name)とツイート本文(text)を取得。
ツイートIDをtweet_id_stamp.txtに保存してある値と比較して大きいもの(新しいもの)であれば読み上げる。
発信者の名前のアルファベットは読まない(強引だけど)
ツイート本文はリンクと記号を読まない、他テキトーに整形、改行や空白を利用して分割して読み上げ。
今回はツイートがタイムラインに追加されたら自動的に取得して読み上げというものではないが、php /path/tsubuyakundesu.phpをcrontabに仕掛ければ1分毎だとか3分毎だとかにタイムラインを拾ってきて新しいツイートだけ読み上げてくれる。
一応、手抜きながらもツイートIDで比較しているのでツイート読み上げの重複はない筈。
最低限の動作をするだけのコードになっているので「何だコレ?危なっかしいな」という部分が多々あるとは思うけどご容赦というか勝手に改良して貰えればと。
関連記事:- Google TTSを利用してAsteriskで日付・時刻の読み上げ
- NanoPi NEOに100均スピーカーを繋いでみた
- WindowsでもTwitterを声でツブヤクンデス
- NanoPi NEOがTwitterを声でツブヤクンデス ←いまここ
- Windowsの音声合成 IVONA Voices 2
- Windowsの音声合成 標準搭載のHaruka, Zira
- Androidの英語音声合成 SVOX
- Androidで日本語音声合成 SVOX, Vocalizer
- 続・Google TTSを利用してAsteriskのIVRで日本語読み上げ
- Google TTSを利用してAsteriskのIVRで日本語読み上げ
- アッチッチなNanoPi NEO3を冷やしたい パッド交換
- NanoPi NEO3冷却力強化後のUnixBench
- アッチッチなNanoPi NEO3を冷やしたい
- NTPサーバの時刻ソースに対するズレの調整
- NanoPi NEO3をv6プラスのルーターにする systemd-networkd + nftables
- NanoPi NEO3のUSB3.0ポートのネットワーク速度
- NanoPi NEO3でArmbian よきところでUnixBench
- NanoPi NEO3が届いた
- NanoPi NEOにRTCモジュールを付ける
- 新しい中華GPSモジュールとChronyで作るNTPサーバ (中編)
- 新しい中華GPSモジュールとChronyで作るNTPサーバ (前編)
- Prometheus2とGrafana6によるシステム監視 シングルボードコンピュータの温度表示
- NanoPi NEOでNTPサーバ再構築 (全まとめ)
- NanoPi NEO2をv6プラスのルーターにする 後編
- NanoPi NEO2をv6プラスのルーターにする 前編
- ELK Stackでシステム監視 FilebeatでNTP統計ログ取得 Logstashで加工
- NanoPi NEO2(arm64)用にFilebeatをビルド
- NanoPi NEO2を超コンパクトなアルミケースに入れる
- NanoPi NEO2用armbian 5.41 Debian 9 Stretch next 4.14.18
- NanoPi NEO2を100均の灰皿に入れてみた
- NanoPi NEO2のシステム監視 RPi-Monitorとnetdata
- NanoPi NEOとGPSモジュール用アルミケースを作る
- NanoPi NEO2 + DACで音楽プレーヤーVolumioを使う
- NanoPi NEO2にDACを接続
- NanoPi NEO2の最大クロック引き下げ後のUnixBench 再び
- NanoPi NEO2用armbian 5.32 Debian 9 Stretch 4.13.0-RC6
- NanoPi NEO2用armbian 5.32 Debian jessie 4.13.0-RC6
- NanoPi NEOをSIP電話機にする 後編 (その2)
- NanoPi NEO2とICカードリーダーでタイムレコーダーを作る(実用化編)
- NanoPi NEO2とICカードリーダーでタイムレコーダーを作る