본문 바로가기
Tech Story/IoT

라즈베리파이를 이용한 구글어시스턴트스피커

라즈베리파이를 이용한 구글어시스턴트(AI)스피커

라즈베리파이를 이용하여 구글어시스턴트 연동을 통한 인공지능 스피커 만들기 프로젝트

                                                                                                                                                                           2019년 2월

 

 

 

 

 

 

 

 

 

 

▒ 부품

  • 라즈베리파이 3 B+
  • Micro SD Card (16GB)
  • 전원
  • USB 스피커 http://itempage3.auction.co.kr/DetailView.aspx?ItemNo=B636909610
  • USB 마이크(Microphone) http://item.gmarket.co.kr/Item?goodscode=1294374286
  • 목재(스피커, 10x24x1.2cmhttp://www.sonjabee.com/goods/content.asp?num=287873
  • 10mm 알미늄 또는 플라스틱 튜브
 

▒ 기구들

  • 나무 끌(목재용 칼)
  • 드라이버, 니퍼, 자, 나사(4mmx40mmx4ea)
  • 목재용 드릴(3mm, 4mm)
  • 사포(목재 가공)
  • 목재용 오일(대니쉬오닐등), 광택용 니스 or 스프레이
 

 

■ 구글 API 등록
 
1. 구글 콘솔 접속 :  https://console.actions.google.com
2. 프로젝트 추가 : "Add/import project" 클릭

 

3. 대쉬보드에서 프로젝트 추가

(1) 프로젝트 이름 : Raspi-GoogleAssistant (본인이 원하는 이름으로 입력해도 무방함)

(2) 언어 설정 : 한국어 설정, 리전설정

(3) 클릭 "CREATE PROJECT"

 

4. 새로운탭에서 구글 개발자 콘솔접속 & 구글 어시스턴트 활성화

    크롬에서 새로운탭 추가 (기존 구글 콘솔 탭 유지)

    개발자 콘솔 접속 : https://console.developers.google.com/apis/library/embeddedassistant.googleapis.com?pli=1

   (1) 본인이 기존 콘솔에서 추가했던 프로젝트 이름이 맞는지 확인 : Raspi-GoogleAssistant

   (2) 활성화 : 클릭 "Enable"

 

5. 디바이스 등록 페이지 이동

 

6. 디바이스 모델 등록

클릭 "REGISTER MODEL"

 

7.  디바이스 모델 설정

(1) 제품 이름 : Rpi-Speaker (본인이 설정하고 싶은 이름 정하기)

(2) 회사 이름 : Rpi (상용화가 필요 없는 경우 아무 이름이나 상관없음)

(3) 디바이스 타입 : Speaker (AI 스피커이기 때문에 스피커를 설정)

클릭 "REGISTER MODEL"

 

8. 다운로드 OAuth 2.0 자격증

(1) 클릭 : "Download OAuth 2.0 credentials"

(2) 다운로드한 자격증명 파일을 본인 PC(노트북)나 라즈베리파이에 복사해둔다

(3) 클릭 "NEXT"

 

9. 기타설정

클릭 : "SAVE TRAITS" (다른건 설정하지 않고 그냥 저장)

 

10. 완료페이지

 

11. 활동제어 활성화

(1) URL 이동 : https://myaccount.google.com/activitycontrols?pli=1

(2) 모든 활동 : 클릭 "Enable"


 

 

 

■ 구글 어시스턴트 셋팅

앞에서 진행했던 구글 어시스턴트 등록절차를 마무리하고 실제 라즈베리파이에 해당 등록내용을 동작하도록 셋팅하는 절차입니다

 

1. 기본 패키지 업데이트 및 구글어시스턴트 디렉토리 생성

# sudo apt-get update

# mkdir ~/googleassistant

 

# sudo vi ~/googleassitant/credentials.json

 

2. 인증 크리덴셜 저장

구글어시스턴트 등록페이지에서 다운로드한(8번항목 "Download OAuth 2.0 credentials") 파일을 열어서 해당 내용을 "~/googleassitant/credentials.json" 에 붙여 넣기를 합니다

 

3. 파이썬3 설치, 파이썬3 버추얼 환경설치 및 가상 환경변수 셋팅

 # sudo apt-get install python3-dev python3-venv

 # python3 -m venv env

 

4. 최신의 pip, setuptool설치 및 버추얼 파이썬3 환경설정

# env/bin/python -m pip install --upgrade pip setuptools --upgrade

# source env/bin/activate 

(env) pi@raspberrypi: ~ $

 

5. 구글 어시스턴트 라이브러리 설치

# python -m pip install --upgrade google-assistant-library

 # python -m pip install --upgrade google-assistant-sdk[samples]

 




 

■ 구글 어시스턴트 라즈베리파이 권한설정

지금까지 진행한 구글 어시스턴트 환경을 라즈베리파이에 권한을 설정한다.

 

1. 파이썬 인증툴 설치

# python -m pip install --upgrade google-auth-oauthlib[tool]

 

2. 구글 인증 라이브러리 설치

google-oauthlib-tool --client-secrets ~/googleassistant/credentials.json \

--scope https://www.googleapis.com/auth/assistant-sdk-prototype \

--scope https://www.googleapis.com/auth/gcm \

--save --headless


위와 같이 실행하면 아래와 같은 형태가 나오고 URL을 복사해서 크롬부라우저에 입력하면 인증코드가 나온다.

이를 복사해서 아래의 코드 입력란에 붙여넣기 한다.

# Enter the autorization code :

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 


정상적으로 입력하면  “credentials saved: /home/pi/.config/google-oauthlib-tool/credentials.json”이런 메세지가 나와야 한다.



 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

■ 라즈베리파이 구성 및 스피커, 마이크 설치

진행했던 사항중에 제일 힘들었고 시간이 제일 많이 걸린 작업으로 라즈베리파이에서 스피커와 마이크 인식이 잘 안되서 고생을 한참해서 해결을 했지만, 정확하게 문제를 해결한건지 하다보니 된건지는 아이러니 함.

여하튼 여기에 있는 팁을 이용하면 어느정도 해결은 될것으로 생각됩니다.

 

1. 우분투 메이트 설치

   (1) 라즈베리언 사이트에서 우분투 메이트 이미지 다운로드 https://www.raspberrypi.org/downloads/raspbian

   (2) Etcher를 이용하여 SD카드에 우분트 메이트 설치

   (3) Wifi등 네트웍 설정, 원격 접속 설정

   ※ 인터넷을 찾아보면 우분투 메이트 설치는 금방 따라할 수 있습니다.

 

2. 오디오(마이크) 설정

   (1) USB에 연결후 인식 확인

       아래와 같은 명령어를 입력할 때 card 1, device 0 이런 형태로 나오면 우선 라즈베리파이에서 인식은 된것임

 # arecord -l

**** List of CAPTURE Hardware Devices ***

card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]

  Subdevices: 1/1

  Subdevice #0: subdevice #0 

 

   (2) USB스피커 연결후 인식 확인

       아래와 같은 명령어를 입력하여 card 1, device 0 으로 인식하면 연결 성공

