개발 프로젝트

WebRTC P2P vs SFU 버츄얼 개발 프로젝트 (Nest.js 2편)

maxwithjude 2025. 5. 2. 17:46

요구사항

유저는 AI 버튜버와 1대1 채팅을 할 수 있고 AI 버튜버의 목소리와 반응을 볼 수 있는 서비스입니다.

 

LLM& TTS 모델을 이용해 감정 별로 삽입해 놓은 이미지와 매칭시켜 감정에 따라 이미지가 출력되게는 성공했습니다. 그러나 팀원

들과 저는 이에 멈추지 않고 실제 영상으로 출력하는 서비스를 원했고, 더 도전하기로 했습니다.

 

춤추기 노래부르기 등 큰 액션보다 소소하게 대화할 수 있는 모델을 행동 범위를 정해놓고 개발하기로 했습니다. 말을 할 때 좌우로 고개를 흔든다거나 인사할 때 손 흔드는 정도만 정했습니다. 

 

 

잠시 후 시도해주세요 뜨는 것은 비용 때문에 TTS를 개발 단계에서 막아놨기 때문입니다

 

버츄얼 모델 렌더링을 어디서 하는게 최선인가?

 

크게 UNITY & WebRTC 로 서버에서 렌더링 하는 방식과 클라이언트 사이드에서 렌더링 하는 방식이 있습니다. 그러나 유저가 늘어날 경우 서버 사이드 렌더링 방식은 점점 부하가 생길 수 밖에 없는 구조가 될 것 입니다. 

 

  • 1대1 대화방 구조
  • 서버가 모든 참가자의 렌더링을 수행하면
    • 사용자가 많아질수록 렌더링해야 할 수가 늘어남 → 서버 과부하
  • 예: 유저가 5명 접속 → 서버는 5개의 렌더링 필요

그래서 저는 Three.js를 이용한 클라이언트 렌더링 방식으로 녹화를 하고 한 액션(유저의 채팅에 대한 AI 버튜버의 음성, 리액션)을 트는 방식이 확장성이 좋다고 판단했습니다. 

 

현재 프론트는 React+Next.js 를 사용하고 있고 이에 맞는 라이브러리를 설치합니다.

yarn add ~ 로 추가하기

@pixiv/three-vrm": "^3.4.0",
    "@react-three/drei": "^10.0.7",
    "@react-three/fiber": "^9.1.2",

 

일단 VRM을 1.0 으로 export 했는지 0.0으로 export 했는지부터 알아야 합니다.

각 버전 별로 감정 변화 컨트롤 객체가 다르기 때문입니다.

 

 

속성 이름                                                    VRM 0.x                                    VRM 1.0 (@pixiv/three-vrm v3.x)

표정 설정 vrm.expression vrm.expressionManager
표정 이름 대소문자 보통 대문자 시작 소문자 사용 (happy, angry)
Plugin 등록 필요 여부 필요 필요 (loader.register(...))

 

 

WebRTC P2P vs SFU 

https://millo-l.github.io/WebRTC-%EA%B5%AC%ED%98%84-%EB%B0%A9%EC%8B%9D-Mesh-SFU-MCU/

 

WebRTC 구현 방식(Mesh/P2P, SFU, MCU) | millo's tech blog

WebRTC를 구현하기 위한 서버의 종류에 대해 알아보자. (Mesh/P2P, SFU, MCU)

millo-l.github.io

 

WebRTC도 P2P 방식만 있는게 아니었는데 각 방식마다의 장단점도 있습니다. 

 

만약 제가 개발하는 서비스가 (일반적인 스트리밍 플랫폼 ex. soop, 트위치 등)1:N 방식이였고 들어갈 수 있는 M개의 AI 버츄얼 모델이 있다고 한다면 M개의 버츄얼 모델 렌더링 인스턴스가 있으면 됩니다. 목표하는 모델은 1(최대 한 자릿수)개 이기때문에 1개의 서버에 N명의 유저에게 렌더링을 뿌려주면 되기 때문에 WebRTC 방식이 적합했을 것 같습니다.

 

 

그러나, 1대1 방식이기 때문에 결국 방 한 개당 렌더링 서버가 하나씩 존재해야해 선형적으로 증가하기 때문에 서버의 부담이 큽니다.

 

