Joonas' Note
실시간 음성 감지 및 자동 번역 크롬 확장 프로그램 개발기 (1편) 본문
이름이 왜 이렇게 기냐구요? 로빈슨 크루소의 원제를 오마주한 겁니다.
이 글은 회고록을 적는 느낌으로 작성했습니다.
1분 소개 영상
소개
크롬에서 현재 보고 있는 탭의 소리(음성)를 인식하여 원하는 언어로 번역해주는 확장 프로그램, 짧게 부르면 통역 프로그램이다. 실은 통역이라는 단어가 생각이 안 났다.
종종 개발하다가 유튜브의 인도 개발자 영상으로 들어간다든지, MIT 수업 영상을 본다든지 모국어가 아닌 영상을 봐야 하는 경우를 이따금 접했다. 그러던 중, 할리우드 배우의 인터뷰를 보기 위해 영화 정보 사이트 IMDb에 들어간 것이 계기였다. 한국으로 치면 연예가 중계 같은 방송이었던 것 같은데, 말이 워낙 빨라서 도저히 들을 수가 없었다. 이 곳은 유튜브가 아니라 자체 비디오 플레이어를 사용하는 데, 자막은 지원하지 않는다. 나는 자막이 필요했다.
그렇게 2018년 7월 즈음 이 프로젝트를 시작하게 되었다.
시장 조사
모바일 앱에서는 이미 엄청 많았다. 하지만 브라우저의 영역에서는 달랐다. 정확히는 PC의 영역이라고 해야 할 것 같다. PC에서 출력되는 소리(스테레오 믹스 등)를 번역하는 프로그램은 찾기 힘들었다.
늘 그렇듯 사람들은 방법을 찾았다. 스마트폰에서 번역 어플을 실행하여 스피커 앞에 대고 번역된 문장을 보고 있었다. 그리고 (문서를 작성해야 한다면) 다시 옮겨 적고...
하지만 나는 굉장히 수고롭다고 생각했고 이는 좋은 솔루션이 되지 못한다고 생각했다.
특히 크롬 웹 스토어에 같은 프로그램이 없는 것을 확인하고 개발하기로 마음 먹었다.
동시에 당연한 것 같은 이 프로그램이 왜 없는가에 대한 의문도 생겼다. (지금은 아마 재정문제가 아닐까 추측해본다.)
여담으로, 이런 아이디어가 Hyperconnect사의 영상 채팅 앱 Azar에서 사용되고 있었다. (링크) 후술 하겠지만 모바일 SDK를 사용했을 것 같고, 그렇다면 조금 다르다. 하지만 이 사실을 알게 된 것은 나중 일이었다.
개발 시작
현재 내가 보고 있는 동영상에 자막을 띄우는 프로그램으로 계획했으나, 어차피 소리가 소스이고 STT(Speech-to-Text)인데 영상으로 국한할 필요가 없겠다고 생각했다.
이런 일은 보통 컴퓨터로 동영상을 보다가 일어나는 일이었으므로 구글 크롬 확장 프로그램을 떠올렸다. 마침 크롬 API 중에 tabCapture가 있었고 영상과 음성 스트림을 모두 전송할 수 있었다.
필요한 기술을 정리하기 위해 프로세스를 다음처럼 정리했다.
Audio capturing → Speech-to-Text → Translate → Display
문제는 로컬에서 STT를 하긴 힘들어 보였고, 번역은 특히 그랬다. 그래서 서버를 따로 구축하고 서버와 요청/응답하는 형식으로 개발하기로 했다.
우선 구글 번역을 떠올리며 구글 클라우드 플랫폼(GCP)를 중심으로 필요한 API들을 리서치 했다. 클라우드 업체는 AWS, Azure, Naver, Google 이렇게 4곳에서 찾아봤고, AWS, Naver, Google에는 크레딧이 좀 있어서 Azure는 신경을 덜 썼다.
소리에서 글자를, Speech-To-Text
STT는 Amazon Transcribe, Azure Speech, Clova Speech Recognition, Google Cloud STT 이렇게 있었다. 실시간 번역의 느낌을 위해 음성 스트림을 전송하고 그 결과를 받는 API를 원했지만 스트림은 Device SDK 밖에 없어 보였다. GCP에 StreamingRecognize이 있었지만 gRPC를 통해서만 가능했다. (조대협 님의 gRPC 소개 글) (당시는 2018년 7월)
개발 가능성을 보기 위한 프로토타입을 원해서 프로젝트가 무거워지는 기분이라 gRPC의 사용은 피했다.
문제는 스트림이 아니라면 적당한 길이로 녹음하여 STT API로 전송해야 하는데, 사용자가 소리가 나오는 시점을 알고 녹음하는 것이 아니기 때문에 다른 방법이 필요해 보였다. Oxford Guide to Plain English에서 한 문장의 평균 길이는 15~20단어라는 것과, 말하거나 듣는 상황에서 WPM(Words per minute)가 평균 145~160이라는 점을 참고해서 한 문장은 6초 정도라고 판단했다. 청크를 10초 단위로 설정하면 큰 번역 오류는 없을 것이라 생각하여 10초로 설정했다.
(다음 업데이트에서는 10초마다 녹음이 아니라, 소리가 감지된 시점부터 녹음을 진행하도록 변경할 예정이다.)
결국 돌고 돌아 GCP에서 Google Cloud Storage에 오디오 파일을 저장 후 STT 결과를 받아오도록 구현했다. 구글은 API 문서가 예제와 함께 매우 잘 정리되어 있었다.
구글 제품의 사용 후기로는, 약 100개국의 자동 언어 감지가 인상적이었다. 실생활에서 듣는 말은 어떤 언어일지 모를 확률이 높다. 이런 점에서 아주 유용한 기능이라 생각한다.
그리고 네이버 클로바는 60초까지만 인식 가능한 반면, 구글은 비동기 인식의 경우 최대 180분까지 가능했다.
번역
파파고(클로바)는 한국어의 경우에 꽤 그럴싸한 번역 결과를 보였다. 전체 문장에 대해서는 잘 되었지만 토막 난 문장은 어색함을 넘어 이상한 의역이 생기곤 했다. 클로바는 최초 60분 무료에 15초당 4원로 같은 시간에 6원인 구글에 비해 1.5배 저렴하다.
구글의 경우에는 우선 언어 스펙트럼이 넓은 것이 진짜 사기적이다. 그리고 문맥이 잘린 문장들에 있어서도 납득할만한 번역 결과를 보여주었다. SMT(Phrase-Based Model)에서 더 강하다고 느껴졌다.
오디오 데이터에서 인식된 문장이 어떤 문맥을 가지냐에 따라 결과가 많이 다를거라 생각한다. 특히 NMT와 SMT를 어떻게 사용하느냐도 중요할 것이다.
이미 STT API로 구글을 사용하고 있어서, 사용 권한이나 API KEY 등의 추가적인 일은 없었다.
아키텍처
중간에 점선으로 묶인 부분은 Docker를 사용하여 각 서비스를 컨테이너로 실행하여 관리와 배포도 쉽게 하고, 싱글 스레드인 node.js를 여러개 띄워 멀티 스레드의 효과도 기대하였다.
Why node.js?
이 프로젝트에서 가장 중요한 요소는 응답성이었다. 클라이언트로부터 요청이 계속 올 것이고, 음성 스트림을 .wav 포맷으로 변환하는 과정에서 I/O 처리가 발생하는데 이 부분에 병목이 걸릴 것을 우려하였다. node.js는 싱글 스레드 기반에 이벤트 루프 기반으로 동작한다. 비동기 I/O가 가능했고 많은 요청을 동시에 처리하는 이 프로젝트에 적합하다고 생각했다.
실제로 STT(Speech-to-Text)나 번역은 클라이언트 라이브러리를 통해 Google Cloud Platform에 요청하고 기다리는 것이 전부였으므로 실제 CPU 연산량은 그렇게 많지 않았다.
대회 참가
2018년 10월에 웨일 확장앱 콘테스트가 있었다. 마침 바로 실행 가능한 프로토타입이 8월에 완성되어서 PPT를 만들고 제출하였지만 서류에서 탈락했다. 심사 기준에 부합하도록 내용을 나름 적었지만 설득되지 못한 모양이다.
조금 지나 11월에 교내에서 작품경진대회가 열렸고, 개인 프로젝트로 마치기에는 아쉽고 다른 대회에도 제출할 기회는 없어보여 참가했는데 금상을 수상했다.
스토어 등록
이 프로젝트는 구글 크롬 확장 프로그램의 형태로 개발했다.
크롬 웹 스토어에 확장 프로그램을 등록하기 위해서는 개발자 등록이 필요했고, 이게 $5가 필요하다. 언젠가 또 추가하겠지 하는 마음에 쿨하게 결제하고 검수 거쳐서 등록됐다.
그리고 내가 가장 많이 쓰는 브라우저가 크롬이기 때문에 선택한 것인데, 이 확장 프로그램이 호환되는 크롬 기반의 브라우저가 생각보다 많았다. (네이버 웨일, Mozilla Firefox 등)
그렇다보니 네이버 웨일 스토어에도 등록이 가능했다! (웨일 스토어는 등록이 공짜! 와!!)
그리고 네이버 웨일만의 기능들이 좋아보였다. 특히 사이드바가 무척 탐이 난다. 향후 업데이트에서 꼭 적용하고 싶다.
구글 크롬 웹 스토어: https://chrome.google.com/webstore/detail/speech-translator/gcfkkagkjfgioopdgonmpjmoehfkbeng
네이버 웨일 스토어: https://store.whale.naver.com/detail/lmghiccipodepbjkeblgfmdffoipiegd
다음 이야기는 2편에서 이어진다.
2편은 실제로 배포하면서 있었던 일을 다룰 예정이다.
'개발' 카테고리의 다른 글
(3 in 5)^2 퍼즐 / Rubik's Race / 루빅스 레이스 (0) | 2019.11.01 |
---|---|
실시간 음성 감지 및 자동 번역 크롬 확장 프로그램 개발기 (2편) (14) | 2019.04.10 |
[Vue.js] Module not found: Error: Can't resolve... (1) | 2018.11.22 |
대용량 더미 파일 생성 (fallocate) (0) | 2018.11.03 |
socket.io 연결 실패 해결하기 (7) | 2018.07.23 |