デジタル ヒューマン ソリューション - ER-NeRF リアルタイム対話デジタル ヒューマン モデル推論展開 UI インタラクティブ インターフェイス

導入

これは、ER-NeRF を使用してリアルタイム会話デジタル ヒューマンと口頭放送デジタル ヒューマンを実現する全体的なアーキテクチャであり、大規模な言語応答モデル、音声合成、生成されたビデオ ストリーム、背景置換などの機能が含まれています。ビデオ メモリ。リアルタイム推論の効果を実現したい場合は、24G 以上のグラフィック カードを搭載することをお勧めします。

デジタル担当者とのリアルタイムの会話

ディスカッショングループのペンギン: ​​787501969

1. 環境のインストール

#下载源码
git clone https://github.com/Fictionarry/ER-NeRF.git
cd ER-NeRF
#创建虚拟环境
conda create --name vrh python=3.10
activate vrh
#pytorch 要单独对应cuda进行安装,要不然训练时使用不了GPU
conda install pytorch==2.0.0 torchvision==0.15.0 torchaudio==2.0.0 pytorch-cuda=11.7 -c pytorch -c nvidia
conda install -c fvcore -c iopath -c conda-forge fvcore iopath
#安装所需要的依赖
pip install -r requirements.txt

#处理音频时用的
pip install tensorflow

pytorch3d ソース コードをダウンロードします。ダウンロードできない場合は、上の Baidu ネットワーク ディスク ダウンロードをクリックしてください: リンク: https://pan.baidu.com/s/1xPFo-MQPWzkDMpLHhaloCQ
抽出コード: 1422

git clone https://github.com/facebookresearch/pytorch3d.git
cd pytorch3d
python setup.py install

2.対話モデルChatGLM3

1. ChatGLM3 の概要

ChatGLM3 は、中国語と英語のバイリンガリズムをサポートするオープン ソースの会話言語モデルです。Zhipu AI と清華大学の KEG 研究室が共同でリリースしています。一般言語モデル (GLM) アーキテクチャに基づいており、62 億のパラメータがあります。ChatGLM3-6B は、前 2 世代のモデルのスムーズな対話と導入しきい値の低さという利点を維持しながら、さらに多くの機能を追加しています。ChatGLM は現時点では GPT よりわずかに劣っていますが、ChatGLM は展開後に完全にローカルで実行でき、ユーザーはモデルの使用を完全に制御できます。これにより、ユーザーはより高い柔軟性と自主性を得ることができます。
ChatGLM3-6B はより強力な基本モデルであり、その基本モデル ChatGLM3-6B-Base は、より多様なトレーニング データ、より十分なトレーニング ステップ、およびより合理的なトレーニング戦略を使用します。セマンティクス、数学、推論、コード、知識などのさまざまな観点からデータセットを評価したところ、ChatGLM3-6B-Base は 10B 未満の基本モデルの中で最も高いパフォーマンスを示しました。ChatGLM3-6B には、より完全な機能サポートもあります。新しく設計されたプロンプト形式を採用しており、通常のマルチラウンド会話をサポートするだけでなく、ツール呼び出し (ファンクション コール)、コード実行 (コード インタープリター)、エージェント タスクなどの複雑なシナリオもネイティブにサポートします。対話モデル ChatGLM3-6B に加えて、基本モデル ChatGLM3-6B-Base および長文対話モデル ChatGLM3-6B-32K オープンソースもあります。これらの重みはすべて学術研究に完全に公開されており、アンケートに記入して登録すれば無料で商用利用も可能です。
在这里插入代码片ここに画像の説明を挿入します

2.モデルとダウンロード

ChatGLM3-6B オープンソース ChatGLM3-6B、ChatGLM3-6B-Base、ChatGLM3-6B-32K の 3 つのモデル:

モデル シーケンスの長さ ダウンロード
チャットGLM3-6B 8k ハグフェイスModelScope
チャットGLM3-6B-Base 8k ハグフェイスModelScope
チャットGLM3-6B-32K 32k ハグフェイスModelScope
量的レベル 最小 8K 長のビデオ メモリを生成する
FP16 15.9GB
INT8 11.1GB
INT4 8.5GB

3. プロジェクトの展開

  1. このプロジェクトには Python 3.10 以降が必要です。
conda create -n ChatGLM3 python=3.10
conda activate ChatGLM3
  1. ソースコードとモデルをダウンロードする
