π€ Live Streaming AI VTuber: μ€μκ° AI λν + TTS μμ± ν©μ± + VTubeStudio μ°λ
Ollama κΈ°λ° AIμ GPT-SoVITS TTS,RealtimeSTTλ₯Ό νμ©ν μ€νΈλ¦¬λ° λ° VTubeStudio μ°λ μμ± AIλ²νλ² μμ€ν
β οΈ μ΄ μ½λλ λ°λͺ¨ λ²μ μΌλ‘ μ¬λ¬ λ¬Έμ κ° μμ μ μμ΅λλ€. κ³μ μ λ°μ΄νΈ μ€μ΄λ―λ‘ μ΅μ λ²μ μ μ μ§ν΄μ£ΌμΈμ.
μλ νμΈμ! μ΄ νλ‘μ νΈλ₯Ό κ°λ°ν μ μμμ λλ€.
νμ¬ κ΅° 볡무 μ€μ΄λΌ νλ‘μ νΈλ₯Ό νλ°νκ² μ
λ°μ΄νΈνκΈ° μ΄λ €μ΄ μν©μ
λλ€.
λ€μ μ£Όμ μ
λ°μ΄νΈλ μ μ νμΈ 2025λ
5μ μ΄νμ κ°λ₯ν μμ μ
λλ€.
κ·Έλμ νλ‘μ νΈλ₯Ό νμ©νμλ©΄μ λ²κ·Έλ κ°μ μ μ΄ μλ€λ©΄ μ΄μλ₯Ό λ¨κ²¨μ£Όμλ©΄ κ°μ¬νκ² μ΅λλ€.
λͺ¨λ κΈ°μ¬μλΆλ€κ» νμ κ°μ¬λ립λλ€! π
CUDA 12.3
PyTorch 2.2.0 cuda121
Python 3.9+
Ollama
GPT-SoVITS-v2λ₯Ό λ€μ΄λ‘λν ν, GPT λͺ¨λΈκ³Ό SoVITSλ₯Ό νμ΅νμ¬ TTS λͺ¨λΈμ μμ±ν©λλ€.
GPT-SoVITS-v2/configs/tts_infer.yaml
νμΌμ μμ ν©λλ€.
t2s_weights_path,vits_weights_path κ²½λ‘λ₯Ό νμ΅λ μ¬μ©μμ λͺ¨λΈλ‘ λ³κ²½ν©λλ€.
device: cuda
is_half: true
t2s_weights_path: GPT_weights_v2/MY_TTS_MODEL.ckpt
version: v2
vits_weights_path: SoVITS_weights_v2/MY_TTS_MODEL.pth
device: cpu
is_half: false
t2s_weights_path: GPT_weights_v2/MY_TTS_MODEL.ckpt
version: v2
vits_weights_path: SoVITS_weights_v2/MY_TTS_MODEL.pth
default_v2:
bert_base_path: GPT_SoVITS/pretrained_models/chinese-roberta-wwm-ext-large
cnhuhbert_base_path: GPT_SoVITS/pretrained_models/chinese-hubert-base
device: cuda
is_half: true
t2s_weights_path: GPT_weights_v2/MY_TTS_MODEL.ckpt
version: v2
vits_weights_path: SoVITS_weights_v2/MY_TTS_MODEL.pth
Ollama λ€μ΄λ‘λ Ollama Models λ€μ΄λ‘λ
DEMO_test.py
μμ Ollama λͺ¨λΈμ΄λ¦μ λ€μ΄λ‘λν λͺ¨λΈμ μ΄λ¦μΌλ‘ λ³κ²½ν©λλ€.- λͺ¨λΈ μ΄λ¦μ μλ λͺ λ Ήμ΄λ‘ νμΈν μ μμ΅λλ€.
ollama list
μμ μ½λ (DEMO_test.py
μμ λΆλΆ)
class OllamaChat:
def __init__(self, model: str = "Ollama λͺ¨λΈμ΄λ¦") -> None:
self.model = model
self.system_message = {
'role': 'system',
'content': (
"λΉμ μ μΈν°λ· AI λ°©μ‘ ν¬λ¦¬μμ΄ν°μ
λλ€. "
"Ollama κΈ°λ°μ μΈκ³΅μ§λ₯ AIμ΄λ©°, μμ²μλ€κ³Ό μν΅νλ κ²μ μ¦κΈ°κ³ νΈνΈν μ±κ²©μ κ°μ‘μ΅λλ€. "
"μ‘΄λλ§μ μ¬μ©νμ§ λ§κ³ , λνλ μ§§κ³ κ°κ²°νκ² νλ©°, μ νν μ 보λ₯Ό μ λ¬νμΈμ."
)
}
self.conversation_history = []
DEFAULT_REF_AUDIO = r"C:\Users\unit6\Documents\Test\My_tts\My_BaseTTS_v2.wav" # μ°Έμ‘° μ€λμ€ κ²½λ‘
DEFAULT_PROMPT_TEXT = "" # μ°Έμ‘° ν
μ€νΈ (νκ΅μ΄λ λΉμΉΈμΌλ‘)
DEFAULT_PROMPT_LANG = "ko" # μ°Έμ‘° μΈμ΄ μ€μ
VTubeStudio μ€μ μμ VTubeStudio API μμ μ΅μ μ ONμΌλ‘ νμ±νν©λλ€.
VTubeStudio μ€ν.
cd GPT-SoVITS-v2-240821
python api_v2.py -a 127.0.0.1 -p 9880 -c GPT_SoVITS/configs/tts_infer.yaml
python DEMO_test.py
VTubeStudio νλ©΄μ κΆν μμ²μ νμ©ν©λλ€.
πΉ μμ https://youtu.be/XH1xBt59EGw
λ§μ½ VTubeStudio λͺ¨λΈμ΄ μμ§μ΄μ§ μλλ€λ©΄, DEMO_vts_api_helper.py
μ param_id
κ° μ€μ IDμ μΌμΉνλμ§ νμΈνμΈμ.
def inject_mouth_value(self, mouth_value: float, face_found: bool = True, param_id: str = "MouthOpen"): # μ€μ ID νμΈ
if not self.authenticated:
return
mouth_value = max(0.0, min(1.0, mouth_value))
req_id = str(uuid.uuid4())[:8]
payload = {
"apiName": "VTubeStudioPublicAPI",
"apiVersion": "1.0",
"requestID": req_id,
"messageType": "InjectParameterDataRequest",
"data": {
"faceFound": face_found,
"mode": "set",
"parameterValues": [
{"id": param_id, "value": mouth_value}
]
}
}
self.send_message(payload)
μ΄ νλ‘μ νΈλ μ€νμμ€λ‘ μ 곡λ©λλ€. μ¬μ© μ λΌμ΄μ μ€λ₯Ό μ°Έκ³ νμΈμ.
κΆκΈν μ μ΄λ κ°μ μ¬νμ΄ μλ€λ©΄ μ΄μλ₯Ό λ¨κ²¨μ£ΌμΈμ! π
Discord : leehyunbin