# aplay -l

 **** List of PLAYBACK Hardware Devices ****

card 0: ALSA [bcm2835 ALSA], device 0: bcm2835 ALSA [bcm2835 ALSA]

  Subdevices: 7/7

  Subdevice #0: subdevice #0

  Subdevice #1: subdevice #1

  Subdevice #2: subdevice #2

  Subdevice #3: subdevice #3

  Subdevice #4: subdevice #4

  Subdevice #5: subdevice #5

  Subdevice #6: subdevice #6

card 0: ALSA [bcm2835 ALSA], device 1: bcm2835 ALSA [bcm2835 IEC958/HDMI]

  Subdevices: 1/1

  Subdevice #0: subdevice #0

card 1: Device [USB Audio Device], device 0: USB Audio [USB Audio]

  Subdevices: 1/1

  Subdevice #0: subdevice #0

   (3) 마이크, 스피커 기본 환경 설정

       계정 홈에서 .asoundrc를 편집하여 아래와 같이 설정한다.

# vi ~/.asoundrc

 pcm.!default {

        type hw

        card 1

    }

    ctl.!default {

        type hw

        card 1

    }


   (4) 마이크, 스피커 테스트

[ 스피커 테스트  ]

 # speaker-test -t wav         

    ▶ left, right라는 소리가 반복해서 나오면 정상

 

