Slide 1

Slide 1 text

改造 ReSpeaker 2-MIC HAT 台灣樹莓派

Slide 2

Slide 2 text

姓名標示 — 非商業性 — 相同方式分享 CC (Creative Commons) 姓名標示 — 你必須給予 適當表彰、提供指向本授權 條款的連結,以及 指出(本作品的原始版本)是否已 被變更。你可以任何合理方式為前述表彰,但不得以 任何方式暗示授權人為你或你的使用方式背書。 非商業性 — 你不得將本素材進行商業目的之使 用。 相同方式分享 — 若你重混、轉換本素材,或依本 素材建立新素材,你必須依本素材的授權條款來 散布你的貢獻物。

Slide 3

Slide 3 text

3 ● Raspberry Pi 官方經銷商 ● 專注 Raspberry Pi 應用與推廣 , 舉辦社群活動 關於我們

Slide 4

Slide 4 text

4 ● COSCUP,MakerConf,PyCon,HKOSCon 講者 ● 投影片 ● https://speakerdeck.com/piepie_tw ● 程式碼 ● https://github.com/piepie-tw 分享 x 教學

Slide 5

Slide 5 text

No content

Slide 6

Slide 6 text

6 ● ReSpeaker 2-Mic HAT 使用 ● Linux ALSA 介紹 ● Google Assistant 介紹 ● ReSpeaker 2-Mic HAT 改造 本次主題

Slide 7

Slide 7 text

