写在前面

很早就在b站上看到有虚拟主播的计划,之前看到的计划主要分为3种:

  • ①用的unity+live2d
  • ②有的用的steam的Vtube Studio这款软件
  • ③也有根据galgame的。

根据纯前端和python的我好像没找到,在看到一篇文章:/post/720474… ,运用的pixi-live2d-display这个纯前端es6就能够完成前端的表情操控。不过这个没写口型的操控。关于pixi-live2d-display的口型操控,我在这个 github.com/itorr/itorr… 找到了计划。

下面介绍我完成的live2d虚拟直播姬Demo的过程,代码放在了:github.com/nladuo/live…

视频作用见B站:www.bilibili.com/video/BV1iX…

前端Live2D虚拟形象

前端的虚拟形象便是用的pixi-live2d-display,我用vite的vue模版建了一个工程(后来发现用不到vue,自己前端小白哈),首先调通了嘴型的操控,也便是经过按钮来操控嘴型闭合。

HTML代码:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <script src="https://cubism.live2d.com/sdk-web/cubismcore/live2dcubismcore.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/dylanNew/live2d/webgl/Live2D/lib/live2d.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/pixi.js@6.5.2/dist/browser/pixi.min.js"></script>
    <title>Live2d display control</title>
  </head>
  <body>
    <canvas id="canvas2" style="margin-top: 50px;"></canvas>
    <button id="mbtn">张嘴</button>
    <button id="mbtn2">闭嘴</button>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

JS代码:

import * as PIXI from 'pixi.js';
import { Live2DModel } from 'pixi-live2d-display/cubism4';
window.PIXI = PIXI;
const app = new PIXI.Application({
    view: document.getElementById("canvas2"),
    autoStart: true,
    // resizeTo: window
  });
const cubism4Model = "assets/haru/haru_greeter_t03.model3.json";
const model = await Live2DModel.from(cubism4Model);
app.stage.addChild(model);
// transforms
model.x = 900;
model.y = 0;
model.rotation = Math.PI;
model.skew.x = Math.PI;
model.scale.set(0.45);
// 设置嘴型
const setMouthOpenY = v=>{
    v = Math.max(0,Math.min(1,v));
    model.internalModel.coreModel.setParameterValueById('ParamMouthOpenY',v);
}
document.getElementById("mbtn").onclick = () =>{
    setMouthOpenY(1)
}
document.getElementById("mbtn2").onclick = () =>{
    setMouthOpenY(0)
}

这儿经过setMouthOpenY来设置嘴型开闭,1为张嘴,0为闭嘴。

live2d模型修正

由于要操控口型,需求删掉live2d自身自带的一堆动作,模型文件删的差不多了,就剩余基本的: github.com/nladuo/live…

{
  "Version": 3,
  "FileReferences": {
    "Moc": "haru_greeter_t03.moc3",
    "Textures": [
      "haru_greeter_t03.2048/texture_00.png",
      "haru_greeter_t03.2048/texture_01.png"
    ],
    "Expressions": [
    ],
    "Motions": {
    }
  },
  "Groups": [
    {
      "Target": "Parameter",
      "Name": "EyeBlink",
      "Ids": [
        "ParamEyeLOpen",
        "ParamEyeROpen"
      ]
    }
  ],
  "HitAreas": [
    {
      "Id": "HitArea",
      "Name": "Head"
    },
    {
      "Id": "HitArea2",
      "Name": "Body"
    }
  ]
}

作用

张嘴

前端+Python实现Live2D虚拟直播姬

闭嘴

前端+Python实现Live2D虚拟直播姬

音频和虚拟形象嘴型对应

我在网上搜了一些音频和口型的操控许多都是深度学习办法的,不过关于直播姬的要求我觉得没必要那么精确。

这儿我拍脑袋想了一种办法,经过声响的响度来操控口型。

这儿运用librosa得到音频的时域信息,能够看到声响的起伏随着时刻改变的情况,然起伏越大也意味着响度越大,代表张嘴越大。

前端+Python实现Live2D虚拟直播姬

这儿我挑选采样间隔为0.1秒,算法如下:

def my_tts(text, save_path):
    tts = gTTS(text, lang="zh-CN")
    tts.save(save_path)
def tts_and_play_audio(text):
    tmp_audio_path = 'tmp.mp3'
    my_tts(text, tmp_audio_path)
    pygame.mixer.init()
    pygame.mixer.music.load(tmp_audio_path)  
    pygame.mixer.music.set_volume(0.8) 
    x , sr = librosa.load(tmp_audio_path, sr=8000)
    x = x  - min(x)
    x = x  / max(x)
    x= np.log(x) + 1
    x = x  / max(x) * 1.2
    pygame.mixer.music.play()
    s_time = time.time()
    try:
        for _ in range(int(len(x) / 800)):
            it = x[int((time.time() - s_time) * 8000)+1]
            if it < 0:
                it = 0
            with open("tmp.txt", "w") as f:
                f.write(str(float(it)))
            time.sleep(0.1)
    except:
        pass
    time.sleep(0.1)
    with open("tmp.txt", "w") as f:
        f.write("0")

这儿我运用了gTTS来做文字转声响,把tts的输出的音频经过pygame进行后台播放,同时根据时刻来操控嘴的巨细,把嘴型的巨细写到tmp.txt文件中。

后端操控

然后写个后端不断的读取tmp.txt的嘴型巨细,前端再去恳求嘴型巨细进行操控即可。流程如下:

前端+Python实现Live2D虚拟直播姬

接入ChatGPT

最终的话便是接入ChatGPT了,这儿我用了:pypi.org/project/rev…,运用的prompt如下:

请运用女性化的语言风格,扮演一个正在直播的 vtuber,之后我的输入均为用户谈论,请用简略的一句话回答它们吧,每句话不要超越20字,而且不要运用表情,运用纯文字进行回答,不要运用emoji表情。

前端+Python实现Live2D虚拟直播姬

这儿我在ChatGPT首先先创建了一个会话窗口然后在指定的conversation_id进行直播内容互动。

from revChatGPT.V1 import Chatbot
access_token = "浏览器访问https://chat.openai.com/api/auth/session获取"
conversation_id = ""
chatbot = Chatbot(config={"access_token": access_token}, conversation_id=conversation_id)
def ask(prompt):
    for data in chatbot.ask(prompt):
        response = data["message"]
    return response

最终作用如下:

前端+Python实现Live2D虚拟直播姬

(真实跑起来口型会动起来,而且我觉得对的还能够。)

弥补说明

gTTS的发声感觉其实不像一个直播姬(心爱的女孩子)该有的声响,能够加入VITS练习得到自己喜爱的声响【B站有许多教程这儿就不说了】,当然也能够用用别的哈。