2022年底 OpenAI 引爆大語言模型(Large Lauguage Model,LLM)及生成式人工智慧(Generative Artificial Intelligence,GenAI),從此有各種文字、聲音、影像及多模態的應用,其中「虛擬主播」就是很常的應用例,如像民視的「敏熙」就是很經典的案例。
說到虛擬主播,其演進歷史也有數十年,早年需由美工人員大費周章設計好3D人物模型,再請配音員配上固定對白,最後由動畫人員把肢體動作、對白和嘴形對好,才能完成影片輸出,常見於高階 3D 電玩中較精緻的非玩家角色(Non-Player Character,NPC)。
後來隨著傳統電腦視覺及3D動畫技術演進,慢慢開始有了虛擬代理人(Virtual Agent)、VTuber (Video + Youtuber)出現,只要事先準備好可愛的3D人物模型(公仔),加上高階動作補捉器(Motion Capture),再請真人表演肢體及臉部動作來驅動3D公仔,就可大幅減少美工及動畫人員的工作。早期電腦性能較差,只能採預錄加上後處理合成方式處理,像日本「初音未來」這類「虛擬偶像」及擬真 3D 電影「阿凡達」就是知名代表。
後來隨電腦性能及電腦視覺技術成熟,只需使用一般網路攝影機,就能即時偵測到表演者的動作、表情並驅動3D公仔,一般會稱呼表演者為 VTuber (Video Youtuber),像日本知名「絆愛」、台灣 Yahoo TV 的「虎妮」就屬此類。這樣的技術很適合哪些不露臉的表演者和真實世界的互動,但缺點也是沒有真人就無法操作了,且真人表演不流暢也會影響虛擬人物表現。
十多年前深度學習電腦視覺及自然語言處理(Natual Language Processing,NLP)技術興起,讓電腦有機會能完全控制3D公仔的肢體動作、語音轉文字(Speech To Text,STT)、自然語言理解(Natual Language Understanding,NLU)、對話內容產生、語音轉文字(Text To Speech,TTS),於是開始有了虛擬助理(Vitrual Assistant)和虛擬代理人(Virtual Agent)出現。而隨著大語言模型及生成式技術越來越成熟,像真人一樣互動的數位分身(中國大陸慣稱數字人--即Digital Human、Meta Human)也開始出現在各種場域中,如捷運站的虛擬客服。
圖1:虛擬分身演進,3D人物、人臉建模,動作、表情補捉、真人驅動VTuber,大語言模型及生成式AI客服、主播。(OmniXRI整理製作, 2024/12/12)
為了使大家能更進一步理解如何實作一個簡單離線版(邊緣端)的虛擬主播,可以輸入所需文字,產生對應語音,配合閉嘴人物影片生成新的對嘴影片。接下來就分別從「推論硬體及環境建置介紹」、「MeloTTS 文字轉語音生成」、「Wav2Lip 自動對嘴影片生成」及「建置完整虛擬主播」等四大部份作更進一步說明。
完整範例程式可參考下列網址:https://github.com/OmniXRI/digital_human
(註:本文範例不適用 Google Colab 執行,僅限Intel OpenVINO Notebooks虛擬環境下使用)
1. 推論硬體及環境建置介紹
這裡選用了 Intel AI PC Asus NUC 14 Pro (Core Ultra 5 125H, 內建 Arc GPU, 10TOPS NPU, DDR5 32GB)作為邊緣推論裝置,完整規格請見參考文獻。建議使用前先到官網更新一下NPU驅動程式。(註:如果你仍是使用 Core i3/i5/i7 12/13/14代CPU,在Windows 10運作,原則上以下各範例還是可以執行,只是速度上會慢上許多。)
本文主要使用Windows 11,工作環境是根據 Intel OpenVINO Notebooks 建議的 Python 虛擬環境。如果你未曾安裝過OpenVINO及Notebooks則可參考官方Github 說明進行全新的安裝。
(註:如需中文安裝說明,可參考第2小節說明)
OpenVINO Notebooks目前最新版(latest)為2024.5版,原則大部份的範例都可執行在OpenVINO 2024.x 版。由於w2vlip 範例 只存在 2024.5版中,所以如果電腦中已安裝過較舊版本OpenVINO Notebooks,請先下載最新版openvinotoolkit/openvino_notebooks的ZIP格式檔案,解壓縮後再把 /notebooks/wav2lip 整個檔案夾複製到自己電腦上原先 /openvino_notebooks/notebooks 路徑下,才能進行後面的工作。
不管全新或部份安裝,為避免影響到原先的範例程式,所以請先將 /notebooks/wav2lip 檔案夾複製一份,並更名為 /notebooks/digital_humnan,以便後續將MeloTTS和Wav2Lip整合在一起。接著將 https://github.com/OmniXRI/digital_human 中三個 ipynb 範例下載到 \digitl_human 路徑下,以利後續測試。
另外由於程式會使用到影音相關處理函式,但這些未包括在 OpenVINO & Notebooks 範例中,所以需手動安裝 ffmpeg 函式庫。請確認已進入 OpenVINO Notebooks Python 虛擬環境中後再安裝,如以下指令所示:
pip install ffmpeg
2. MeloTTS 文字轉語音生成
目前 OpenVINO 在文字轉語音(TTS)方面雖有提供 OuteTTS 和 Parler-TTS 範例,但本文使用另一個更輕量的模型 MeloTTS 。它提供了多國語言,如英文、法文、日文、韓文、西班牙文等,其中當然也有包含中文(可中英文混合)。使用上非常簡單,只需提供待發音之文字內容、語速即可。
由於 MeloTTS 尚未正式加入 OpenVINO Notebooks 中,所以這裡我們需要手動安裝相關套件。安裝前,首先啟動 OpenVINO Notebooks Python 虛擬環境,但先不要啟動 Jupyter Notebooks 環境,進到 /openvino_notebooks/notebooks/ 路徑中準備安裝。
接著到 https://github.com/zhaohb/MeloTTS-OV/tree/speech-enhancement-and-npu ,按下綠色「<> Code」,選擇「Download ZIP」,解壓縮後把 \MeloTTS-OV-speech-enhancement-and-npu 檔案夾內所有內容複製到 \openvino_notebooks\notebooks\digital_human 下。
(註:請不要直接複製網頁上git clone命令,這樣會誤下載到標準版本,導致 OpenVINO 無法正確執行。)
再來進到指定路徑,開始安裝必要套件。
cd digital_human
pip install -r requirements.txt
pip install openvino nncf
python setup.py develop # or pip install -e .
python -m unidic download
python -m nltk.downloader averaged_perceptron_tagger_eng
pip install deepfilternet # optional for enhancing speech
pip install ffmpeg # 一定要裝,不然影音內容無法顯示
完成後執行下列命令進行文字轉語音測試。這裡 language 設為 ZH (中英混合)即可, tts_device 可設為CPU、GPU,而bert_device則可設為 CPU、GPU、NPU。
python test_tts.py --language ZH --tts_device CPU --bert_device CPU
第一次執行會花比較多的時間下載模型及轉換成OpenVINO用的IR格式(bin+xml),完成的模型會存放在 \tts_ov_ZH 路徑下。執行完成後會得到 ov_en_int8_ZH.wav ,語音內容為「我們探討如何在Intel平台上轉換和優化atificial intelligence 模型」,可開啟聲音播放軟體進行檢查。
完成上述步驟後才能運作下列簡易版帶介面程式 MeloTTS_run.ipynb 。這個範例有提供 Gradio 介面,方便大家以網頁方式重覆輸入測試字串及檢查生成聲音檔案內容。
下次想要測試時,由於已有轉換好的模型,所以直接開啟並執行這個範例即可執行文字轉語音工作。
# MeloTTS for OpenVINO 單獨執行含Gradio介面範例
#
# by Jack OmniXRI, 2024/12/12
from melo.api import TTS
from pathlib import Path
import time
# MeloTTS 文字轉語音基本參數設定
speed = 1.0 # 調整語速
use_ov = True # True 使用 OpenVINO, False 使用 PyTorch
use_int8 = True # True 啟用 INT8 格式
speech_enhance = True # True 啟用語音增強模式
tts_device = "CPU" # 指定 TTS 推論裝置 , "CPU" 或 "GPU"(這裡指 Intel GPU)
bert_device = "CPU" # 指定 Bert 推論裝置, "CPU" 或 "GPU" 或 "NPU"
lang = "ZH" # 設定語系, EN 英文, ZH 中文(含混合英文、簡繁中文皆可)
# 指定測試文字轉語音字串
if lang == "ZH":
text = "我們討如何在 Intel 平台上轉換和優化 artificial intelligence 模型"
elif lang == "EN":
text = "For Intel platforms, we explore the methods for converting and optimizing models."
# 若指定語音增強模式則新增 process_audio() 函式
if speech_enhance:
from df.enhance import enhance, init_df, load_audio, save_audio
import torchaudio
# 將輸入聲音檔案處理後轉存到新檔案中
def process_audio(input_file: str, output_file: str, new_sample_rate: int = 48000):
"""
Load an audio file, enhance it using a DeepFilterNet, and save the result.
Parameters:
input_file (str): Path to the input audio file.
output_file (str): Path to save the enhanced audio file.
new_sample_rate (int): Desired sample rate for the output audio file (default is 48000 Hz).
"""
model, df_state, _ = init_df()
audio, sr = torchaudio.load(input_file)
# Resample the WAV file to meet the requirements of DeepFilterNet
resampler = torchaudio.transforms.Resample(orig_freq=sr, new_freq=new_sample_rate)
resampled_audio = resampler(audio)
enhanced = enhance(model, df_state, resampled_audio)
# Save the enhanced audio
save_audio(output_file, enhanced, df_state.sr())
# 初始化 TTS
model = TTS(language=lang, tts_device=tts_device, bert_device=bert_device, use_int8=use_int8)
# 取得語者資訊
speaker_ids = model.hps.data.spk2id
speakers = list(speaker_ids.keys())
# 若指定使用 OpenVINO, 檢查該語系是否已處理過,若無則進行轉換,結果會存在 \tts_ov_語系 路徑下
if use_ov:
ov_path = f"tts_ov_{lang}"
if not Path(ov_path).exists():
# 將原始模型轉換成 OpenVINO IR (bin+xml) 格式
model.tts_convert_to_ov(ov_path, language= lang)
# 進行模型初始化
model.ov_model_init(ov_path, language = lang)
if not use_ov: # 若未使用 OpenVINO
for speaker in speakers:
output_path = 'en_pth_{}.wav'.format(str(speaker))
start = time.perf_counter()
model.tts_to_file(text, speaker_ids, output_path, speed=speed*0.75, use_ov = use_ov)
end = time.perf_counter()
else: # 若使用 OpenVINO
for speaker in speakers:
output_path = 'ov_en_int8_{}.wav'.format(speaker) if use_int8 else 'en_ov_{}.wav'.format(speaker)
start = time.perf_counter()
model.tts_to_file(text, speaker_ids, output_path, speed=speed, use_ov=use_ov)
if speech_enhance:
print("Use speech enhance")
process_audio(output_path,output_path)
end = time.perf_counter()
dur_time = (end - start) * 1000
print(f"MeloTTS 文字轉語音共花費: {dur_time:.2f} ms")
# 使用 Gradio 產生互動介面
import gradio as gr
# 定義文字轉語音處理函式 tts()
# 輸入: content(字串)、 use_ov(布林值)、 speed(數值)
# 輸出: "MeloTTS 文字轉語音共花費: xx.xx ms"(字串)、 語音檔案名稱(字串)
def tts(content, use_ov, speed):
start = time.perf_counter()
model.tts_to_file(content, speaker_ids, output_path, speed=speed/100, use_ov=use_ov)
if speech_enhance:
print("Use speech enhance")
process_audio(output_path,output_path)
end = time.perf_counter()
dur_time = (end - start) * 1000
audio = "ov_en_int8_ZH.wav"
result = f"MeloTTS 文字轉語音共花費: {dur_time:.2f} ms"
return result, audio
# 建立輸人及輸出簡單應用介面
# fn: 介面函數名稱
# inputs: 輸人格式, 文字(標籤:名字, 值: “請輸入文字內容")、使用 OpenVINO(複選盒)、滑動桿(標籤:語速(%),最小值50,最大值200,預設值100)
# outputs: 輸出格式,結果字串(標籤:輸出)、輸出音檔(標籤:輸出結果, 檔格式式: filetype)
demo = gr.Interface(
fn=tts,
inputs=[gr.Textbox(label="文字", value = "請輸入文字內容"),
gr.Checkbox(value=True, label="Use_OpenCV"),
gr.Slider(50, 200, value=100, label="語速(%)") ],
outputs=[gr.Textbox(label="轉換時間"),
gr.Audio(label="輸出結果", type="filepath")],
)
# 執行顯示介面
demo.launch()
只需不到短短一分鐘...
輸入您的信箱與ID註冊即可享有一切福利!
會員福利
免費電子報
會員搶先看
主題訂閱
好文收藏