7 ● 硬體:Raspberry Pi 4B ● 作業系統:2021-05-07-raspios-buster-armhf.img (https://bit.ly/42iddHA) ● 為了可以使用USB轉TTL傳輸線 ● 修改/boot/config.txt, 新增三行 – dtoverlay=pi3-miniuart-bt – core_freq=250 – enable_uart=1 ● 修改/boot/cmdline.txt, 將quiet splash的quiet移除 今日環境 刪除 quiet 新增三行

Slide 8

Slide 8 text

● $ sudo apt-get update --allow-releaseinfo- change ● $ sudo apt-get install -y vim git ● $ sudo apt-get install -y python3-pyaudio ● $ sudo apt-get install -y sox flac libatlas- base-dev espeak mpg123 ● $ sudo pip3 install -U SpeechRecognition python-vlc gtts openai ● $ sudo ln -s /usr/lib/arm-linux- gnueabihf/libpython3.7m.so.1.0 /usr/lib/arm- linux-gnueabihf/libpython3.5m.so.1.0 ● $ sudo pip3 install -U yt-dlp (hackmd) 安裝所需軟體

Slide 9

Slide 9 text

● # 安裝新版 Dialogflow ● $ sudo pip3 install -U google-cloud-dialogflow ● $ sudo pip3 install grpcio-tools ● $ sudo pip3 install -I --force-reinstall grpcio (hackmd) 安裝所需軟體

Slide 10

Slide 10 text

● # 安裝 Voice Engine + Echo Cancellation ● $ sudo apt-get install -y libspeexdsp-dev speex ● $ sudo apt-get install swig3.0 ● $ sudo ln -s /usr/bin/swig3.0 /usr/bin/swig ● $ sudo pip3 install -U speexdsp (hackmd) 安裝所需軟體

Slide 11

Slide 11 text

語音控制現有商品

Slide 12

Slide 12 text

https://www.mobilegeeks.de/artikel/amazon-echo-apple-homepod-google-home-microsoft-invoke-vergleich/ Google Home Apple HomePod Amazon Echo Microsoft Invoke Amazon Dot

Slide 13

Slide 13 text

超級比一比 http://phandroid.com/2017/06/06/apple-homepod-vs-google-home-vs-amazon-echo-which-is-best/?i=2

Slide 14

Slide 14 text

誰最吸引人? https://marketingland.com/survey-amazon-echo-google-home-owners-interested-apple-homepod-217549

Slide 15

Slide 15 text

15 實驗 1: 錄音 / 播音 目的 : 使用 ALSA 相關工具

Slide 16

Slide 16 text

● 特色 ● 使用 WM8960(low power stereo codec) ● 2 Microphones ● 3.5mm Audio Jack ● JST2.0 Speaker Out ● 2 Grove Interfaces ● 1 User Button ReSpeaker 2-Mics Pi HAT http://wiki.seeed.cc/ReSpeaker_2_Mics_Pi_HAT/

Slide 17

Slide 17 text

ReSpeaker 2-Mics Pi HAT http://wiki.seeed.cc/ReSpeaker_2_Mics_Pi_HAT/

Slide 18

Slide 18 text

● $ cd ~ ● $ git clone https://github.com/respeaker/seeed- voicecard.git ● $ cd seeed-voicecard ● $ sudo ./install.sh --compat-kernel ● $ sudo reboot (hackmd) 安裝設定 http://wiki.seeed.cc/ReSpeaker_2_Mics_Pi_HAT/

Slide 19

Slide 19 text

測試是否安裝成功? aplay -l arecord -l

Slide 20

Slide 20 text

攜帶型喇叭 電源開關 ( 有兩段大小聲 ) miniUSB 充電

Slide 21

Slide 21 text

ReSpeaker 2-Mics + 喇叭 喇叭接在 ReSpeaker 上

Slide 22

Slide 22 text

● 列出目前可 record 的音訊裝置 ● $ arecord -l ● 錄音 (mono, stereo) ● $ arecord -D plughw:2,0 -d 3 -f dat -c 1 mono.wav ● $ arecord -D plughw:2,0 -r 16000 -f S16_LE 16k.wav ● $ arecord -D plughw:2,0 -f dat stereo.wav 測試錄音 (arecord)

Slide 23

Slide 23 text

● 列出目前可 playback 的音訊裝置 ● $ aplay -l ● 播放音訊 ● $ aplay -D plughw:2,0 mono.wav ● $ aplay -D plughw:2,0 16k.wav ● $ aplay -D plughw:2,0 stereo.wav 播放 (aplay)

Slide 24

Slide 24 text

● 列出PulseAudio 的Audio 輸出: ● $ pactl list short sinks 0 alsa_output.platform-bcm2835_audio.digital-stereo 1 alsa_output.platform-bcm2835_audio.analog-stereo 2 alsa_output.platform-soc_sound.stereo-fallback ● 設定PulseAudio 的Audio 預設輸出 ● $ pactl set-default-sink 1 # 1 是3.5mm Audio Jack ● $ pactl set-default-sink 2 # 2 是ReSpeaker 設定 PulseAudio Sound Server 預設輸出

Slide 25

Slide 25 text

● $ aplay stereo.wav Playing WAVE 'stereo.wav' : Signed 16 bit Little Endian, Rate 48000 Hz, Stereo 聲音格式 https://www.aiseesoft.com/resource/what-is-mono-audio.html mono stereo

Slide 26

Slide 26 text

26 使用 alsamixer 控制音量

Slide 27

Slide 27 text

$ alsamixer 按鍵盤上下鍵調整音量

Slide 28

Slide 28 text

按 F5 顯示所有功能 按 tab 切換功能 按 F5 會顯示 音效卡所有功能

Slide 29

Slide 29 text

按 F6 可切換音效卡 切換到 ReSpeaker 音效卡

Slide 30

Slide 30 text

調整 ReSpeaker 音效卡 結束按 ESC 退出 Microphone 和 Speaker 設定同時出現 先調整音量大小

Slide 31

Slide 31 text

● 儲存 ALSA 設定到 ~/.config/asound.state ● $ alsactl --file ~/.config/asound.state store ● 將 ALSA 設定載入 ● $ alsactl --file ~/.config/asound.state restore 儲存和載入 ALSA 設定

Slide 32

Slide 32 text

32 Linux 輸入與輸出的處理流程 https://en.wikipedia.org/wiki/Evdev

Slide 33

Slide 33 text

● Sound Card & Device 音效卡的資訊流 http://www.alsa-project.org/main/index.php/Minivosc

Slide 34

Slide 34 text

現代的 Linux Consumer Audio Stack https://medium.com/@YihuiXiong/record-play-audio-on-linux-8f59adf93710

Slide 35

Slide 35 text

● 是一個軟體架構 (software framework) 和部 份的 Linux Kernel, 提供音效卡驅動程式 API ● 包括指令列工具 ● alsactl, amixer, arecord/aplay and alsamixer ALSA (Advanced Linux Sound Architecture)

Slide 36

Slide 36 text

● /usr/share/alsa/alsa.conf => hook 兩個檔案 + 預設使用 Card 0 和 Device 0 作為音訊設備 ● /etc/asound.conf( 系統層級的設定檔 ) ● ~/.asoundrc( 使用者層級的設定檔 ) ● 相關名詞 (device) ● control: 音效卡的控制 , 例如通道選擇 / 混音 / 麥克風控制等 ● pcmc: 用於錄音的 pcm 設備 ● pcmp: 用於播放的 pcm 設備 ● seq: 音序器 ● timer: 計時器 相關設定檔

Slide 37

Slide 37 text

將喇叭插到 Pi 上的 3.5mm Audio Jack 改成預設 audio 從 3.5mm jack 輸出 , 打以下指令 $ pactl set-default-sink 1

Slide 38

Slide 38 text

● espeak( 支援多國語言 ) ● festival( 不支援中文 ) ● zhspeak( 支援中文 ) ● gtts-cli( 支援多國語言 , 需要連網 ) Text to Speech(TTS) on Linux https://elinux.org/RPi_Text_to_Speech_(Speech_Synthesis)

Slide 39

Slide 39 text

● $ pactl set-default-sink 1 ● $ espeak "hello world" ● $ espeak -p90 "hello world" ● $ espeak -vzh " 你好 " ● $ echo " 你好帥 " > words.txt ● $ espeak -vzh+m2 -s 150 -f words.txt -p: 音調 ( 預設 50) -vzh: 中文 m2: 第二種男生聲音 f2: 第二種女生聲音 -s: 速度 espeak

Slide 40

Slide 40 text

● 需要下載安裝執行檔和 ogg 音訊檔 ● $ cd ~ ● $ wget http://bit.ly/3iWvTpP -O zhspeak_4.3.0.tar.gz ● $ tar zxvf zhspeak_4.3.0.tar.gz ● $ cd ~/zhspeak/bin ● $ ./zhspeak 你好帥 zhspeak https://www.eguidedog.net/zhspeak.php

Slide 41

Slide 41 text

● 英文 ● $ gtts-cli 'hello' --output hello.mp3 ● $ mpg123 hello.mp3 ● 中文 ● $ gtts-cli 'Taipei 現在溫度是 31 度 ' -l zh-TW --output hello.mp3 ● $ mpg123 hello.mp3 gtts-cli ( 需要聯網 ) https://pypi.org/project/gTTS/

Slide 42

Slide 42 text

控制 ReSpeaker 2-Mics 的 GPIO

Slide 43

Slide 43 text

接到實體腳位 11 接到實體腳位 32

Slide 44

Slide 44 text

44 import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BOARD) BTN_PIN = 11 GPIO.setup(BTN_PIN, GPIO.IN) def mycallback(channel): print("Button pressed") try: GPIO.add_event_detect(BTN_PIN, \ GPIO.FALLING, \ callback=mycallback, \ bouncetime=200) while True: time.sleep(10) finally: GPIO.cleanup() 測試按鍵 ( 實體腳位 11)

Slide 45

Slide 45 text

45 DEMO push_button_interrupt.py $ cd ~/hack-respeaker/01-gpio $ python3 push_button_interrupt.py

Slide 46

Slide 46 text

Grove 接頭 ● 由 seeedstudio 設計的 grove system ● 數位輸出 / 輸入由四根 pin 控制 http://www.seeedstudio.com/blog/2016/03/09/tutorial-intro-to-grove-connectors-for-arduinoraspberry-pi-projects/

