1. Viseme
이전에 텍스트를 목소리로 변환해 보았다. 이제 립싱크를 위해서는 그 목소리에서 특정 값을 추출해야한다. 우리가 추출할 값을 보통 Viseme 값이라고 한다.
위키백과(https://en.wikipedia.org/wiki/Viseme)
- MS 음성 서비스에서 제공하는 REST API 경우 Viseme 값을 추출하는 기능이 지원되지 않는다.
- 언리얼에서 사용할 AzureTTS 플러그인은 REST API를 이용하기 때문에 또 다른 플러그인이 필요하다.
2. OVRLipSync
2.1. OVRLipSync - USoundBase to Visemes
처음에 플러그인을 모두 준비했겠지만, 만약 안 되어 있다면 마저 다운받고 실행해주자. 그리고 OVRLipSync 플러그인의 테스트에 사용할 대사파일을 하나 준비하자. ( LOL: https://goodcow.tistory.com/58 )
언리얼 엔진4에는 기본적으로 오큘러스 플러그인이 설치치어 있어, 마켓플레이스에 들르지 않아도 관련 플러그인들을 사용할 수 있다. 다만, OvrLipSync 플러그인은 직접 사이트에서 다운로드 받아야한다. ( https://developer.oculus.com/downloads/package/oculus-lipsync-unreal/ )
- Viseme 값을 불러오기 위해서는 OVLipSyncPlaybackActor 컴포넌트와 OVRLipSyncFrameSequence 클래스가 필요하다.
- OVRLipSync 컴포넌트는 자신과 연결 된 시퀀스를 통해 지속적으로 Viseme 값들을 추출한다.
Start 노드에 오디오 액터와 시퀀스를 입력하면 컴포넌트와 시퀀스가 연결 되고, 오디오 재생 시 OnVisemes Ready 이벤트가 지속적으로 호출 된다.
- 이제 Visime 값을 어디에 사용할까? 립싱크 대상으로 사용할 StaticMesh 컴포넌트도 OVRLipSyncPlaybackActor 컴포넌트와 연결하자.
- Assign Visemes to Morph Targets 노드가 이 연결을 담당한다.
블루프린트에서는 등록만해도 괜찮지만, C++에서는 바인딩 후 BeginPlay 쯤에서 바인딩한 함수를 1회 실행할 필요가 있다.
2.2. OVRLipSync - Animation with Viseme
Viseme 값을 어디에(Static Mesh Morphing) 사용할지는 알았다. 이제 어떻게 사용할까?
립싱크할 얼굴의 애니메이션 블루프린트를 열고 Viseme 값을 가져오자.
- 그리고 메타휴먼의 ABP를 복사해서 사용한다면 다음과 같은 노드를 발견할 수 있을텐데, 없으면 하나 생성해고, 커브 변경 노드의 인풋에 캐시를 연결해주자.
- 이렇게 기본 캐시데이터가 필요한 이유는 이후 생성될 '커브수정' 노드의 기본 포즈 때문이다. 만약 아무 인풋 없이 커브를 수정한다면,
- 목이 분리되어버린다.
- OVRLipSync 플러그인에서 제공하는 Viseme 데이터는 영문음 기준으로 15개의 실수(float) 배열이다.
sil(묵음), PP, FF, TH, DD, kk, CH, SS, nn, RR, aa, E, ih, oh, ou
설명문 링크: https://developer.oculus.com/documentation/unreal/audio-ovrlipsync-viseme-reference
- 사용할 Viseme 값에서 불러온 값이 커브값에 그대로 쓰이면 모자라거나 과할 수 있으니 중간중간 변수를 추가해준다. 다음은 사례의 일부이다.
- 자연스러운 입 모양을 찾아서 적당한 변수값을 붙여주는 일이 매우 지난한 일일 수 있다. 아무래도 영어 위주의 Viseme 값이기에 한국어로는 더 어려웠다. 다음 링크는 도움이 되었던 튜토리얼이다. (https://www.youtube.com/watch?v=18ZzMLvqpS4&ab_channel=FracturedFantasy)
- 여기까지 작업을 마쳤다면 오디오 컴포넌트를 사용해서 목소리를 들어보자.
- 이제 플레이 버튼을 누르면 캐릭터가 대사를 치는 모습을 볼 수 있다.
- 지금은 파일을 통해 립싱크를 했지만, 다음에는 입력한 텍스트를 사용해 대사를 읊어보자. 그냥 'Runtime audio importer 사용하면 되겠네.' 싶을 수 있다. 하하하, 당연히 그렇게는 안 될 것이다.
'GameDevelopmentDiary > UnrealDiary' 카테고리의 다른 글
Mobile AOS XR Study - Virtual camera in mobile (0) | 2022.06.07 |
---|---|
언리얼4 립싱크(Text To Speech) 구현 방법 Part4 (완성) (1) | 2022.03.10 |
언리얼4 립싱크(Text To Speech) 구현 방법 Part2 (5) | 2022.03.07 |
언리얼4 립싱크(Text To Speech) 구현 방법 Part1 (0) | 2022.03.07 |
립싱크 - (메타휴먼, 리얼루전) (0) | 2021.12.28 |