git clone https://github.com/THUDM/ChatGLM3.git
git lfs clone https://huggingface.co/THUDM/chatglm3-6b
  1. 依存関係をインストールします。
cd ChatGLM3
pip install -r requirements.txt
  1. 複数のグラフィックス カードを高速化してインストールする必要がある
pip install accelerate

4. テスト項目

Basic_demo/cli_demo.py を開き、モデル パスをダウンロードしたばかりのモデル パスに変更します。そうしないと、実行プロセス中にコードが自動的にモデルをダウンロードし、ダウンロードが失敗する可能性があります。

MODEL_PATH = os.environ.get('MODEL_PATH', './chatglm3-6b')

ここに画像の説明を挿入します

3. 音声合成Edge-tts

1.edge-ttsのインストール

Edge-TTS は、Microsoft の Azure Cognitive Services を使用して音声合成 (TTS) を実装する Python ライブラリです。テキストから音声への変換を可能にし、複数の言語と音声をサポートするシンプルな API を提供します。

Edge-TTS ライブラリを使用するには、次の手順に従ってインストールできます。

pip install edge-tts

インストールが完了したら、Python でこのライブラリを使用し、対応する API を呼び出してテキストを音声に変換できます。これには通常、Azure Cognitive Services への要求の送信と、返された音声データの処理が含まれます。

2.edge-ttsテスト

async def main(voicename: str, text: str, OUTPUT_FILE):
    communicate = edge_tts.Communicate(text, voicename)

    with open(OUTPUT_FILE, "wb") as file:
        async for chunk in communicate.stream():
            if chunk["type"] == "audio":
                file.write(chunk["data"])
            elif chunk["type"] == "WordBoundary":
                pass

4. 音声特徴抽出 DeepSpeech

PaddleSpeech は、PaddlePaddle の音声方向に基づいたオープン ソース モデル ライブラリです。音声とオーディオのさまざまな重要なタスクの開発に使用されます。深層学習に基づいた最先端の影響力のあるモデルが多数含まれています。ここでは DeepSpeech を使用して生成された音声から特徴を抽出し、抽出された音声の特徴はビデオ合成用の npy ファイルとして保存されます。

def main():
    """
    Main body of script.
    """
    args = parse_args()
    in_audio = os.path.expanduser(args.input)
    if not os.path.exists(in_audio):
        raise Exception("Input file/directory doesn't exist: {}".format(in_audio))
    deepspeech_pb_path = args.deepspeech
    #add
    deepspeech_pb_path = True
    args.deepspeech = '~/.tensorflow/models/deepspeech-0_1_0-b90017e8.pb'
    #deepspeech_pb_path="/disk4/keyu/DeepSpeech/deepspeech-0.9.2-models.pbmm"
    if deepspeech_pb_path is None:
        deepspeech_pb_path = ""
    if deepspeech_pb_path:
        deepspeech_pb_path = os.path.expanduser(args.deepspeech)
    if not os.path.exists(deepspeech_pb_path):
        deepspeech_pb_path = get_deepspeech_model_file()
    if os.path.isfile(in_audio):
        extract_features(
            in_audios=[in_audio],
            out_files=[args.output],
            deepspeech_pb_path=deepspeech_pb_path,
            metainfo_file_path=args.metainfo)
    else:
        audio_file_paths = []
        for file_name in os.listdir(in_audio):
            if not os.path.isfile(os.path.join(in_audio, file_name)):
                continue
            _, file_ext = os.path.splitext(file_name)
            if file_ext.lower() == ".wav":
                audio_file_path = os.path.join(in_audio, file_name)
                audio_file_paths.append(audio_file_path)
        audio_file_paths = sorted(audio_file_paths)
        out_file_paths = [""] * len(audio_file_paths)
        extract_features(
            in_audios=audio_file_paths,
            out_files=out_file_paths,
            deepspeech_pb_path=deepspeech_pb_path,
            metainfo_file_path=args.metainfo)

5. ビデオ合成 ER-NeRF

1. 言語モデル

  • 簡単な答え:
    テストの便宜のために、ここに簡単な返信機能があります。マシンに大きなビデオ メモリがない場合は、この機能を使用してデジタル ヒューマンが実行できるかどうかをテストできます。