Slide 47

Slide 47 text

47 ● LED_PIN = 32 GPIO.setup(LED_PIN, GPIO.OUT, initial=GPIO.LOW) ● try: while True: print("LED is on") ● GPIO.output(LED_PIN, GPIO.HIGH) time.sleep(2) print("LED is off") ● GPIO.output(LED_PIN, GPIO.LOW) time.sleep(2) except KeyboardInterrupt: print("Exception: KeyboardInterrupt") finally: GPIO.cleanup() 測試 GPIO12( 實體腳位 32)

Slide 48

Slide 48 text

48 DEMO grove_gpio12.py $ cd ~/hack-respeaker/01-gpio $ python3 grove_gpio12.py

Slide 49

Slide 49 text

49 實驗 2: Google Assistant 目的 : 設定 Google 服務

Slide 50

Slide 50 text

使用 Google Assistant SDK

Slide 51

Slide 51 text

https://www.slideshare.net/greenido/actions-on-google-gdd-europe 使用情境

Slide 52

Slide 52 text

互動式對話 https://marketingland.com/survey-amazon-echo-google-home-owners-interested-apple-homepod-217549

Slide 53

Slide 53 text

自然語言處理與動作反應 https://marketingland.com/survey-amazon-echo-google-home-owners-interested-apple-homepod-217549

Slide 54

Slide 54 text

● 特色 ● Hotword detection ● Voice control ● Natural language understanding ● SDK 元件 ● Google Assistant Library – 原生 Python ● Google Assistant Service – 使用 gRPC API 傳遞 , 可和 Go, Java, C#, Node.js or Ruby 介接 安裝 Google Assistant SDK https://developers.google.com/assistant/sdk/overview

Slide 55

Slide 55 text

● 設定 Google Assistant 的順序 ● 專案 (project)> 模型 (model)> 設備 (device) ● 在 console.actions.google.com 建立專案 ● 在 console.cloud.google.com 設定功能與權限 設定 Google Assistant 基本概念 https://developers.google.com/assistant/sdk/overview

Slide 56

Slide 56 text

● 安裝 Google Assistant Library ● 建立專案 ● 啟用 Google Assistant API ● 產生驗證檔案 ● 用範例程式測試 操作步驟 - Configure a Developer Project and Account Settings https://developers.google.com/assistant/sdk/overview

Slide 57

Slide 57 text

● https://console.actions.google.com 從 console.action.google.com 建立專案

Slide 58

Slide 58 text

取一個響亮的名稱吧

Slide 59

Slide 59 text

完成新建專案

Slide 60

Slide 60 text

● https://console.cloud.google.com/ 啟用 Google Assistant API

Slide 61

Slide 61 text

API & Service > Dashboard

Slide 62

Slide 62 text

Dashboard > Enable API

Slide 63

Slide 63 text

搜尋 Google Assistant API

Slide 64

Slide 64 text

啟用 Google Assistant API

Slide 65

Slide 65 text

● https://console.cloud.google.com/ 產生驗證檔案 選擇專案

Slide 66

Slide 66 text

選擇 OAuth 驗證方式

Slide 67

Slide 67 text

選擇其他類型

Slide 68

Slide 68 text

下載建立好的驗證檔案 下載

Slide 69

Slide 69 text

69 ● 下載到本機端的檔案名稱為 client_secret_xxx.apps.googleuserco ntent.com.json ● 傳回到 Pi 的目錄為 /home/pi/Downloads ● 檔名為 credentials.json 將本機端的的檔案傳回 Pi

Slide 70

Slide 70 text

70 ● 下載網址 http://winscp.net/eng/download.php 在 Windows 上安裝 WinSCP http://winscp.net/ Windows Pi

Slide 71

Slide 71 text

71 ● $ scp /path/to/file [email protected]:/path ● 範例 ( 以下為同一行 ) ● $ scp /home/sosorry/Downloads/client_secret_x xx.apps.googleusercontent.com.js [email protected]:/home/pi/Downloads/cre dentials.json 在 Mac 上使用 scp Pi 的 IP

Slide 72

Slide 72 text

● 安裝授權工具 (authorization tool) ● 產生驗證資訊 (credentials.json) ● 開啟瀏覽器到驗證頁面得到驗證碼 ● 在終端機輸入驗證碼 建立驗證資訊 (Generate Credentials) https://developers.google.com/assistant/sdk/guides/library/python/embed/run-sample

Slide 73

Slide 73 text

OAuth 2.0 使用 Authorization Code https://cloud.google.com/community/tutorials/understanding-oauth2-and-deploy-a-basic-auth-srv-to-cloud-functions

Slide 74

Slide 74 text

● $ cd ~/AIY-projects-python ● $ source env/bin/activate ● (env) $ google-oauthlib-tool --scope https://www.googleapis.com/auth/assistant-sdk-prototype --save --headless --client-secrets /path/to/credentials.json ● 範例 ● (env) $ google-oauthlib-tool --scope https://www.googleapis.com/auth/assistant-sdk-prototype --save --headless --client-secrets /home/pi/Downloads/credentials.json (hackmd) 產生 OAuth2 驗證資訊 https://developers.google.com/assistant/sdk/guides/library/python/embed/install-sample

Slide 75

Slide 75 text

產生驗證資訊 https://developers.google.com/assistant/sdk/guides/library/python/embed/install-sample

Slide 76

Slide 76 text

將網址貼到瀏覽器 https://developers.google.com/assistant/sdk/guides/library/python/embed/install-sample 如果出現 401 的錯誤 點選 Learn more

Slide 77

Slide 77 text

在 support email 選擇自己的 email 感謝淡江大學資創系 Ting 的貢獻 選擇自己的 email 以後 save

Slide 78

Slide 78 text

再將網址貼到瀏覽器 https://developers.google.com/assistant/sdk/guides/library/python/embed/install-sample

