在上一篇文中,我們已經組裝好了屬於自己的 Voice Kit,不過,如果要讓 Voice Kit 成為一個稱職的隨身助手,我們還有一些設定要做。如果你剛好對這部分有些疑問,那這篇文章應該可以解決你的問題喔~
在這篇文章中,我們要進行的有:
1. 讓你的 Voice Kit 2.0 ,變成可以進行簡單(只回一句話)對話的聊天機器人 (Chatbot)。
2. 讓你的 Voice Kit 2.0 可以辨識中文。
在按照這篇文章步驟完成設定後,我們應該可以學到:
- 基本的vim操作
- 基本的python缺套件安裝
- 基本的python語法修改
- 使用gTTS套件得到文字轉音訊檔
- 讓Voice Kit 辨識中文
- 如何開設GCP帳號
如果對整個智慧音箱的理論架構有興趣的話,可以參考另一篇的『理論篇』,裡面會有更詳細的說明~
首先我們需要準備:
1. 已經組裝好,可以正常啟動的 Voice Kit 2.0
2. 能進行網路刷卡的信用卡或 Visa 金融卡
3. 電腦 (Mac、Windows、Linux皆可)
確定都有的話,就讓我們開始吧!
1. 開啟 Google Cloud Platform 帳號
1.1 首先先點入此連結,進入 Google Cloud Platform的頁面。
1.2 選擇同意服務條款,居住地區確認依所在地選擇,這裡就先選台灣吧
*是否接收電子郵件訊息的部分可自由選擇。
1.3 點選同意並繼續,就會進入主畫面了
1.4 進入主畫面後,點選左上目錄,接著點選帳單
1.5 選擇新增帳單帳戶
1.6 點選同意後繼續
1.7 填入相關資訊、依照需求選擇付款方式
*稅務資料可以填寫個人
1.8 資料確認無誤後,點選同意免費試用
1.9 點選我知道了
到這裡,我們就完成 Google Cloud Platform 帳戶的申請了,同時,Google 也會自動開啟一個被命名為『 My First Project 』的專案。
2. 申請服務憑證(Service Credentials)
2.1 點選左上目錄,選擇 API 和服務中的『憑證』項目
2.2 點選建立憑證,選擇『服務帳戶金鑰』項目
2.3 服務帳戶的部分,請選擇『新增服務帳戶』
2.4 帳戶名稱可以輸入自己喜歡、好識別的名稱,這篇文章中,我們將帳戶命名為:『 Voice Kit 專用』
2.5 角色身分是 Project (專案)的『檢視者』
2.6 金鑰類型請選擇 JSON
2.7 點選建立
2.8 下載、儲存金鑰檔案
*金鑰就像是你在 Google Cloud 的記名會員卡,請務必妥善存放金鑰檔案。如果金鑰被盜用,相關消費都會記在這個帳戶上面喔
*如果完成後要把程式碼分享給朋友,也請記得再三檢查有沒有不小心把這個檔案公開到網路上
3. 請參考上一篇文章的第三點,以 ssh pi@{Voice Kit 的 IP}
登入 Voice Kit
3.1 執行
~/AIY-projects-python/checkpoints/check_cloud.py
,這個 Script可以幫忙檢查憑證設定有沒有錯誤,如果正確,會顯示如下:
pi@raspberrypi:~ $ ~/AIY-projects-python/checkpoints/check_cloud.py
Please follow the Custom Voice User Interface instructions on the AIY website
to download credentials:
https://aiyprojects.withgoogle.com/voice-v1/#makers-guide-3-custom-voice-user-interface
and save them to /home/pi/cloud_speech.json
Press Enter to close...
3.2 請按下鍵盤上的 Enter關掉程式
3.3 以任意文字編輯器把上一步的
My First Project-xxxxxxxx.json
(金鑰檔案)打開3.4 打開後應該能看見類似以下開頭的文字
{
"type": "service_account",
3.5 把文字全部複製下來
3.6 回到 Voice Kit ,輸入
vim /home/pi/cloud_speech.json
打開檔案3.7 按下
i
進入編輯模式,此時畫面左下角應該會看到-- INSERT --
3.8 把複製的內容貼上,接著按下 ESC 離開編輯模式
3.9 輸入
:wq
存檔3.10 再次執行
~/AIY-projects-python/checkpoints/check_cloud.py
,之後可能會看到有出現錯誤訊息的以下字串:
pi@raspberrypi:~ $ ~/AIY-projects-python/checkpoints/check_cloud.py
Testing the Google Cloud Speech API...
Traceback (most recent call last):
File "/opt/aiy/projects-python/src/aiy/_apis/_speech.py", line 274, in do_request
return self._handle_response_stream(response_stream)
File "/opt/aiy/projects-python/src/aiy/_apis/_speech.py", line 223, in _handle_response_stream
for resp in response_stream:
File "/usr/local/lib/python3.5/dist-packages/grpc/_channel.py", line 347, in __next__
return self._next()
File "/usr/local/lib/python3.5/dist-packages/grpc/_channel.py", line 341, in _next
raise self
grpc._channel._Rendezvous: <_Rendezvous of RPC that terminated with (StatusCode.PERMISSION_DENIED, Cloud Speech-to-Text API has not been used in project 418950185212 before or it is disabled. Enable it by visiting https://console.developers.google.com/apis/api/speech.googleapis.com/overview?project=418950185212 then retry. If you enabled this API recently, wait a few minutes for the action to propagate to our systems and retry.)>The above exception was the direct cause of the following exception:Traceback (most recent call last):
File "/home/pi/AIY-projects-python/checkpoints/check_cloud.py", line 104, in <module>
main()
File "/home/pi/AIY-projects-python/checkpoints/check_cloud.py", line 95, in main
if not check_speech_reco():
File "/home/pi/AIY-projects-python/checkpoints/check_cloud.py", line 68, in check_speech_reco
output = req.do_request()
File "/opt/aiy/projects-python/src/aiy/_apis/_speech.py", line 279, in do_request
raise Error('Exception in speech request') from exc
aiy._apis._speech.Error: Exception in speech request
Press Enter to close...
*看起來會像圖片中的樣子:
不用太緊張,請仔細閱讀一下,中間有出現來自 Google的溫馨提示:
Cloud Speech-to-Text API has not been used in project 418950185212 before or it is disabled.
這代表這個帳戶還沒開啟 Speech-to-Text API 的權限,等下個步驟開啟後就會消失了
4. 啟用 Speech-to-Text API
4.1 回到 GCP(Google Cloud Platform) Console,點左上目錄,點選『API 和服務』選擇 『資訊主頁』項目。
4.2 點選啟用 「+啟用API和服務」
4.3 在『搜尋 API 和服務』中輸入 Speech
4.4 點擊 Cloud Speech-to-Text API
4.5 點擊啟用
4.6 回到 Voice Kit,再次輸入
~/AIY-projects-python/checkpoints/check_cloud.py
後,就會看到以下的成功訊息了
pi@raspberrypi:~ $ ~/AIY-projects-python/checkpoints/check_cloud.py
Testing the Google Cloud Speech API...
Everything's set up to use the Google Cloud.
Press Enter to close...
*假如輸入內容和先前相同的話,可以按鍵盤的向上鍵,就能重覆輸入同樣內容喔~
5. 進行第一次語音辨識
5.1 接下來執行
~/AIY-projects-python/src/examples/voice/cloudspeech_demo.py
,執行後會看到以下訊息:
pi@raspberrypi:~ $ ~/AIY-projects-python/src/examples/voice/cloudspeech_demo.py
Press the button and speak
5.2 按下 Voice Kit 上的按鈕,看到畫面出現
Listening...
的時候和他說turn on the light
5.3 運作順利可以像下圖一樣,看到 Voice Kit 發光
*語音部分可以多試幾次看看反應,如果擔心英文發音不夠標準,可以用 Google 翻譯讓 Google 小姐幫忙說~
如果都請Google小姐說了 turn off light
都還沒看到 Voice Kit 發光,是因為原先的 LED 程式碼是比較舊的版本,需要更新,這時就會進入步驟5.4。
5. 4更新程式
5.4.1 用
cd ~/AIY-projects-python
的命令,把工作目錄 (work directory)切換到程式碼在的資料夾5.4.2 接著用
git log
做確認,從 Date (加粗的文字)可以看到,程式是 2018年 8月的版本
commit 93a6306438492464c25916b6b2f53d8e4750579b
Author: Dmitry Kovalev <dkovalev@google.com>
Date: Fri Aug 3 16:20:52 2018 -0700Update debian changelog and bump package version.Change-Id: I80bb5a73e2f9b7c12c6b51152fa7d4c1bc0b3145
5.4.3 輸入
git pull
,從 GitHub 上面拉最新的版本*這篇文章發布時,最新的版本是應該是 2018年 12月,如加粗文字所示:
pi@raspberrypi:~/AIY-projects-python $ git log
commit 56d40c7c1c5125fcfe2e69ec2b6f27a15fe35ad9
Author: Dmitry Kovalev <dkovalev@google.com>
Date: Thu Dec 20 13:58:35 2018 -0800Add doc generation shortcut to Makefile.Change-Id: Id51fbe9ceeeab6f055911b2f99645d54510cf03c
5.4.4 輸入
git checkout 56d40c7c1c5125fcfe2e69ec2b6f27a15fe35ad9
這個指令來切換到目前的版本 (有種時間跳躍的感覺)5.4.5 再執行一次
~/AIY-projects-python/src/examples/voice/cloudspeech_demo.py
此時會看到以下錯誤訊息:*此時出現錯誤是正常的,因為 AIY 的程式碼還沒更新,所以我們需要手動更新一下程式碼
INFO:root:Initializing for language en_GB...
INFO:root:Say something, e.g. turn on the light, turn off the light, blink the light, goodbye.
DEBUG:google.auth.transport.requests:Making request: POST https://oauth2.googleapis.com/token
DEBUG:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): oauth2.googleapis.com
DEBUG:requests.packages.urllib3.connectionpool:https://oauth2.googleapis.com:443 "POST /token HTTP/1.1" 400 None
ERROR:root:AuthMetadataPluginCallback "<google.auth.transport.grpc.AuthMetadataPlugin object at 0xb54815d0>" raised exception!
Traceback (most recent call last):
File "/usr/local/lib/python3.5/dist-packages/grpc/_plugin_wrapping.py", line 77, in __call__
callback_state, callback))
File "/usr/local/lib/python3.5/dist-packages/google/auth/transport/grpc.py", line 73, in __call__
callback(self._get_authorization_headers(context), None)
File "/usr/local/lib/python3.5/dist-packages/google/auth/transport/grpc.py", line 61, in _get_authorization_headers
headers)
File "/usr/local/lib/python3.5/dist-packages/google/auth/credentials.py", line 121, in before_request
self.refresh(request)
File "/usr/local/lib/python3.5/dist-packages/google/oauth2/service_account.py", line 310, in refresh
request, self._token_uri, assertion)
File "/usr/local/lib/python3.5/dist-packages/google/oauth2/_client.py", line 143, in jwt_grant
response_data = _token_endpoint_request(request, token_uri, body)
File "/usr/local/lib/python3.5/dist-packages/google/oauth2/_client.py", line 109, in _token_endpoint_request
_handle_error_response(response_body)
File "/usr/local/lib/python3.5/dist-packages/google/oauth2/_client.py", line 59, in _handle_error_response
error_details, response_body)
google.auth.exceptions.RefreshError: ('invalid_scope: Bad Request', '{\n "error": "invalid_scope",\n "error_description": "Bad Request"\n}')
5.4.6 輸入
vim src/aiy/cloudspeech.py
,開啟有問題的程式碼,此時會看到以下訊息:
@@ -38,6 +38,9 @@ AUDIO_SAMPLE_RATE_HZ = 16000
AUDIO_FORMAT=AudioFormat(sample_rate_hz=AUDIO_SAMPLE_RATE_HZ,
num_channels=1,
bytes_per_sample=2)
+_CLOUD_SPEECH_OAUTH_SCOPE = (
+ 'https://www.googleapis.com/auth/cloud-platform'
+)logger = logging.getLogger(__name__)@@ -47,7 +50,7 @@ class CloudSpeechClient:
if service_accout_file is None:
service_accout_file = os.path.expanduser('~/cloud_speech.json')- credentials = service_account.Credentials.from_service_account_file(service_accout_file)
+ credentials = service_account.Credentials.from_service_account_file(service_accout_file, scopes=[_CLOUD_SPEECH_OAUTH_SCOPE])
self._client = speech.SpeechClient(credentials=credentials)def _make_config(self, language_code, hint_phrases):
5.4.7 打開此連結,找到第 38 行,可看見以下訊息:
AUDIO_FORMAT=AudioFormat(sample_rate_hz=AUDIO_SAMPLE_RATE_HZ,
num_channels=1,
bytes_per_sample=2)
5.4.8 用
i
進入插入模式,在後面加上以下訊息 ,完成後按 ESC 恢復
_CLOUD_SPEECH_OAUTH_SCOPE = (
'https://www.googleapis.com/auth/cloud-platform'
)
5.4.9 然後找到第 47 行,用
i
進入插入模式,把
credentials = service_account.Credentials.from_service_account_file(service_accout_file)
修改成
credentials = service_account.Credentials.from_service_account_file(service_accout_file, scopes=[_CLOUD_SPEECH_OAUTH_SCOPE])
完成後按 ESC 恢復
*修改完成後,應該會如圖呈現:
5.4.10 用
:wq
存檔離開5.4.11 再輸入一次
~/AIY-projects-python/src/examples/voice/cloudspeech_demo.py
,這時應該就能看到以下訊息:
pi@raspberrypi:~/AIY-projects-python $ ~/AIY-projects-python/src/examples/voice/cloudspeech_demo.py
INFO:root:Initializing for language en_GB...
INFO:root:Say something, e.g. turn on the light, turn off the light, blink the light, goodbye.
DEBUG:google.auth.transport.requests:Making request: POST https://oauth2.googleapis.com/token
DEBUG:requests.packages.urllib3.connectionpool:Starting new HTTPS connection (1): oauth2.googleapis.com
DEBUG:requests.packages.urllib3.connectionpool:https://oauth2.googleapis.com:443 "POST /token HTTP/1.1" 200 None
INFO:aiy.cloudspeech:Start listening.
INFO:aiy.cloudspeech:Stop listening.
INFO:root:You said nothing.
INFO:root:Say something, e.g. turn on the light, turn off the light, blink the light, goodbye.
INFO:aiy.cloudspeech:Start listening.
*這個版本的程式碼不需要按按鈕就會自動偵測麥克風,所以直接用
turn on the light
、turn off the light
做測試吧
6. 讓 Voice Kit 發出聲音
6.1 先把工作目錄切換到 example下
pi@raspberrypi:~ $ cd ~/AIY-projects-python/src/examples/voice/
pi@raspberrypi:~/AIY-projects-python/src/examples/voice $
在
:
和$
中間的東西就被我們稱做是工作目錄(work directory) 這時候我們執行程式就可以少掉一串路徑6.2 在這個狀況下,輸入
./cloudspeech_demo.py
應該可以順利執行上一步驟的程式
接下來,我們要在開燈的時候讓他和我們說 “Light is turned on.” 、關燈的時候說 “Light is turned off.”
我們要使用gtts這個 python套件來將文字轉成語音(gtts是什麼意思請參考理論篇)
6.3 先用 vim 打開程式
vim ./cloudspeech_demo.py
6.4 移動到
form aiy.cloudspeech import CloudSpeechClient
這行下面,點
i
進入插入模式,接著新增新的一行,輸入form gtts import gTTS
,如下圖:
6.5 按下 ESC離開插入模式,輸入
:wq
存檔並關掉檔案6.6 執行
./cloudspeech_demo.py
,但可能會看到下圖的錯誤訊息
6.7 這時用 pip把套件裝下來就行了,輸入
pip3 install gtts
6.8 當看到以下訊息時代表安裝成功
Installing collected packages: ... gtts
Successfully installed ...
6.9 這時再重新執行
./cloudspeech_demo.py
應該就可以順利執行了* 因為 gtts 可以幫我們把文字存成 mp3的格式,接下來要安裝可以播放 mp3的套件。
6.10 用
vim ./cloudspeech_demo.py
打開程式,在
from gtts import gTTS
下繼續新增
from pydub import AudioSegment
然後執行,如果缺套件的話同樣輸入
pip3 install pydub
安裝6.11 接著執行
./cloudspeech_demo.py
6.12 確認兩個 python套件安裝完成後,接著我們把文字轉成語音撥出的函式放在
from ...
和def get_hints( ...
的中間
def say(text):
tts = gTTS(text) # 把文字變成gtts內建的物件
tts.save('output.mp3') # 把得到的語音存成 output.mp3
sound = AudioSegment.from_mp3('output.mp3') # 把 output.mp3 讀出
sound.export('output.wav', format='wav') # 轉存成 output.wav
audio.play_wav('output.wav') # 把 wav 用 VoiceKit 播出來
*打在#後的是註解,不用打
6.13 因為用到了
audio
這個套件,所以在上面的 from再多輸入一行:
from aiy.voice import audio
完成後如下圖:
6.14 接著存檔執行,確定沒有打錯
6.15 在
def main():
後新增say('test')
,如下圖
6.16 執行
./cloudspeech_demo.py
,應該會看到以下錯誤訊息:
Traceback (most recent call last):
File "./cloudspeech_demo.py", line 81, in <module>
main()
File "./cloudspeech_demo.py", line 48, in main
say('Test')
File "./cloudspeech_demo.py", line 30, in say
sound = AudioSegment.from_mp3("output.mp3")
File "/home/pi/.local/lib/python3.5/site-packages/pydub/audio_segment.py", line 716, in from_mp3
return cls.from_file(file, 'mp3', parameters=parameters)
File "/home/pi/.local/lib/python3.5/site-packages/pydub/audio_segment.py", line 665, in from_file
info = mediainfo_json(orig_file)
File "/home/pi/.local/lib/python3.5/site-packages/pydub/utils.py", line 263, in mediainfo_json
res = Popen(command, stdin=stdin_parameter, stdout=PIPE, stderr=PIPE)
File "/usr/lib/python3.5/subprocess.py", line 676, in __init__
restore_signals, start_new_session)
File "/usr/lib/python3.5/subprocess.py", line 1282, in _execute_child
raise child_exception_type(errno_num, err_msg)
FileNotFoundError: [Errno 2] No such file or directory: 'ffprobe'
6.17 錯誤關鍵在
No such file or directory: ‘ffprobe’
上面,請輸入以下文字進行安裝
sudo apt install ffmpeg
6.18 出現
Do you want to continue? [Y/n]
時請選 Y,接著執行./cloudspeech_demo.py
*沒問題的話應該能聽到 Test 的音效
接著,需要在原先開燈關燈判斷的地方加上開關完成的回應。
6.19 找到
if 'turn on the light' in text:
後面加上say('the light has been turned on')
6.20 找到
if 'turn off the light' in text:
後面加上say('the light has been turned off')
6.21 找到
if 'goodbye' in text:
後面加上say('bye')
後存檔、執行。*此時的程式如下圖:
7. 中文化
語音轉文字的中文化可以透過在執行的時候使用 --language=zh-TW
這樣的參數讓他變成中文。
7.1 將
say(text):
裡面的tts = gTTS(text)
改成tts = gTTS(text, lang='zh-TW')
,如下圖所示:
7.2 判斷意圖的部分可以用 elif 依樣畫葫蘆,參考下圖:
然後用
./cloudspeech_demo.py — language=zh-TW
的方式執行*因為語言參數會在
text = client.recognize(language_code=args.language, hint_pharses=hints)
被傳入(所以直接改這邊把它寫死也可以)
到這裡,我們就有了一個可以聽懂中文、也能回應中文的 Voice Kit啦~
大家都關心的費用問題
* Cloud Speech To Text API (STT)需要付費,目前每 15秒 0.006美元 (約0.18台幣)每個月 60分鐘免費,大概是 240 次,一天平均可使用 8次
而 Text To Speech API (TTS)的部分主要是進行文字轉語音(還需要確認) ,目前每個月 400萬字以下的轉換是免費的,超過400萬字後,每 100 萬文字收取 4 美元 (約32元台幣)費用
以上兩種 API 如果都是由個人正常使用,應該都不會超過免費使用的額度。
同場加映:串接Maid White
只是控制 Voice Kit 上面的電燈,還不是個合格的隨身助手,如果要控制家中的電器,我們可以利用 Maid White Python SDK 來控制 Maid White 目前可以支援的設備(電燈、冷氣、洗衣機……)喔~
安裝透過
pip3 install maidwhite
進行,並透過以下程式碼進行控制
m = MaidWhite({access_token})
l = m.get_devices()
dl = [x for x in l if x.display_name == 'My lamp']
dl[0].set_state({"power_status": "true"})
完成後如下圖
access_token 的取得方式請參考 如何以qmote控制聲寶冷氣 這篇文章,透過以下命令取得
curl 'https://www.tih.tw/2/token' -d 'username=your@email.tw&password=yourpassword'
參考資料
AIY 多語系
Maid White Python SDK
如何開機自動啟動程式 (避免Voice Kit 插頭被拔掉…)