[ 마이크 테스트 ]

 # arecord --format=S16_LE --duration=5 --rate=16000 --file-type=raw out.raw

   녹음한 뒤

 

 # aplay --format=S16_LE --rate=16000 out.raw

   ▶  녹음한게 나오면 정상

 

볼륨을 조절하기 위해서 "alsamixer " 명령어를 이용하여 조절할 수 있으며, 우분트메인트 데스크탑환경에서 스피커설정의 GUI를 이용하여 설정하여도 좋다

※ 스피커와 마이크가 인식은 되지만 아무리하여도 스피커가 잘되는데 마이크가 안되거나 그 반대인 경우가 있는데 정확히 원인은 모르겠으나 라즈베리파이 버그나 오작동인듯하여 인터넷에서 관련 내용이 많이 있어서 찾아봤지만 도움이 되는 내용이 없었음.

그러다 라즈베리파이 패키지 업데이트를 해서 해결했다는 내용을 확인하고 똑 같이 했는데 해결이 됐음.

만약, 스피커나 마이크 동작이 잘 안되면 라즈베리파이 패키지업데이트 후 우분투 데스크탑환경에서 스피커, 마이크 음량조절을 해보시기를 권장. 

 # sudo apt-get update

 # sudo apt-get upgrade

 # sudo apt-get dist-upgrade

 # sudo reboot

※ 위와 같이 해도 안될시는 커널을 업데이트를 해보시고 이외의 오류는 구글링을 통해서 케이스를 찾아보시면 됩니다.

 


 

 

■ 구글 스피커 조립

(1) 스피커 모양 목재 만들기

 


인터넷으로 구매한 스피커모양 목재(10x24x1.2cm)를 가장자리는 1cm 여유를 두고 집에 있는 조각칼을 이용하여 홈을 팝니다. (이는 라즈베리파이와 스피커등을 부탁했을 때 좀더 안쪽에 공간을 여유롭게 하기 위함입니다.

※ 목재의 특성에 따라 집에 있는 조각칼로 충분한 경우가 있고, 목재용 전용 칼을 별도로 구매해서 사용해야되는 경우도 있으니 목재의 특성을 잘 확인하여 구매하시기 바랍니다.

 

(2) 라즈베리파이, 스피커, 마이크 결합 및 목재 Build

  • 상단 스피커 영역과 라즈베리파이 영역의 두께로 인해서 다른 부분보다 더 홈을 파야됩니다. (좀더 모양새를 위해서)
  • 아래위에 있는 스피커는 외부에서 음성과 마이크 소리를 인식하고 들리기 위해서 3mm 목재용 드릴로 구멍을 뚫었습니다.
  • 아래 스피커는 선이 짧아서 별도로 선을 연결해서 납땜
  • 오른쪽 아래 부분에 홈을 별도로 외부까지 판것은 라즈베리파이 전원을 연결하기 위한 위치

 

(3) 결합 및 목재용 수성 페인트칠

  • 나사를 조이기 위해서는 상하단 4곳에 홈을 좀더 파서 나사가 잘 들어가도록 함
  • 뒷판 나사 구멍은 드릴을 4mm로 뚫고 나사 길이는 4mm용 4피스
  • 목재 두께 1.2cm 2개 총 2.4cm
  • 약 1cm 목재사이 공간을 감안하면 전체 두께는 3.4~3.5cm정도
  • 목재 사이에 공간을 지지하고 나사를 조였을 때 힘을 받을 수 있도록 알미늄슬리브를 사용하면 좋음(1cm 4개만 판매하는곳이 없음). 그러나, 플라스틱(볼펜등)을 이용하여 잘라서 사용해도 전혀 이상없음
  • 마무리로 목재용 페인트칠 후, 수성용 오일로 마무리

 

(4) 완성품

 

 

 

 


 

 

■ 구글 스피커 실행

전원 연결후에 구글 스피커 실행

실행하기

 (env) # googlesamples-assistant-hotword --lang ko-KR --project_id my-dev-project --device_model_id 

source ~/env/bin/activate

(env) # googlesamples-assistant-hotword --lang ko-KR --project_id rpigoogleassistant-1abcd --device_model_id rpigoogleassistant-1abcd-speech-1aa32a 

 

그런데, 이상하게도 hotword로 하면 Segment Fault가 나오면서 동작을 안한다.(구글링을 해도 못찾음 ㅜㅜ)

결국 pushtalk만 실행해서 성공

 (env) # googlesamples-assistant-pushtotalk --lang ko-KR --project-id <projectid> --device-model-id <deviceid> --display

source ~/env/bin/activate

(env) # googlesamples-assistant-pushtotalk --lang ko-KR --project-id rpigoogleassistant-1abcd --device-model-id rpigoogleassistant-1abcd-speech-1aa32a  --display 

 

※팁1] pushtalk는 질문하고 Enter를 쳐줘야하기 때문에 질의 응답을 Enter키를 누르지 않고 할 수가 없다