Slide 79

Slide 79 text

准許存取 https://developers.google.com/assistant/sdk/guides/library/python/embed/install-sample

Slide 80

Slide 80 text

產生驗證碼 https://developers.google.com/assistant/sdk/guides/library/python/embed/install-sample

Slide 81

Slide 81 text

將驗證碼貼回去 https://developers.google.com/assistant/sdk/guides/library/python/embed/install-sample

Slide 82

Slide 82 text

建立 OAuth 驗證檔 https://developers.google.com/assistant/sdk/guides/library/python/embed/install-sample

Slide 83

Slide 83 text

Google Home Architecture

Slide 84

Slide 84 text

服務串接情境 可使用任意裝置 https://programmaticponderings.com/2018/08/11/

Slide 85

Slide 85 text

Device Type https://developers.google.com/actions/smarthome/guides/

Slide 86

Slide 86 text

Device Trait https://developers.google.com/assistant/sdk/reference/traits/

Slide 87

Slide 87 text

使用 Google Assistant SDK

Slide 88

Slide 88 text

● https://github.com/googlesamples/assistant-sdk-python 但 Google 不再維護了 ...

Slide 89

Slide 89 text

● 測試預設喇叭和麥克風功能 ● > audio_helpers.py ● 使用文字輸入和 Google Assistant 交談 ● > textinput.py ● 按下 Enter 後 , 使用語音和 Google Assistant 交談 ● > pushtotalk.py 測試其他範例程式 https://github.com/googlesamples/assistant-sdk-python

Slide 90

Slide 90 text

● (env) $ python ~/assistant-sdk-python/google-assistant- sdk/googlesamples/assistant/grpc/audio_helpers.py (hackmd) 執行 audio_helpers.py 開始錄音 , 請講話

Slide 91

Slide 91 text

● (env) $ python ~/assistant-sdk-python/google-assistant- sdk/googlesamples/assistant/grpc/textinput.py --device- model-id --device-id (hackmd) 執行 textinput.py 請輸入文字

Slide 92

Slide 92 text

● 問時間 (what time is it) textinput.py

Slide 93

Slide 93 text

● 問天氣 (how is the weather tomorrow) textinput.py

Slide 94

Slide 94 text

● (env) $ python ~/assistant-sdk-python/google-assistant- sdk/googlesamples/assistant/grpc/pushtotalk.py --device- model-id --device-id (hackmd) 執行 pushtotalk.py 按下 Enter 以後開始說話

Slide 95

Slide 95 text

● 問時間 (what time is it) pushtotalk.py 即時的 Speech to Text

Slide 96

Slide 96 text

96 實驗 3: 語音轉文字 (STT) 目的 : 語音辨識和語音喚醒

Slide 97

Slide 97 text

使用麥克風收音後 , 該怎麼變成文字 ? https://ithelp.ithome.com.tw/articles/10195763

Slide 98

Slide 98 text

● 語言系統由發音 (phonetics), 音韻 (phonology), 形態 (morphology), 詞彙 (lexicon), 句法 (syntax), 語義 (semantics), 語用學 (pragmatics) 等所組成 https://www.slideshare.net/zelandiya/kiwipycon-2014-nlp-with-python-tutorial

Slide 99

Slide 99 text

99 目前 Google Assistant 支援的語系 https://developers.google.com/assistant/sdk/reference/library/languages

Slide 100

Slide 100 text

● STT(Speech to Text) 含訊號處理 (Signal), 聲學處理 (Acoustic) 和語言處理 (Language) 語音訊號處理 + 自然語音處理 https://ithelp.ithome.com.tw/articles/10195970

Slide 101

Slide 101 text

● 支援多種語音辨識引擎 ● CMU Sphinx (works offline) ● Google Speech Recognition ● Google Cloud Speech API ● Wit.ai ● Microsoft Bing Voice Recognition ● Houndify API ● IBM Speech to Text ● Snowboy Hotword Detection (works offline) 使用 SpeechRecognition 套件 https://pypi.python.org/pypi/SpeechRecognition/

Slide 102

Slide 102 text

試試看 Google 的 STT 吧 #!/usr/bin/python3 ● import speech_recognition as sr r = sr.Recognizer() with sr.Microphone() as source: r.adjust_for_ambient_noise(source, duration=1) print('Say something>>> ') audio = r.listen(source, timeout=10) print('Google Speech Recognition thinks you said:') sent = r.recognize_google(audio, language="zh-TW") print("{}".format(sent))

Slide 103

Slide 103 text

103 DEMO stt_demo.py $ cd ~/hack-respeaker/03-stt $ python3 stt_demo.py

Slide 104

Slide 104 text

104 ● r = sr.Recognizer() ● # 停止動態門檻值 ● r.dynamic_energy_threshold = False ● # 停止多少秒數後視為結束語句 ● r.pause_threshold = 1 ● # 最小語句秒數 ● r.phrase_threshold = 0.3 ● # 開始和結束的等待秒數 ● r.non_speaking_duration = 0.5 speech_recognition 常用參數

Slide 105

Slide 105 text

105 Text-to-Speech(TTS) https://en.wikipedia.org/wiki/Speech_synthesis https://slideplayer.com/slide/4846056/ Linguistic * 正規化 * 斷詞斷句 * 字轉音 * 標記詞性 Acoustic * 音量 * 音頻 * 語速 Synthesis * 疊加合成 * 共振峰合成 * 線性編碼預測合成

Slide 106

Slide 106 text

試試看 Google 的 TTS 吧 #!/usr/bin/python3 from gtts import gTTS from pygame import mixer def speak(sentence, lang, loops=1): with tempfile.NamedTemporaryFile(delete=True) as fp: tts = gTTS(text=sentence, lang=lang) tts.save('{}.mp3'.format(fp.name)) mixer.init() mixer.music.load('{}.mp3'.format(fp.name)) mixer.music.play(loops) sentence = 'Hello World' speak(sentence, 'en') time.sleep(2)