def test_answer(message):
    message = message.lower()

    if message == "你好":
        response = "你好,有什么可以帮到你吗?"

    elif message == "你是谁":
        response = f"我是虚拟数字人静静,这是我的一个测试版本。"

    elif message == "你能做什么":
        response = "我可以陪你聊天,回答你的问题,我还可以做很多很多事情!"
    else:
        response = "你的这个问题超出了我的理解范围,等我学习后再来回答你。或者你可以问我其他问题,能回答的我尽量回答你!"

    return response
  • GLM 回答
    GLM 言語モデルを使用して回答します。コードを推論コードに直接統合できます。これにより、大量の GPU が消費されます。12G を超えるビデオ メモリがない場合は、GLM をサーバー形式にすることをお勧めします。アクセス用:
tokenizer = AutoTokenizer.from_pretrained("ChatGLM3/chatglm3-6b", trust_remote_code=True)
model = AutoModel.from_pretrained("ChatGLM3/chatglm3-6b", trust_remote_code=True, device='cuda')
video_pre_process()

def glm_answer(query):
    global model
    model = model.eval()
    query = query +"(请在20个字内回答)"
    response, history = model.chat(tokenizer, query, history=[])

    return response

2. 音声合成と音声特徴抽出

生成された音声のスピーカーを選択します。


    audio_eo_path,audio_path_wav = text_to_audio(response,dir,voicename)

    output_video_path = compound_video(audio_path_wav, audio_eo_path, cv_bg, dir, 0)

    return history, history, output_video_path

def text_to_audio(text,save_path,voicename):
    global voices_list;

    asyncio.set_event_loop(asyncio.new_event_loop())
    name = ''
    if voicename == "晓晓":
        name = 'zh-CN-XiaoxiaoNeural'
    if voicename == "晓依":
        name = 'zh-CN-XiaoyiNeural'
    if voicename == "云霞":
        name = 'zh-CN-YunxiaNeural'
    if voicename == "东北":
        name = 'zh-CN-liaoning-XiaobeiNeural'
    if voicename == "陕西":
        name = 'zh-CN-shaanxi-XiaoniNeural'
    if voicename == "云剑":
        name = 'zh-CN-YunjianNeural'
    if voicename == "云溪":
        name = 'zh-CN-YunxiNeural'
    if voicename == "云阳":
        name = 'zh-CN-YunyangNeural'

    timestamp = int(time.time())
    audio_path_mp3 = os.path.join(save_path, str(timestamp) + ".mp3")
    audio_path_wav = os.path.join(save_path, str(timestamp) + ".wav")

    asyncio.get_event_loop().run_until_complete(main(name, text,audio_path_mp3))

    command = ['ffmpeg', '-i', audio_path_mp3, audio_path_wav]
    subprocess.run(command, capture_output=True, text=True)

    cmd = f'python data_utils/deepspeech_features/extract_ds_features.py --input {
      
      audio_path_wav}'
    os.system(cmd)

    audio_eo_path = os.path.join(save_path, str(timestamp) + ".npy")

    return audio_eo_path,audio_path_wav

3. 合成ビデオ

合成動画は使用する背景を選択できるほか、ポートレートの位置を左・中央・右の3つに分け、実行中に動的に変更することも可能です。

def answer(message, history,voicename,llm_name):
    global dir
    global cv_bg
    history = history or []

    response = ''
    if llm_name =="测试":
        response = test_answer(message)
    elif llm_name =="ChatGLM3":
        response = glm_answer(message)

    history.append((message, response))

    audio_eo_path,audio_path_wav = text_to_audio(response,dir,voicename)

    output_video_path = compound_video(audio_path_wav, audio_eo_path, cv_bg, dir, 0)

    return history, history, output_video_path

4.webuiコードの統合

ここでは Gradio を使用してインタラクティブな UI を作成します。

import gradio as gr
import time
import cv2
import os
from tools import video_pre_process, compound_video

from transformers import AutoTokenizer, AutoModel

import asyncio
import edge_tts
import subprocess


dir = "workspace"
cv_bg = cv2.imread('bg_1.jpg')

tokenizer = AutoTokenizer.from_pretrained("ChatGLM3/chatglm3-6b", trust_remote_code=True)
model = AutoModel.from_pretrained("ChatGLM3/chatglm3-6b", trust_remote_code=True, device='cuda')
video_pre_process()

def glm_answer(query):
    global model
    model = model.eval()
    query = query +"(在20个字内回答)"
    response, history = model.chat(tokenizer, query, history=[])

    return response