그래서 pushtalk 프로그램 원소스를 약간 수정하여 Enter키를 하지 않아도 계속 질문과 응답을 할 수 있도록 약간의 꼼수를 사용함

 

[ 수정 ] grpc에 있는 pushtalk.py수정

# 457라인에 있는 아래의 click.pause(info='Press Enter to send a new request...')를 찾아서 리마크하고 다른 옵션을 넣습니다.

 # 저는 1초 대기 커멘트를 넣었습니다.

wait_for_user_trigger = not once

        while True:

            if wait_for_user_trigger:

                #click.pause(info='Press Enter to send a new request...')

                time.sleep(1)

            continue_conversation = assistant.assist()

            # wait for user trigger if there is no follow-up turn in

            # the conversation.

            wait_for_user_trigger = not continue_conversation

 

            # If we only want one conversation, break.

            if once and (not continue_conversation):

                break

 

※팁2] 구글어시스턴트가 동작을 하다가 데몬이 다운되는 경우가 발생하여 실행파일을 수정해서 부팅시 바로 구동하도록 설정하고, 크론잡에도 등록함

# vi ~/start_googleassistant.sh

 

 

 

# sudo crontab -u pi -l

 

 

 


                                                                                                                                                                The End

  • 안녕하십니까 라즈베리파이3으로 구글어시스턴트 이용하여 AI스피커 만들기 하는 중에 게시글로부터 많은 도움을 받았습니다. 다른 작업까지는 모두 완료하였는데, 제가 글쓴이님과 같은 USB마이크를 사용하고 있는 와중에, 마이크 인식은 되나 pushtotalk 명령어로 샘플코드 테스트를 할 때 계속 에러가 납니다. 마이크 관련해서 오류가 계속 나는 것 같은데 여러 방법을 다 써봐도 해결이 안되네요...혹시 당시에 시도해보셨던 다른 방법들도 있는지 궁금합니다.

  • 비나룽 2021.01.17 07:08 댓글주소 수정/삭제 댓글쓰기

    google-assistant-demo --project-id PROJECT_ID --device-model-id DEVICE_MODEL
    이걸로 실행해보세요. 핫워드로 호출이 가능하네요. 저도 이것저것 찾아보다가 겨우 찾았습니다.

  • gsm 2021.03.18 09:13 댓글주소 수정/삭제 댓글쓰기

    혹시 이거 성공적으로 다 실행까지 되신분 연락 부탁드립니다 ㅠㅠㅠ 저는 잘 안되네요...

    • 크게 2가지 난관이 있는데요,
      첫번째는 마이크,스피커 연결인데, 저도 엄청 고생하다가 Rpi도 몇번 OS새로 설치하고, 여러가지 마이크, 스피커를 했었는데, 잘 안되다가 이것저것 구글링 통해서 Rpi 패키지 업데이트해서 해결했었습니다.

      두번째는, 실제 hotword로하면 segment fault가 나오면서 동작이 안되, pushtalk을 실행해서 했고, 소스내에 enter를 쳐야만 다음 질문을 할 수 있도록 되어 있는걸 제거해서 대화형태로 변경한게 있었습니다.

      도움이 되었기를 바랍니다.

  • gsm 2021.03.18 09:27 댓글주소 수정/삭제 댓글쓰기

    저는 사실 고등학생인데요 해당 게시물을 보고 영감을 얻어서 만들어보고 있습니다 그런데 중간에

    3. 파이썬3 설치, 파이썬3 버추얼 환경설치 및 가상 환경변수 셋팅

    4. 최신의 pip, setuptool설치 및 버추얼 파이썬3 환경설정

    여기서 지금 Retrying (Retry(total=0, connect=None, read=None, redirect=None, status=None)) after connection broken by 'NewConnectionError('<urllib3.connection.VerifiedHTTPSConnection object at 0xb521b910>: Failed to establish a new connection: [Errno -3] Temporary failure in name resolution',)': /simple/google-assistant-library/

    이런식으로 에러가 나는데 어떻게 해결하죠 ㅠㅠ

    • 아마 잘은 모르겠는데 구글링을 더 해보면 도움이 될듯하구요

      일반적으로는 연결구성에서 뭔가 오류가 있는듯합니다.(마이크나, 스피커, 구글 어시스턴트와 api 통신등요)

      라이브러리가 제대로 설치가 안되서 발생할 수도 있습니다.

  • gsm 2021.03.18 11:32 댓글주소 수정/삭제 댓글쓰기

    Traceback (most recent call last):
    File "/home/pi/env/bin/google-oauthlib-tool", line 8, in <module>
    sys.exit(main())
    File "/home/pi/env/lib/python3.7/site-packages/click/core.py", line 722, in call
    return self.main(args, kwargs)
    File "/home/pi/env/lib/python3.7/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
    File "/home/pi/env/lib/python3.7/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, ctx.params)
    File "/home/pi/env/lib/python3.7/site-packages/click/core.py", line 535, in invoke
    return callback(args, kwargs)
    File "/home/pi/env/lib/python3.7/site-packages/google_auth_oauthlib/tool/main.py", line 102, in main
    client_secrets, scopes=scope
    File "/home/pi/env/lib/python3.7/site-packages/google_auth_oauthlib/flow.py", line 204, in from_client_secrets_file
    client_config = json.load(json_file)
    File "/usr/lib/python3.7/json/init.py", line 296, in load
    parse_constant=parse_constant, object_pairs_hook=object_pairs_hook, kw)
    File "/usr/lib/python3.7/json/init.py", line 348, in loads
    return _default_decoder.decode(s)
    File "/usr/lib/python3.7/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
    File "/usr/lib/python3.7/json/decoder.py", line 353, in raw_decode
    obj, end = self.scan_once(s, idx)
    json.decoder.JSONDecodeError: Invalid control character at: line 1 column 471 (char 470)
    이건 무슨 에러죠 ㅠㅠ

  • gsm 2021.03.25 12:24 댓글주소 수정/삭제 댓글쓰기

    마지막에 전원 연결하고 실행하기에서 저는 똑같이 했는데 bash : googlesamples-assistant-hotword: command not found 이런 에러가 나오네요 혹시 어떡하죠 ㅠㅠ?

    • 아마도 path설정이 안되서 그럴수 있는데, 명령어 전체를 Full로 적어보세요.
      ex. /usr/bin/???./googlesamples-assistant-hotword
      이렇게 googlesamples-assistant-hotword 명령어가 있는 위치를 전체 directory명까지해서 적어서 실행해보세요

  • 2001 2021.05.18 09:06 댓글주소 수정/삭제 댓글쓰기

    데모 버전을 전원을 줬을때 자동 실행 되도록 했습니다. 근데 가끔씩 오케이 구글로 호출하고 물어보면 답변을 하지않고 프로그램이 바로 종료 되는데 이건 무슨 에러인가요?

    • 종료될 때 나오는 에러메세지나 로그에 저장된 내용을 보구선 확인해보는게 좋을듯 합니다. 보통은 Crash Dump로 비정상종료되는 형태인데, OS type, 설정, 여러가지 사유로 발생될 수 있습니다.

  • 와ㅠㅠ감사합니다.