Slide 107

Slide 107 text

107 DEMO tts_demo.py $ cd ~/hack-respeaker/03-stt $ python3 tts_demo.py

Slide 108

Slide 108 text

可以用語音輸入做為程式進入點嗎?

Slide 109

Slide 109 text

● 在一段音訊中 , 可針對特定喚醒詞被觸發的演算法 ● 好的喚醒詞檢測引擎 ● 低的錯誤接收率 (FAR, false acceptance rate) ● 低的錯誤拒絕率 (FRR, false rejection rate) ● 低的資源利用率 喚醒詞檢測引擎 C 比 A 好

Slide 110

Slide 110 text

喚醒詞檢測引擎比較 https://picovoice.ai/blog/benchmarking-a-wake-word-detection-engine/

Slide 111

Slide 111 text

● 一個高度客製化的喚醒詞檢測引擎 , 並且 ● 可客製化喚醒詞 ● 一直監聽 , 但保護隱私 ● 輕巧 , 容易移植 Snowboy https://github.com/Kitt-AI/snowboy

Slide 112

Slide 112 text

解碼器 (decoder) 結構 ├── README.md ├── _snowboydetect.so ├── demo.py ├── demo2.py ├── light.py ├── requirements.txt ├── resources │ ├── ding.wav │ ├── dong.wav │ ├── common.res │ └── snowboy.umdl ├── snowboydecoder.py ├── snowboydetect.py └── version snowboy 喚醒詞模型 由 SWIG 產生的 Python 封裝檔 使用 SWIG 編譯的動態鏈接庫 控制樹莓派 GPIO

Slide 113

Slide 113 text

demo.py import snowboydecoder model = sys.argv[1] signal.signal(signal.SIGINT, signal_handler) detector = snowboydecoder.HotwordDetector(model, sensitivity=0.5) print('Listening... Press Ctrl+C to exit') detector.start(detected_callback=snowboydecoder.play_audio_file, interrupt_check=interrupt_callback, sleep_time=0.03) ● detector.terminate()

Slide 114

Slide 114 text

114 DEMO demo.py $ cd ~/hack-respeaker/03-stt/snowboy $ python3 demo.py resources/snowboy.umdl

Slide 115

Slide 115 text

整合 SpeechRecognition import snowboydecoder detector = snowboydecoder.HotwordDetector(model, sensitivity=0.5) def audioRecorderCallback(fname): r = sr.Recognizer() with sr.AudioFile(fname) as source: audio = r.record(source) # read the entire audio file print(r.recognize_google(audio, language="zh-TW")) detector.start(detected_callback=detectedCallback, audio_recorder_callback=audioRecorderCallback, interrupt_check=interrupt_callback, sleep_time=0.01) detector.terminate() 可調整靈敏度,通常從 0.38 到 0.5

Slide 116

Slide 116 text

116 DEMO demo4.py $ cd ~/hack-respeaker/03-stt/snowboy $ python3 demo4.py resources/snowboy.umdl

Slide 117

Slide 117 text

訓練自己的喚醒詞 (hotword)

Slide 118

Slide 118 text

( 原本 ) 在 snowboy 平台建立喚醒詞

Slide 119

Slide 119 text

( 原本 ) 一共要做三次 開始錄音

Slide 120

Slide 120 text

120 ● snowboy 雲端喚醒詞平台在 2020/12/31 關閉 kitt.ai 在 2017 賣給百度 https://www.ithome.com.tw/news/115414

Slide 121

Slide 121 text

121 ● 我們移植 snowboy 功能 , 重新建立新的訓練平台 ● 使用網頁版的 snowboy 訓練 ● http://snowboy.ricelee.com/kitty.html 訓練喚醒詞

Slide 122

Slide 122 text

122 ● 錄製喚醒詞 , 取名 record1.wav, 結束按 ctrl+c ● pi$ cd ~ ● pi$ rec -r 16000 -c 1 -b 16 -e signed-integer -t wav record1.wav (hackmd) 錄製三次喚醒詞

Slide 123

Slide 123 text

123 ● http://snowboy.ricelee.com/kitty.html 使用網頁版的 snowboy 訓練

Slide 124

Slide 124 text

124 ● http://snowboy.ricelee.com/kitty.html 上傳使用 rec 指令錄製的喚醒詞 第二步 : 上傳 record1.wav 和 record2.wav 和 record3.wav 第一步 : 選擇檔案

Slide 125

Slide 125 text

125 ● http://snowboy.ricelee.com/kitty.html 訓練完喚醒詞後可以下載 訓練完成後 , 可以下載喚醒詞模型 將此一模型放到 pi 的 snowboy/resources 目錄下

Slide 126

Slide 126 text

126 DEMO demo.py $ cd ~/hack-respeaker/03-stt/snowboy $ python3 demo.py resources/hotword.pmdl 使用自訂喚醒詞 , 可能需要調整靈敏度

Slide 127

Slide 127 text

127 DEMO demo4.py $ cd ~/hack-respeaker/03-stt/snowboy $ python3 demo4.py resources/hotword.pmdl 使用自訂喚醒詞喚醒後再做 STT

Slide 128

Slide 128 text

● # 語音合成英文以後用 mpg123 播放 ● $ gtts-cli 'hello' --output hello.mp3 ● $ mpg123 hello.mp3 ● # 轉成 wave 檔以後用 aplay 播放 ● $ mpg123 -w ding.wav hello.mp3 ● $ aplay ding.wav 使用 mpg123 將 MP3 轉成 wav

Slide 129

Slide 129 text

● 預設的回應語檔名為 ding.wav, 檔案路徑 在 /path/to/snowboy/resources 下 ● 將做好的 ding.wav 放到 resources 下 ( 先備份 ) ● $ cd ~/hack-audio/03-stt/snowboy ● $ mv resources/ding.wav resources/ding.wav.bak ● $ mv ding.wav resources/ 換掉回應語 ding.wav