async def main(voicename: str, text: str, OUTPUT_FILE):
    communicate = edge_tts.Communicate(text, voicename)

    with open(OUTPUT_FILE, "wb") as file:
        async for chunk in communicate.stream():
            if chunk["type"] == "audio":
                file.write(chunk["data"])
            elif chunk["type"] == "WordBoundary":
                pass

def test_answer(message):
    message = message.lower()

    if message == "你好":
        response = "你好,有什么可以帮到你吗?"

    elif message == "你是谁":
        response = f"我是虚拟数字人静静,这是我的一个测试版本。"

    elif message == "你能做什么":
        response = "我可以陪你聊天,回答你的问题,我还可以做很多很多事情!"
    else:
        response = "你的这个问题超出了我的理解范围,等我学习后再来回答你。或者你可以问我其他问题,能回答的我尽量回答你!"

    return response

def answer(message, history,voicename,llm_name):
    global dir
    global cv_bg
    history = history or []

    response = ''
    if llm_name =="测试":
        response = test_answer(message)
    elif llm_name =="ChatGLM3":
        response = glm_answer(message)

    history.append((message, response))

    audio_eo_path,audio_path_wav = text_to_audio(response,dir,voicename)

    output_video_path = compound_video(audio_path_wav, audio_eo_path, cv_bg, dir, 0)

    return history, history, output_video_path

def text_to_audio(text,save_path,voicename):
    global voices_list;

    asyncio.set_event_loop(asyncio.new_event_loop())
    name = ''
    if voicename == "晓晓":
        name = 'zh-CN-XiaoxiaoNeural'
    if voicename == "晓依":
        name = 'zh-CN-XiaoyiNeural'
    if voicename == "云霞":
        name = 'zh-CN-YunxiaNeural'
    if voicename == "东北":
        name = 'zh-CN-liaoning-XiaobeiNeural'
    if voicename == "陕西":
        name = 'zh-CN-shaanxi-XiaoniNeural'
    if voicename == "云剑":
        name = 'zh-CN-YunjianNeural'
    if voicename == "云溪":
        name = 'zh-CN-YunxiNeural'
    if voicename == "云阳":
        name = 'zh-CN-YunyangNeural'

    timestamp = int(time.time())
    audio_path_mp3 = os.path.join(save_path, str(timestamp) + ".mp3")
    audio_path_wav = os.path.join(save_path, str(timestamp) + ".wav")

    asyncio.get_event_loop().run_until_complete(main(name, text,audio_path_mp3))

    command = ['ffmpeg', '-i', audio_path_mp3, audio_path_wav]
    subprocess.run(command, capture_output=True, text=True)

    cmd = f'python data_utils/deepspeech_features/extract_ds_features.py --input {
      
      audio_path_wav}'
    os.system(cmd)

    audio_eo_path = os.path.join(save_path, str(timestamp) + ".npy")

    return audio_eo_path,audio_path_wav


with gr.Blocks(css="#chatbot{height:300px} .overflow-y-auto{height:500px}") as rxbot:
    tts_checkbox = gr.Dropdown(["晓晓", "晓依", "云霞", "东北", "陕西", "云剑", "云溪", "云阳"],
                                 label="语音选择", info="晓晓:女, 晓依:女, 云霞:女, 东北:女, 陕西:女, 云剑:男, 云溪:男,云阳:男")

    answer_checkbox = gr.Dropdown(["测试","ChatGLM3", "ChatGPT", "LLaMA"],
                               label="大语言模型",
                               info="测试:只有固定的几个问题, ChatGLM3:GPU在12G以上可以选择这个模型, ChatGPT:暂时没有接入, LLaMA:暂时没有接入")
    with gr.Row():
        video_src = gr.Video(label="数字人", autoplay=True)
        with gr.Column():
            state = gr.State([])
            chatbot = gr.Chatbot(label="消息记录").style(color_map=("green", "pink"))
            txt = gr.Textbox(show_label=False, placeholder="请输入你的问题").style(container=False)
    txt.submit(fn=answer, inputs=[txt, state,tts_checkbox,answer_checkbox], outputs=[chatbot, state, video_src])

# rxbot.launch()

if __name__ == "__main__":
    # response = glm_answer('你好')
    # print(response)
    rxbot.launch()

おすすめ

転載: blog.csdn.net/matt45m/article/details/134256927