ATOM Echo でTTSを堪能
さて前回はM5Stack ATOM Echoの基本動作を楽しみ、
サンプルコード StreamHttpClient_ECHO でスピーカをショート破壊するというエキサイティングな経験をしました。
ここではスピーカを交換して、TTS (Text to Speech) をストリーミング再生できたのでご報告します。
尚、マネして故障してもHomeMadeGarbageは保証できませんのであしからず。
以下のような危険がございます。
- ATOM Echo内蔵スピーカの発熱、破壊
- ATOM Echo 筐体の溶解、IC熱破壊
- 電源供給側 (PC, USB電源アダプタなど) の過電流破壊
HomeMadeGarbageは特殊な訓練を受けております。
目次
ATOM Echo 内蔵スピーカ
スピーカの発熱・故障問題につきまして公式の発表がございました。
内蔵スピーカの許容入力 絶対最大定格が0.7Wとのことですね。
んで搭載アンプ NS4168が5V電源で2.5W出力なんですよね。
そりゃ壊れるわ。
前回、交換した手持ちのアンプも0.5Wでしたのでノイズもすごいし実際アツアツでした。。。
筐体から出して使用していたので、熱がこもってのショート不良には至りませんでしたが危険ですよね。
スピーカ交換
そこでここでは以下の8Ω-8Wのスピーカに交換しました。
これならアンプからの2.5W出力が来ても安心ですね♪
いい感じにストリーミング再生できました!
かわいいATOMに対してサイズがバカでかいけど。。。。
初めてコレをストリーミングでノイズ無しで聴けた
ちなみにゲインは0.2 pic.twitter.com/HntLzAYkkB
— HomeMadeGarbage (@H0meMadeGarbage) June 18, 2020
TTS概要
多言語に対応しています。こんな感じです。https://t.co/l799Q7vulJ https://t.co/pZY3J0ndoG
— robo8080 (@robo8080) June 9, 2020
ATOM Echo で esp8266-google-ttsライブラリで生成されたmp3 URLをストリーミング再生すれば、
任意発話のTTSが実現できるという算段です。
参考
TTS動作
早速動作をご覧ください。
やーっと ATOM Echoで憧れのTTSができた!#M5Stack #ATOMEcho #blynk pic.twitter.com/hNHF0q4Aoy
— HomeMadeGarbage (@H0meMadeGarbage) June 18, 2020
BlynkアプリでスマホからテキストをATOM EchoにWiFi介して送信して、
ATOM Echoはテキストを受けて、esp8266-google-ttsライブラリでmp3 URLをゲットしストリーミング再生します。
やっとTTSの第一歩が踏み出せました 😛
Arduinoコード
以下を参考にコーディングいたしました。
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 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
#define BLYNK_PRINT Serial #include <M5Atom.h> #include <WiFi.h> #include <WiFiClient.h> #include <BlynkSimpleEsp32.h> #include <google-tts.h> #include "AudioFileSourceICYStream.h" #include "AudioFileSourceBuffer.h" #include "AudioGeneratorMP3.h" #include "AudioOutputI2S.h" // You should get Auth Token in the Blynk App. // Go to the Project Settings (nut icon). char auth[] = "Blynkアプリで取得したトークン"; // Your WiFi credentials. // Set password to "" for open networks. char ssid[] = "WiFI SSID"; char pass[] = "WiFI Pass"; String textIn = ""; TTS tts; AudioGeneratorMP3 *mp3; AudioFileSourceICYStream *file; AudioFileSourceBuffer *buff; AudioOutputI2S *out; #define CONFIG_I2S_BCK_PIN 19 #define CONFIG_I2S_LRCK_PIN 33 #define CONFIG_I2S_DATA_PIN 22 String getMacAddress() { byte mac[6]; WiFi.macAddress(mac); String cMac = ""; for (int i = 0; i < 6; ++i) { if (mac[i] < 0x10) { cMac += "0"; } cMac += String(mac[i], HEX); if (i < 5) cMac += ":"; // put : or - if you want byte delimiters } cMac.toUpperCase(); return cMac; } // Called when a metadata event occurs (i.e. an ID3 tag, an ICY block, etc. void MDCallback(void *cbData, const char *type, bool isUnicode, const char *string) { const char *ptr = reinterpret_cast<const char *>(cbData); (void) isUnicode; // Punt this ball for now // Note that the type and string may be in PROGMEM, so copy them to RAM for printf char s1[32], s2[64]; strncpy_P(s1, type, sizeof(s1)); s1[sizeof(s1)-1]=0; strncpy_P(s2, string, sizeof(s2)); s2[sizeof(s2)-1]=0; Serial.printf("METADATA(%s) '%s' = '%s'\n", ptr, s1, s2); Serial.flush(); } // Called when there's a warning or error (like a buffer underflow or decode hiccup) void StatusCallback(void *cbData, int code, const char *string) { const char *ptr = reinterpret_cast<const char *>(cbData); // Note that the string may be in PROGMEM, so copy it to RAM for printf char s1[64]; strncpy_P(s1, string, sizeof(s1)); s1[sizeof(s1)-1]=0; Serial.printf("STATUS(%s) '%d' = '%s'\n", ptr, code, s1); Serial.flush(); } void setup(){ M5.begin(true, false, true); Serial.begin(115200); delay(1000); M5.update(); Blynk.begin(auth, ssid, pass); } //Text Inputデータ受信 BLYNK_WRITE(V0) { textIn = param.asStr(); Serial.println(textIn); String http = "http" + tts.getSpeechUrl(textIn, "ja").substring(5); Serial.println(http); audioLogger = &Serial; file = new AudioFileSourceICYStream( (const char *)http.c_str() ); file->RegisterMetadataCB(MDCallback, (void*)"ICY"); buff = new AudioFileSourceBuffer(file, 10240); buff->RegisterStatusCB(StatusCallback, (void*)"buffer"); out = new AudioOutputI2S(); out->SetPinout(CONFIG_I2S_BCK_PIN, CONFIG_I2S_LRCK_PIN, CONFIG_I2S_DATA_PIN); out->SetChannels(1); out->SetGain(0.4); mp3 = new AudioGeneratorMP3(); mp3->RegisterStatusCB(StatusCallback, (void*)"mp3"); mp3->begin(buff, out); while(mp3->isRunning()) { Serial.println("playing"); if (!mp3->loop()) { mp3->stop(); break; } } } void loop(){ Blynk.run(); } |
たなかまさゆきさんのブログを参考にL. 33-35, L. 104でアンプへのI2S入力端子ピンを明確に指定いたしました。
https://lang-ship.com/blog/work/m5stack-atom-echo-spiffs-mp3/
音声周りの構成は以下の通り
またesp8266-google-ttsライブラリはhttpsのURLを返すのでL. 94でhttpに変更しています。
httpsでは再生できませんでしたので。
おわりに
ここではTTSで任意の発話をストリーミング再生することに成功しました。
最終目標はATOM Echoで以前ラズパイゼロで作ったおしゃべりティラノくんのようなコンシェルジュを制作することですので
次回は定時発話システムの構築やセンサ値の発話を目指したいと思います。
我が家のティラノくんのお友達をコレで作りたいな
ATOM Echo – スマートスピーカー開発キット – スイッチサイエンス https://t.co/GPnuRzPkhE pic.twitter.com/u4vOT3NcFg
— HomeMadeGarbage (@H0meMadeGarbage) June 5, 2020
初めまして
こちらで勉強させていただいております。
(念のためatom echoを2台購入しました)
さて、見よう見まねで作ってみた所、シリアルモニタから下記エラーが出て鵜なくいきません。
Failed to get TKK. trying again…
私側の問題なのか、他の問題(例えばgoogleの仕様が変わった等)を切り分けしたく、現状で動作しているかご確認いただけると大変助かります。