Slide 130

Slide 130 text

130 DEMO demo.py 自訂喚醒詞和回應語 $ cd ~/hack-respeaker/03-stt/snowboy $ python3 demo.py resources/hotword.pmdl

Slide 131

Slide 131 text

131 實驗 4: 使用 Dialogflow 平台 目的 : 自然語言了解 (NLU)

Slide 132

Slide 132 text

自然語言處理 (NLP) http://www.techprenuer.com/entrepreneur/artificial-intelligence-natural-language-processing-fundamentals/

Slide 133

Slide 133 text

自然語言理解 (NLU) - Natural Language Understanding https://www.jianshu.com/p/90a0e2a7e265

Slide 134

Slide 134 text

● Dialogflow.com(Google) ● Luis.ai(Microsoft) ● Wit.ai(Facebook) ● Olami.ai(VIA 威盛 ) ● UNIT(Baidu 服务 ) ● DUI( 思必 服务 驰 ) 自然語言理解 (NLU) 平台

Slide 135

Slide 135 text

● 可能的問句 ● 請告訴我明天天氣如何? ● 明天外面是不是很熱? ● 台北下星期會不會下雨 ● 天氣怎麼樣 ● 下星期會下雨嗎 ● Intent( 意圖 ) => 問天氣 ● Entity( 實體 ) => 日期 , 地點 明天台北的天氣如何?

Slide 136

Slide 136 text

● Agent ● 一個具有特定功能範圍的 NLU 模型 ● Intent ● 一個句子的意圖 , 通常可以用一句話回答 ● Entity ● 自然語言中有關鍵意義的參數 , 如時間 / 城市 ● User Says ● 使用者用自然語言說出的一句話 自然語言理解 (NLU) 重要元素

Slide 137

Slide 137 text

● 原名稱為 Api.ai, 或是 Speaktoit ● 提供自然語言對話和人機互動技術 ● 支援 Android, iOS 和 Windows Phone ● Google 在 2017 年收購 , 改名為 dialogflow ● 已整合到 Google Cloud 等服務 Dialogflow https://cloud.google.com/dialogflow-enterprise/

Slide 138

Slide 138 text

● 建立⼀個 Agent( 代理 AI) ● 建立所需的 Entity( 句⼦中的物件 ) ● 建立所有的 Intent( 句⼦的意圖 ) ● 測試 (Testing) 和訓練 (Training) 使用 Dialogflow 步驟

Slide 139

Slide 139 text

● https://dialogflow.cloud.google.com 登入使用

Slide 140

Slide 140 text

建立新的 Agent

Slide 141

Slide 141 text

建立新的 Agent 要分析的語言 , 建立後不可改 自動建立 GCP 專案

Slide 142

Slide 142 text

主控台 點選後會展開左邊選單

Slide 143

Slide 143 text

建立新的 Entities 建立新的 Entities

Slide 144

Slide 144 text

Entity 屬性 ( 名稱 ) 記得存檔 Entity 代號 同義詞 Entity 內容

Slide 145

Slide 145 text

再建立一個 Entity( 動作 ) Entity 代號 記得存檔 同義詞 Entity 內容

Slide 146

Slide 146 text

在沒有建立 Intent 輸入文字測試 開燈

Slide 147

Slide 147 text

回傳預設結果 預設回應 Default Fallback Intent

Slide 148

Slide 148 text

建立新的 Intent 預設回應 Default Fallback Intent

Slide 149

Slide 149 text

建立新的 Intent Intent 名稱 可能的用語 (User Says)

Slide 150

Slide 150 text

輸入可能的用語 (User Says) 可能的用語 自動識別出 Entity

Slide 151

Slide 151 text

再輸入一個可能的用語 (User Says) 再輸入可能的用語 自動識別出 Entity 存檔後測試

Slide 152

Slide 152 text

測試輸入 有認得 Intent, 可是沒有內容 開燈 開燈

Slide 153

Slide 153 text

新增 Intent 的回覆 新增回覆

Slide 154

Slide 154 text

先用底線將句子連成一個單字 完成後存檔 通常是有意義的句子 , 利如 turn_on_light_ok

Slide 155

Slide 155 text

測試輸入 有認得 , 並且 傳回正確回覆 開燈 開燈

Slide 156

Slide 156 text

測試新的輸入 如果不認得 去開燈

Slide 157

Slide 157 text

使用 Training 功能 剛剛的測試用語

Slide 158

Slide 158 text

( 如果沒有自動選取的話 ) 還要做些微調 將字選取起來以後選擇對應的 Entity 燈對應到 light

Slide 159

Slide 159 text

將字選取起來以後選擇對應的 Entity 燈對應到 turn_on ( 如果沒有自動選取的話 ) 還要做些微調

Slide 160

Slide 160 text

記得要先存檔 存檔

Slide 161

Slide 161 text

認得新的用語了 有認得 , 並且 傳回正確回覆 開燈 去開燈

Slide 162

Slide 162 text

● 根據不同的用語 (User Says) ● 去開燈 ● 燈打開 ● 打開燈 ● 對應到相同的意圖 (Intent) ● turnOnLight ● 並且有相同的回應 (Response) ● turn_on_light_ok 目前 Dialogflow 會了什麼?

Slide 163

Slide 163 text

但如果判斷錯了怎麼辦? 判斷錯誤 關燈

Slide 164

Slide 164 text

加強訓練! 點選進入

Slide 165

Slide 165 text

把錯誤的找出來 , 剃除掉 改成預設回應 修改完後存檔

Slide 166

Slide 166 text

再試一次 不再判斷錯誤 關燈

Slide 167

Slide 167 text

● v1 的 API 比較簡單 , 但安全性弱 (2021 已停用 ) ● v2 的 API 要設定 Google Cloud Platform 該如何整合到程式裡?

Slide 168

Slide 168 text

168 使用 v2 的 API(OAuth 2)

Slide 169

Slide 169 text

