본문으로 건너뛰기
단어별 요청으로 바꾼 서버 기반 TTS
목차

단어별 요청으로 바꾼 서버 기반 TTS (2022-11)

원문 정보

앱에 내장된 TTS의 한계

기존 티맵은 TTS 변환 엔진(NUGU, GOOGLE TTS 엔진), 음성 DB, 내부 예외처리 사전을 앱에 두고 필요한 음성을 앱 안에서 합성했습니다. 예외처리 사전은 특정 문자열을 정해진 읽기로 바꾸게 하는 문서입니다. 원문의 예로 “8.15 광장"을 “팔.십오광장"이 아니라 “팔.일오광장"으로 읽게 합니다.

이 구조에는 네 가지 문제가 있었습니다. 정적으로 링크한 엔진 라이브러리 때문에 앱 용량이 커졌습니다. 목소리를 늘리려면 음성 파일이 많이 필요해서 여러 사람의 목소리를 지원하기 어려웠습니다. 사전과 기본 음성을 처음에 내려받지 않으면 음성안내가 되지 않았습니다. 그리고 TTS로 바꾸는 부분이 POI 명칭뿐이어서 기본 음성과 이어 붙이면 매끄럽지 않았고, POI 외의 문장 음성은 앱 버전을 올려야만 추가할 수 있었습니다.

서버 기반 TTS는 이 일을 서버에 맡기는 방식입니다. 클라이언트가 길안내에 필요한 음성을 텍스트로 요청하면, 서버가 텍스트를 받아 저장된 사람 음성 DB로 합성해 돌려줍니다.

트래픽 추정과 두 가지 안

요구사항은 끊김 없이 안정적인 안내, 그리고 멘트를 주기적으로 바꿀 수 있는 운영 가능성이었습니다. 문장이 매끄럽게 이어지게 하려면 네트워크 사용량이 커질 수 있어서, 먼저 앱에 음성 분석용 로그를 넣어 발성 종류와 평균 길이를 뽑았습니다. 평균 재생 시간은 3.7초였고 사용자당 이벤트는 232건이었습니다. 최근 30분 동안 발성은 2,991,067회였습니다. 초당 10kb로 계산하면 30분간 네트워크 사용량이 90 TB라는 것이 원문의 추정입니다. 같은 음성이 반복 발성되는 적중률 높은 음성이 따로 있다는 점도 확인했습니다.

여기서 두 안이 나왔습니다.

  • 문장 전체를 TTS로 요청하는 안은 발성이 자연스럽고 인터페이스가 간결하지만, 네트워크 사용량이 크고 길이 때문에 응답을 믿기 어렵습니다.
  • 기존처럼 기본 음성과 POI 명칭을 단어별로 요청하는 안은 음성별 캐싱으로 사용량을 줄이고 응답 지연에도 대응할 수 있지만, 앞 안의 장점이 사라집니다.

단어별 요청에 문장 정보를 얹은 구성

팀은 두 안을 섞었습니다. 요청은 단어별로 하되 요청 헤더에 전체 문장 정보를 실어 보냅니다. 캐시 적중률이 높아 네트워크 사용량이 줄고 개발 공수도 적으며 문장 발성도 자연스러워집니다. 서버는 헤더의 문장 정보를 보고 단어별 음성의 강약을 조정한 단어 조합 리스트를 단말에 내려줍니다.

끊김을 막는 예외 처리도 넣었습니다. 요청한 단어의 응답이 오지 않았을 때, 그 단어가 문맥상 꼭 필요하지 않으면 빼고 이미 캐시에 있는 음성 파일끼리 조합해 안내합니다. 트래픽이 몰릴 문구는 미리 캐싱해 서버 부하를 막았고, 원문은 피크 시간의 시보 알림을 예외 사례로 듭니다.

서버 이전으로 얻은 효과

앱 용량은 TTS 라이브러리를 서버로 옮겨 줄였습니다. 필수 기본 음성 파일이 앱 초기화에 필요 없어져서 초기 로딩의 내려받기 시간과 데이터 사용량도 사라졌습니다. POI 음성이 어색하면 서버에서 바로 고칠 수 있고 단말 작업이 없어 유지보수가 단순해졌습니다. 가장 큰 장점으로 꼽은 것은 단어별 요청이라서 성우나 셀럽 목소리를 추가해도 단말을 고치지 않는다는 점입니다. 서버의 매핑 테이블로 특정 셀럽의 멘트를 치환할 수도 있어, 현재 티맵에서 여러 성우와 셀럽 목소리가 서비스됩니다.

트래픽 추정에 쓴 수치
항목값
평균 재생 시간3.7초
사용자당 이벤트232건
최근 30분(4/28 8:15~8:45) 발성 횟수2,991,067회
추정 기준초당 10kb
원문의 계산식3초 × 300만 × 10kb, 결과를 90 TB로 표기
마지막 수정 일자