Youtube Live, 트위치는 어떤 방식을 쓸까?

갑자기 실제 서비스들은 어떤 방식으로 이루어지는지 궁금해졌습니다. 이들은 단방향 스트리밍이기 때문에 HLS나 DASH 같은 HTTP 기반 스트리밍 프로토콜을 사용한다고 합니다. 

지연시간이 다소 높아도 대규모 전송과 안정성이 중요하기 때문입니다.

 

ZOOM, DISCORD 등은 WEBRTC의 SFU 방식을 이용한다고 합니다. 

 

기본적으로 HLS는 TCP 방식, WEBRTC는 UDP 방식을 이용해 빠르다고 합니다.

 

1대 N의 경우를 가정한 WebRTC(SFU방식)시스템 흐름도

 

클라이언트 사이드 렌더링을 위한 여정

VROID Studio에서 vrm으로 export할 경우 표정은 가져오지만 애니메이션(포즈 등)은 가져오지 않습니다. 그래서 mixamo를 이용해 모델을 업로드하고 행동을 입혀야합니다.

 

이 때, .vrm 파일을 .fbx로 변환할 필요가 있고 간편하게 할 수 있는 방법은 unity의 vrm importer, fbx exporter를 이용하는 것입니다. 

 

필요한것 Vroid Studio, Unity 

Unity에서 vrm을 렌더링 하려면 UniVRM 패키지가 필요합니다. 이를 위한 github 주소입니다. https://github.com/vrm-c/UniVRM/releases

 

Releases · vrm-c/UniVRM

UniVRM is a gltf-based VRM format implementation for Unity. English is here https://vrm.dev/en/ . 日本語 はこちら https://vrm.dev/ - vrm-c/UniVRM

github.com

 

Unity 3d 프로젝트 생성이 안되는 문제 : 그래픽카드 설정

 

Unity 3d 프로젝트를 생성하는데 생성하자마자 자꾸 꺼지는 문제가 발생했습니다. 노트북 기본 gpu 설정 때문인 것 같습니다.

 

노트북의 경우 외장그래픽카드와 내장그래픽 카드 설정을 하셔야합니다. 내장만 있는 경우.. 안타깝지만 최신 내장 그래픽인 Iris xe, 요즘 달려 나오는 그래픽인 Arc Graphic 정도 아니면 힘들 것 같습니다.

window 기준 화면 오른쪽 아래 위를 바라보는 화살표를 클릭하면 nvidia 설정 창이 있습니다.

 

PhysX 프로세서가 기본 내장그래픽 (intel의 경우 UHD GRAPHIC 등..)인데 성능이 낮기 때문에 Unity 3D 프로젝트를 만들면 바로 터지더라구요?

외장그래픽을 쓰도록 바꿔주었습니다.

 

+ Nvidia 그래픽 드라이버 최신버전 다운받기 

https://www.nvidia.com/ko-kr/geforce/drivers/results/244154/

 

Geforce Driver Results | NVIDIA

<dd~OSName> 시스템을 위한 <dd~LanguageName> <dd~Name> 다운받기. <dd~ReleaseDateTime> 출시

www.nvidia.com

 

 

둘 다 하니 프로젝트가 잘 생성되었습니다.

 

Github 링크에 접속 후 vrm 버전에 맞는 패키지 설치하는 방식은 충돌나서 

이대로 하시면 됩니다. unity 설치한 경로로 가서 packages/manifest.json을 열고 위 3가지를 의존성에 추가해주시면 됩니다.

 

그 후 fbx 확장자로 export를 하기 위한 플로그인을 설치하겠습니다.

unity 상단 바 window - package management- package manager - 왼쪽에 in project말고 unity registry로 변경 후 

fbx exporter 검색 후 설치

 

참고로, vrm importer를 설치완료하면 상단 바에 vrm0 과 vrm1이 떠야합니다.

 

Vroid Studio vrm 다운 -> unity vrm import, fbx로 전환 후 export -> mixamo 에서 행동 애니메이션 입히기 -> three.js로 렌더링

 

그런데 지금 모델이 턱 쪽이 너무 어둡습니다.  천장 쪽에 기존 조명이 있는 것 같습니다.

실제 방송하는 분들처럼 얼굴을 비추는 조명을 추가해보았습니다.