https://console.cloud.google.com/ 3. 選擇 APIs & Services 4. 選擇 Credentials 1. 選擇專案 2.

Slide 170

Slide 170 text

驗證選擇 Service Account Key

Slide 171

Slide 171 text

取個名字 ( 例如 : Dialogflow Integrations)

Slide 172

Slide 172 text

選擇 Service Account 角色

Slide 173

Slide 173 text

Dialogflow > Dialogflow API Admin

Slide 174

Slide 174 text

選擇 Dialogflow API Admin 完成 Dialogflow API Admin

Slide 175

Slide 175 text

修改新建立好的 Service Accounts

Slide 176

Slide 176 text

Create new keys 建立新的 Private Key

Slide 177

Slide 177 text

選擇 JSON 格式後建立

Slide 178

Slide 178 text

下載 Private Key 以後再傳到 Pi

Slide 179

Slide 179 text

● $ nano ~/hack-respeaker/smart_speaker.conf [dialogflow] google_app_credential = FIXME ● project_id = FIXME print(response.text) 將儲存路徑寫在設定檔 將 google_app_credential 換成自己的 例如 : /home/pi/ 檔名 .json

Slide 180

Slide 180 text

project_id 在哪裡? project_id

Slide 181

Slide 181 text

config = configparser.ConfigParser() config.read('../smart_speaker.conf') os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = config.get('dialogflow', 'google_app_credential') project_id = config.get('dialogflow', 'project_id') query = sys.argv[1] def detect_intent_texts(project_id, session_id, texts, language_code): import dialogflow_v2 as dialogflow session_client = dialogflow.SessionsClient() session = session_client.session_path(project_id, session_id) text_input = dialogflow.types.TextInput( text=texts, language_code=language_code) query_input = dialogflow.types.QueryInput(text=text_input) response = session_client.detect_intent( session=session, query_input=query_input) ● detect_intent_texts(project_id, session_id, query, language_code) Python 程式串接

Slide 182

Slide 182 text

182 DEMO request_dialogflow_v2.py $ cd ~/hack-respeaker/04-nlu $ python3 request_dialogflow_v2.py 開燈 自己定義的查詢字串

Slide 183

Slide 183 text

使用 Python 呼叫 v2 API 成功 Intent 回覆 查詢字串

Slide 184

Slide 184 text

