발음이 어색하다는 것은 알겠는데, 다음에는 입을 어떻게 움직여야 할까요? 제가 만들고 싶었던 것은 학습자가 다음 시도에 바로 써볼 수 있는 조언이었습니다. 어느 소리가 어색했는지에서 더 나아가, 혀를 어디로 움직이고 입술을 어떻게 바꾸면 좋을지까지 설명하고 싶었습니다. Xhadow는 이 목표에서 출발해 음성 복제, 음향 분석, 비교 재생과 코칭을 연결한 발음 연습 서비스입니다. 기획·개발·디자인을 단독으로 수행했습니다.
내 목소리로 비교 기준을 만들다
점수와 전사 결과는 연습을 돌아보는 데 유용하지만, 입을 어떻게 움직일지 정하려면 다른 정보가 필요합니다. 목표 단어와 다르게 들린 소리가 무엇인지, 어느 부분을 길게 끌었는지, 모음을 발음하는 동안 소리가 어떻게 변했는지를 함께 살펴야 합니다. 또 다른 화자의 녹음과 비교하면 발음뿐 아니라 음색과 음역, 말하기 속도의 차이도 섞입니다. 저는 학습자가 자신의 음색으로 된 목표 발화를 듣고 따라 해볼 수 있도록 비교 기준부터 만들었습니다.
사용자가 녹음한 음성을 Cartesia로 복제하고 목표 언어에 맞게 현지화한 뒤, 연습 문장을 합성합니다. 그 결과를 실제 녹음과 나란히 재생하고 분석할 수 있게 했습니다. 익숙한 자기 목소리를 기준으로 두면 화자 차이의 일부를 줄이고 조음과 타이밍에 집중할 수 있으리라는 제품 가설입니다. 음성 복제가 실제 성도 구조를 그대로 보존한다거나, 화자 차이를 모두 없앤다고 전제하지는 않았습니다.
점수를 움직임에 대한 조언으로 연결하기
녹음에서 코칭에 필요한 단서를 모으기 위해 서로 다른 분석 결과를 결합했습니다. Azure 발음 평가에서는 단어와 음소의 위치, 점수, 기대한 소리 대신 인식된 음소 후보를 가져옵니다. 브라우저에서는 소리를 짧은 구간으로 나눠 주파수 성분을 계산하는 FFT와 피치·포먼트 추정 코드를 직접 작성했습니다. 포먼트는 소리의 공명 특성을 나타내며, 모음이 변하는 과정을 살펴보는 단서로 사용했습니다.
여기서 값이 나온다는 이유만으로 모두 같은 수준의 근거로 취급하면 안 됐습니다. 무음이나 마찰음에서도 스펙트럼의 봉우리는 찾아질 수 있기 때문입니다. 소리의 에너지와 파형의 부호 변화, 피치 추정 결과를 함께 사용해 유성 구간의 신뢰도를 계산하고, 이를 음소 경계 보정과 분석 입력에 반영했습니다. 코칭 모델에는 점수 하나가 아니라 인식된 대치음, 길이 차이, 목표와 실제 발화의 포먼트 궤적을 전달하도록 구성했습니다.
LLM에는 이 입력을 학습자의 언어로 풀어 쓰는 역할을 맡겼습니다. 내부에서는 음향 수치를 비교하되 사용자에게는 혀·턱·입술의 움직임을 제안하도록 프롬프트를 설계했습니다. 이렇게 측정·추정 단계와 설명 생성 단계를 나누면 조언이 어떤 입력에서 출발했는지 대조할 수 있습니다. 다만 마이크가 입 안의 움직임을 직접 측정하는 것은 아닙니다. 화면의 조음 가이드와 설명은 음향 단서에서 추론한 코칭이며, 신체 위치를 정확히 복원한 결과로 제시하지 않습니다.
같은 단어의 같은 순간을 비교하기
음향 특징을 추출하고 나자 시간축이 다음 문제가 됐습니다. 같은 문장을 읽어도 어떤 단어는 빨라지고 어떤 모음은 길어집니다. 녹음 전체의 재생 속도만 맞추면 서로 다른 소리를 같은 시점에 비교할 수 있습니다. 개발 초기에는 두 발화 전체를 정렬하는 DTW를 연결했습니다. 이 방식은 소리의 유사성을 따라 대응 지점을 찾지만, 문장이 길어질수록 계산량이 커지고 단어 경계와 무관한 대응이 생길 수 있습니다.
다음 구현에서는 이미 확보한 단어 위치를 정렬의 기준점으로 사용했습니다. 합성 음성의 단어 타임스탬프와 발음 평가의 단어 오프셋을 연결하고, 각 단어 안에서만 세밀한 시간 차이를 맞추도록 바꿨습니다. 긴 구간은 양쪽을 같은 비율로 줄여 계산한 뒤 원래 시간축으로 되돌립니다. 하나의 큰 비교를 단어별 문제로 나누면서, 화면의 단어 선택과 음소별 길이 분석도 같은 시간 대응표를 사용할 수 있게 됐습니다.
정렬된 위치를 재생하는 과정에도 별도의 작업이 필요했습니다. 초기 구현은 대응하는 소리 조각을 잘라 겹쳐 붙였지만, 조각의 연결 방식까지 고려해야 비교 재생을 자연스럽게 만들 수 있었습니다. 이후에는 앞 조각과 파형이 비슷하게 이어지는 지점을 찾아 겹치는 WSOLA로 재생 코드를 다시 작성했습니다. 목표 발화의 시간 흐름에 맞춰 사용자의 녹음을 늘이거나 줄이면서 피치를 보존하려는 구현입니다. 분석 그래프의 정렬을 실제로 들어볼 수 있는 기능까지 연결한 단계였습니다.
분석을 다음 연습으로 이어가기
인터페이스에서는 전체 문장을 한꺼번에 설명하기보다 단어와 음소를 선택해 해당 구간을 듣고, 목표 발화와 자신의 녹음을 비교하도록 했습니다. 선택한 소리의 점수와 대치 후보, 길이 차이, 코칭을 같은 흐름에서 볼 수 있습니다. 포먼트 시계열도 정렬된 위치에 맞춰 전달하도록 보간 방식을 손봤습니다. 그래프를 많이 보여주는 것보다, 학습자가 지금 듣는 부분과 조언이 가리키는 부분을 연결하는 데 초점을 두었습니다.
연습이 한 번의 분석으로 끝나지 않도록 음소별 이력도 쌓았습니다. 반복해서 등장한 음소의 평가를 모아 취약한 소리를 찾고, 이를 포함한 개인별 연습 코스를 생성합니다. 생성과 분석처럼 시간이 걸리는 작업은 상태를 저장해 페이지를 떠났다가 돌아와도 결과를 확인할 수 있게 했습니다. 목표 발화 듣기, 녹음, 구간 비교, 조언 확인, 다음 연습까지 이어지는 사용 흐름을 구현했습니다.
구현한 것과 더 검증할 것
완성한 것은 음향 분석과 생성형 코칭을 함께 살펴볼 수 있는 연구용 제품입니다. 저장소에는 합성 신호로 포먼트 추정과 유성성 구분, 시간 정렬과 음소 경계 보정을 확인하는 실험 스크립트가 있습니다. 이 실험은 계산 과정의 동작을 살피기 위한 것이며, 실제 학습자의 발음 향상이나 코칭 정확도를 입증하는 사용자 연구는 아닙니다.
현재 포먼트는 스펙트럼의 봉우리를 이용한 근사 추정이고, 단어 대응도 텍스트 일치에 의존하므로 높은 음역이나 반복 단어, 누락 발화에서는 추가 검증이 필요합니다. 다음 단계에서는 음향 추정의 안정성과 전문가가 판단한 조음 문제를 비교하고, 제안한 움직임이 실제 학습에 도움이 되는지 평가해야 합니다. Xhadow에서 얻은 결과는 발음 교정 효과의 증명에 앞서, 어떤 소리 차이가 어떤 코칭으로 이어졌는지 추적하며 개선할 수 있는 구현 기반입니다.