"텍스트가 들어가면 소리가 나와. 그것도 바로 느껴질 만큼 빠르게."
붙여넣기 칸과 방
문장 하나 복사해서 칸에 넣고, 목소리 고르고, Speak 눌러. 잠깐이면 그 문장이 방 안에 울려. 진짜 스피커에서 나온 진짜 소리로. 화면 속 글자에서 방 안 목소리까지, 그 짧은 거리가 제품의 전부야. Bellows의 나머지는 다 그 거리를 짧게, 싸게, 몇 번이든 되풀이할 수 있게 만들려고 있어.
왜 함수가 아니라 엔진이냐면
순진하게 짜면 세 줄이야. 텍스트 받고, provider 부르고, 바이트 재생. 딱 한 번은 잘 돌아가. 근데 같은 문장에 두 번 결제하기 싫어지는 순간이 와. provider가 요청 중간에 먹통 되면 어쩌지 싶고. 두 계정 중 어디에 맞는 목소리가 있는지 따지게 되고. 사적인 오디오가 엉뚱한 스피커로 새면 큰일이다 싶어지고. 그때부턴 함수가 아니야. 엔진을 돌리는 거야. credential이랑 캐시, receipt, 직접 쥔 오디오 디바이스, lifecycle까지 한데 묶인 운영 영역.
그게 별도 repo인 이유 전부야. provider 계정, 유료요청 복구, 오디오 디바이스 소유, 프로덕션 lineage는 한 몸으로 묶여야 해. 그리고 뭘 말할지 정하는 brain에서는 떨어져 있어야 하고. 말하는 방법은 Bellows가 쥐고, 말하는 게 누구인지는 cwkPippa가 지켜.
요청은 이렇게 생겼어
소비자는 Bellows한테 텍스트랑 logical profile을 건네. pippa나 cwk 같은 안정된 이름이지, 날 provider voice ID가 아니야. 그러면 Bellows가 그 profile을 활성 계정의 맞는 binding으로 풀고, 합성 identity를 통째로 계산하고, 캐시에 있으면 공짜로 돌려주고 없으면 유료요청을 딱 하나 날려. 소비자는 voice ID를 알 필요도, 캐시 경로를 짐작할 필요도, provider를 직접 건드릴 필요도 없어.