● ImportError: /lib/arm-linux- gnueabihf/libc.so.6: version `GLIBC_2.33' not found (required by /usr/local/lib/python3.7/dist- packages/grpc/_cython/cygrpc.cpython-37m-arm- linux-gnueabihf.so) ● 解決方法: # 再裝一次 grpcio 和 grpcio-tools ● $ sudo pip3 install -I --force-reinstall grpcio ● $ sudo pip3 install grpcio-tools 如果遇到錯誤如下

Slide 185

Slide 185 text

將 Dialogflow 整合到服務裡 https://www.analyticsvidhya.com/blog/2018/03/how-to-build-an-intelligent-chatbot-for-slack-using-dialogflow-api/

Slide 186

Slide 186 text

● 1. 使用客製化關鍵字喚醒 Pi ● snowboy 客製化 ● 2. 利用 ' 開燈 ' 或是 ' 燈打開 ' 等句子讓 LED 亮或是暗 ● 用 STT 讀取語音輸入 (snowboy/demo4.py) ● 把文字用 request 送到 dialogflow(request_dialogflow_v1.py) 改造 Google AIY Voice Kit

Slide 187

Slide 187 text

187 DEMO nlu_turn_on_light_v2.py $ cd ~/hack-respeaker/03-stt/snowboy $ python3 nlu_turn_on_light_v2.py resources/hotword.pmdl

Slide 188

Slide 188 text

用自訂喚醒詞喚醒後再做 NLU Intent 回覆 查詢字串 自訂喚醒詞

Slide 189

Slide 189 text

189 讓我們的 AIY 更智慧一點

Slide 190

Slide 190 text

用瀏覽器播 Youtube https://techcrunch.com/2010/03/31/youtubes-new-streamlined-watch-page-boosts-engagement-by-7/

Slide 191

Slide 191 text

● 1. 給予搜尋字串回傳影片列表 ● 2. 解析 HTML 找出視訊來源 (yt-dlp) ● 需先安裝套件 $ sudo pip3 install -U yt-dlp ● 3. 使用多媒體播放器播放音訊串流 (vlc) 用程式播 Youtube 裡面的音樂

Slide 192

Slide 192 text

● 因為 youtube_dl 在 2020/10 美國唱片業協會 (RIAA) 控 訴 , 因此專案被 github 下架 , 之後更新不頻繁且不穩定 ● yt-dlp 是 youtube-dl 的分支 , 主要在添加新功能和打 patch, 並維持和 youtube_dl 同步 ● 使用的 function 和 youtube_dl 完全一樣 ! 使用 yt-dlp 原因 https://techtalk.ithome.com.tw/news/140720

Slide 193

Slide 193 text

從 yt_dlp 找來源再用 vlc 播放 ● import yt_dlp as youtube_dl ydl_opts = {音訊參數} ● def play_music(name): with youtube_dl.YoutubeDL(ydl_opts) as ydl: meta = ydl.extract_info(name, download=False) if meta: info = meta['entries'][0] playurl = info['url'] print(playurl) Instance = vlc.Instance() player = Instance.media_player_new() Media = Instance.media_new(playurl) Media.get_mrl() player.set_media(Media) player.play()

Slide 194

Slide 194 text

● 修改第四行 , 將 yt_dlp 更名為 youtube_dl ● import youtube_dl 改為 import yt_dlp as youtube_dl 修改 yt3.py 4 4 將 yt_dlp 取別名 , 名稱為 youtube_dl https://github.com/yt-dlp/yt-dlp

Slide 195

Slide 195 text

195 DEMO yt3.py $ cd ~/hack-respeaker/03-stt/snowboy $ python3 yt3.py " 查詢字串 " " 周杰倫 青花瓷 "

Slide 196

Slide 196 text

● AttributeError: module 'vlc' has no attribute 'Instance' ● 解決方法: # 先移除 ● $ sudo apt-get remove -y --purge vlc* libvlc* ● $ sudo pip uninstall -y vlc python-vlc ● $ sudo pip3 uninstall -y vlc python-vlc ● $ sudo apt-get clean # 再重新安裝 ● $ sudo apt-get install -y vlc ● $ sudo pip3 install -U python-vlc 如果遇到錯誤如下

Slide 197

Slide 197 text

● 1. 建立新的 Entity( 播 , 歌手 , 曲名 ) ● 2. 建立新的 Intent( 解析播音樂自然語言 ) ● 3. 回傳 Response 分析出的歌手和曲名 再用 Dialogflow 分析吧

Slide 198

Slide 198 text

先建立新的 Entity 新增完畢後存檔 播放

Slide 199

Slide 199 text

再建立新的 Intent

Slide 200

Slide 200 text

取個喜歡的名字吧 playMusic

Slide 201

Slide 201 text

先建立新的 Entity 可能的用語 自動識別出 Entity @sys.music-artist 是系統的 Entity

Slide 202

Slide 202 text

將不認識的曲名加到 @sys.any @sys.any 將字選取起來以後選擇對應的 Entity

Slide 203

Slide 203 text

@sys.any 加入一筆資料了 雪狼湖

Slide 204

Slide 204 text

可用的變數 變數代號

Slide 205

Slide 205 text

新增回應 (Response) 1. 使用空白分隔變數 2. 變數名稱開頭符號為 $ 選擇 $music-artist

Slide 206

Slide 206 text

輸入回應的下一個變數 1. 使用空白分隔變數 2. 變數名稱開頭符號為 $ 選擇 $any

Slide 207

Slide 207 text

輸入完成後記得存檔 play $music-artist $any

Slide 208

Slide 208 text

測試輸入 有認得 , 並且 傳回正確回覆 播張學友的雪狼湖

Slide 209

Slide 209 text

再訓練一筆試試看 放蔡依林的舞孃

Slide 210

Slide 210 text

將不認識的曲名加到 @sys.any @sys.any 將字選取起來以後選擇對應的 Entity

Slide 211

Slide 211 text

測試輸入 放蔡依林的舞孃 play 蔡依林 舞孃

Slide 212

Slide 212 text

● 根據不同的用語 (User Says) ● 播張學友的雪狼湖 ● 放蔡依林的舞孃 ● 對應到相同的意圖 (Intent) ● playMusic ● 根據使用者輸入回應帶有變數的結果 (Response) ● play 蔡依林 舞孃 ● play 張學友 雪狼湖 目前 Dialogflow 會了什麼?

Slide 213

Slide 213 text

● JSON(JavaScript Object Notation) 是一種資料結構 ● 物件 (object) 以 { } 表示 ● 鍵 / 值 (collection) 以 : 表示 ● 陣列 (array) 以 [ ] 表示 ● 最外層用 {} 包起來 資料使用 JSON 結構傳送 https://www.ssaurel.com/blog/parse-and-write-json-data-in-java-with-gson/

Slide 214

Slide 214 text

解析回傳結果 查詢字串 Entities Intent 回覆

Slide 215

Slide 215 text

215 DEMO request_dialogflow_v2.py $ cd ~/hack-respeaker/04-nlu $ python3 request_dialogflow_v2.py 放蔡依 林的舞孃 自己定義的查詢字串

Slide 216

Slide 216 text

整合到程式裡面成功 play 蔡依林 舞孃 查詢字串

Slide 217

Slide 217 text

整合其他服務 (Youtube) https://www.jianshu.com/p/90a0e2a7e265

Slide 218

Slide 218 text

● 1. 使用客製化關鍵字喚醒 Pi ● snowboy 客製化 ● 2. 語音輸入 ' 播 ooo 的 xxx’ ● 用 STT 讀取語音輸入 (snowboy/demo4.py) ● 把文字用 request 送到 dialogflow(request_dialogflow_v2.py) ● 根據回傳 response, 播 Youtube 音樂 (yt3.py) 新技能:點歌播放

Slide 219

Slide 219 text

219 DEMO nlu_play_music_v2.py $ cd ~/hack-respeaker/03-stt/snowboy $ python3 nlu_play_music_v2.py resources/hotword.pmdl

Slide 220

Slide 220 text

使用自訂喚醒詞喚醒後再做 NLU Youtube 音訊來源 查詢字串 使用自訂喚醒詞 Intent 回覆

Slide 221

Slide 221 text

221 整合 ChatGPT

Slide 222

Slide 222 text

● OpenAI 開發的 AI 聊天機器人程式 , 於 2022/11 推出 ● 基於 GPT-3.5 和 GPT-4 的大型語言模型 (LLM) 並以強化 學習訓練 ChatGPT Chat Generative Pre-trained Transformer https://openai.com/blog/chatgpt

Slide 223

Slide 223 text

ChatGPT 網頁版

Slide 224

Slide 224 text

串接 GhatGPI API( 需付費 ) import openai ● ● openai.api_key = config.get('dialogflow', 'openai_api_key') ● ● messages = [] ● message = "樹莓派可以吃嗎?" ● ● if message: ● messages.append( ● {"role": "user", "content": message}, ● ) ● chat = openai.ChatCompletion.create( ● model="gpt-3.5-turbo", messages=messages ● ) ● ● reply = chat.choices[0].message.content ● print(f"ChatGPT: {reply}") 向 ChatGPT 問問題 ChatGPT 使用的模型

Slide 225

Slide 225 text

225 DEMO test_chatgpt_api.py $ cd ~/hack-respeaker/03-stt/snowboy $ python3 test_chatgpt_api.py

Slide 226

Slide 226 text

226 Raspberry Pi Rocks the World Thanks