大数跨境
0
0

用 DeepSeek 打造智能虚拟主播:从零到上线全流程

用 DeepSeek 打造智能虚拟主播:从零到上线全流程 搜狐技术产品
2025-12-09
2


01

引言

随着 AIGC 技术的快速发展,虚拟主播逐渐成为内容生产、直播带货、在线教育和人机交互的重要应用场景。

传统虚拟主播系统多依赖规则驱动和预设脚本,缺乏灵活性和智能化。而大型语言模型(LLM)的出现,为虚拟主播赋予了自然语言理解、情感表达和多模态生成的能力。

本文将带你从零开始,结合 DeepSeek 模型,搭建一个可落地的智能虚拟主播系统。在阅读完本文后,你将能够:

  • 学会如何让虚拟角色开口说话并口型同步

  • 搭建一套“AI 大脑”驱动的智能对话系统

  • 将画面和声音推流到直播平台,实现真正的“虚拟主播”

02

系统总体架构

一个典型的虚拟主播系统可以分为以下几个核心模块:

  • 输入层

• 观众或用户输入(文字)

  • 智能决策层(核心:DeepSeek 模型)

• 自然语言理解

• 对话管理

• 内容生成与风格控制

  • 输出层

• 语音合成(TTS)

 虚拟形象驱动(口型)

• 场景渲染与实时输出(直播推流)

架构图


03

前期准备工作

在正式搭建前,我们需要先准备好所需的软件和关键信息,这是确保后续流程顺利的基础。

1.安装虚拟主播形象软件(VTube Studio)

VTube Studio 是一款常用的虚拟形象驱动软件,能让虚拟模型实现口型跟随等效果,我们通过 Steam 平台安装:

  • 首先安装 Steam,打开后在商店搜索 “VTube Studio” 并下载安装。

  • 若 Steam 商店加载缓慢或无法打开,可下载网易 UU 加速器对 Steam 进行加速,提升访问速度。

2. 安装 Python 环境

Python 是后续实现文本转语音等功能的关键工具,安装步骤如下:

  • 前往 Python 官网(https://www.python.org/)下载适合 Windows 系统的最新版本。

  • 安装时需勾选 “Add Python to PATH” 选项,方便后续在命令行中直接调用 Python。

  • 安装完成后,打开命令提示符(Win+R,输入 cmd),输入 “python --version”,若显示 Python 版本号,则安装成功。

3. 获取 AI 大模型 API Key

AI 大模型是虚拟主播 “智能大脑” 的核心,我们可选择多种主流模型(比如DeepSeek,通义千问,ChatGPT),它们的 API 接口基本兼容,后续可灵活替换,目前我们用的是DeepSeek做例子:

  • DeepSeek:进入 DeepSeek 官网,注册充值即可获取 API Key,性价比高,足够长时间使用。

4. 安装虚拟声卡驱动

虚拟声卡用于实现声音的内录和传输,确保虚拟主播的语音能被正确识别,步骤如下:

  • 访问虚拟声卡驱动官网(https://vb-audio.com/Cable),下载最新版本的驱动安装包(推荐 “VBCABLE Driver Pack45.zip”,支持 XP 到 WIN11 系统)。

  • 安装完成后,右键点击任务栏音量图标,选择 “声音”,在 “输出” 栏可看到 “CABLE Input (VB-Audio Virtual Cable)”,“输入” 栏可看到 “CABLE Output (VB-Audio Virtual Cable)”,表示安装成功。

04

配置 VTube Studio:让虚拟形象 “活” 起来

安装好 VTube Studio 后,我们需要进行一系列配置,让虚拟模型能跟随声音做出反应。

1. 选择 VTS 模型

打开 VTube Studio,进入模型选择界面:

  • 界面左侧“有更改VTS模型”等选项,若有自定义模型,可点击 “导入” 添加;若无,可选择软件自带的模型(如 Akari、Hijiki、Hiyori_A 等)。

  • 点击想要使用的模型,即可完成选择,模型会在主界面显示。

2. 设置麦克风为虚拟声卡

为了让 VTube Studio 识别到虚拟主播的语音,需将麦克风设置为之前安装的虚拟声卡:

  • 在 VTube Studio 主界面,找到 “设置” 选项,点击进入,找到”麦克风配置“项。

  • 勾选 “使用麦克风”,然后点击 “麦克风” 下拉框,选择 “CABLE Output (VB-Audio Virtual Cable)”。

  • 可根据需求调整 “音频增益”“音量限幅”“频率增益” 等参数,一般保持默认即可,若声音过小,可适当提高 “音频增益”。

3. 配置模型口型跟随声音

让虚拟模型的口型随语音变化,是提升真实感的关键步骤:

  • 在 VTube Studio 中,进入 “设置” 界面,找到 “Mouth Open”(口型张开)相关设置。

  • 在“输入”选项下,点击下拉框,选择 “VoiceVolumePlusMouthOpen”,该选项能让口型根据声音音量和预设的口型参数综合变化。

  • “输出” 选项默认选择 “ParamMouthOpen” 即可。

05

用 OBS Studio 获取虚拟主播画面

OBS Studio 是一款常用的直播推流软件,我们用它来获取 VTube Studio 中的虚拟主播画面,以便后续开播。

打开 OBS Studio,进入主界面:

  • 添加一个”游戏采集“场景。

  • “模式” 选择 “采集特定窗口”,确保只采集 VTube Studio 的画面,避免其他窗口干扰。

  • “窗口” 下拉框中,选择 “[VTube Studio.exe]: VTube Studio”,确保选中正确的 VTube Studio 窗口。

  • 勾选”允许窗口透明“,主要作用是可以给虚拟主播换其他背景。

06

实现文本转语音:让虚拟主播 “开口说话”

文本转语音功能能将 AI 模型生成的文字回复转换为语音,我们使用 Python 的免费库pyttsx3来实现。

1. 安装文本转语音库

打开命令提示符(cmd),输入以下命令安装所需库:

  • 安装pyttsx3:pip install pyttsx3,该库依赖 Windows 系统自带的语音,无需联网,播放声音较为单一。

2. 编写文本转语音代码

以pyttsx3为例,编写简单的文本转语音代码,实现输入文本、语速、音量,输出语音的功能:


    
     
    import pyttsx3
import
 sys

def
 main():
    try
:
        engine = pyttsx3.init()
        # 获取当前语速和音量

        rate = engine.getProperty('rate')
        volume = engine.getProperty('volume')
        # 从命令行参数获取语速(第一个参数)和音量(第二个参数)

        if
 len(sys.argv) > 1:
            rate = int(sys.argv[1])
        if
 len(sys.argv) > 2:
            volume = float(sys.argv[2])
        # 设置语速和音量

        engine.setProperty('rate', rate)
        engine.setProperty('volume', volume)
        # 从标准输入读取文本

        text = sys.stdin.read()
        # 播放语音

        engine.say(text)
        engine.runAndWait()
    except
 Exception as e:
        print
(f"An error occurred: {e}", file=sys.stderr)

if
 __name__ == "__main__":
    main()

将上述代码保存为 “text_to_speech.py” 文件,后续可通过命令行调用该脚本实现文本转语音。

3. 打包 Python 代码为 EXE 文件

为了方便在其他程序(如 C++)中调用文本转语音功能,我们将 “text_to_speech.py 脚本打包为 EXE 文件,使用 pyinstaller 工具:

  • 首先安装 pyinstaller:在命令提示符中输入pip install pyinstaller

  • 进入 “text_to_speech.py” 文件所在的文件夹,在该文件夹路径下打开命令提示符,输入pyinstaller --onefile text_to_speech.py

  • 执行完成后,在该文件夹下会生成 “dist” 文件夹,进入 “dist” 文件夹,即可找到 生成的“text_to_speech.exe” 执行文件,双击可直接运行,也可被其他程序调用。

07

调用 AI 模型 API:给虚拟主播 “智能大脑”

通过调用 AI 模型 API,让虚拟主播能根据用户提问生成智能回复,这里以 DeepSeek为例(其他AI模型调用也一样,基本接口都是一样的),介绍 API 调用方法。

1. API 调用示例(以 DeepSeek 为例)

使用 curl 命令即可调用 DeepSeek 的 API,获取 AI 回复,命令格式如下:


    
     
    curl https://api.deepseek.com/chat/completions \
-H "Content-Type: application/json" \
-H "Authorization: Bearer <DeepSeek API Key>" \
-d '{
"model": "deepseek-chat",
"messages": [
{"role": "system", "content": "你叫小莉,是一位直播场景下的虚拟主播,需要保持简洁与互动性。"},
{"role": "user", "content": "你叫什么名字。"}
],
"stream": false
}'

<DeepSeek API Key>替换为你自己的 DeepSeek API Key,执行该命令,即可得到 AI 模型返回的 JSON 格式回复。如果是其他AI模型,只需要修改url,Key和model即可。

2. 关键参数说明

API 请求中的关键参数决定了 AI 模型的回复效果和返回方式,具体说明如下:

system:用于设定 AI 的角色和回复规则。例如,若想让 AI 扮演直播平台的虚拟主播 “小莉”,可将 content 设置为:“你叫小莉,是一位直播场景下的虚拟主播,需要保持简洁与互动性。”

user:代表用户的提问内容。例如,用户问 “你叫什么名字。”,则 content 设置为 “你叫什么名字”。

stream:控制回复的返回方式。设为 “true” 时,AI 会逐步返回回复内容,适合实时互动场景;设为 “false” 时,AI 会生成完整回复后一次性返回,适合需要完整文本的场景。


3.AI 模型接口调用相关C++实现

callDeepSeekAPI 函数

  • 调用大语言模型 API,发送聊天消息并获取响应。

  • 参数:

    apiKey:API 访问密钥(Bearer Token)

    messages:聊天消息列表(JSON 格式,包含角色和内容)

  • 返回值API 返回的原始响应字符串(JSON 格式)。

  • 核心流程:

  1. 初始化 libcurl 并设置请求 URL(阿里云通义千问兼容接口)。

  2. 构造 JSON 请求体,包含模型名称、消息列表和非流式响应参数。

  3. 设置 HTTP 头部(Content-Type 和 Authorization)。

  4. 注册 WriteCallback 处理响应数据。

  5. 执行请求并清理资源。


    
     
    // 调用DeepSeek接口
std::string callDeepSeekAPI(const std::string& apiKey, const Json::Value& messages){
    CURL* curl;
    CURLcode res;
    std::string readBuffer;

    // 初始化curl

    curl = curl_easy_init();
    if
 (curl) {
        // 设置URL

        //deepseek

        std::string url = "https://api.deepseek.com/chat/completions";
        curl_easy_setopt
(curl, CURLOPT_URL, url.c_str());

        // 设置HTTP方法为POST

        curl_easy_setopt
(curl, CURLOPT_POST, 1L);

        // 构建JSON请求体

        Json::Value request;
        //deepseek

        request["model"] = "deepseek-chat";
        request["messages"] = messages;
        request["stream"] = false;

        Json::StreamWriterBuilder writerBuilder;
        std::string jsonRequest = Json::writeString(writerBuilder, request);

        // 设置请求体

        curl_easy_setopt
(curl, CURLOPT_POSTFIELDS, jsonRequest.c_str());
        curl_easy_setopt
(curl, CURLOPT_POSTFIELDSIZE, (long)jsonRequest.length());

        // 设置请求头

        struct
 curl_slist* headers = NULL;
        headers = curl_slist_append(headers, "Content-Type: application/json");
        std::string authHeader = "Authorization: Bearer " + apiKey;
        headers = curl_slist_append(headers, authHeader.c_str());
        curl_easy_setopt
(curl, CURLOPT_HTTPHEADER, headers);

        // 设置回调函数

        curl_easy_setopt
(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt
(curl, CURLOPT_WRITEDATA, &readBuffer);

        // 执行请求

        res = curl_easy_perform(curl);

        // 检查请求结果

        if
 (res != CURLE_OK) {
            std::cerr << "curl_easy_perform() failed: " << curl_easy_strerror(res) << std::endl;
        }

        // 清理

        curl_easy_cleanup
(curl);
        curl_slist_free_all
(headers);
    }

    return
 readBuffer;
}

WriteCallback 函数

  • 功能作为 libcurl 的回调函数,用于处理 HTTP 响应数据,将接收到的内容追加到字符串中。

  • 参数:

    contents:接收数据的缓冲区指针

    size:每个数据单元的大小

    nmemb:数据单元的数量

    s:用于存储结果的字符串指针

  • 实际处理的数据大小(size * nmemb),若内存分配失败返回 0。


    
     
    // 回调函数,用于处理HTTP响应
size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* s) {
    size_t
 newLength = size * nmemb;
    try
 {
        s->append((char*)contents, newLength);
    }
    catch
 (std::bad_alloc& e) {
        return
 0;
    }
    return
 newLength;
}

parseResponse 函数

  • 解析 API 返回的 JSON 响应,提取大模型的回答内容。

  • 参数response 为 API 返回的原始 JSON 字符串。

  • 返回值提取的回答内容(字符串),解析失败则返回空字符串。


    
     
    // 解析JSON响应
std::string parseResponse(const std::string& response){
    Json::StreamWriterBuilder writerBuilder;
    writerBuilder["emitUTF8"] = true; // 禁止 Unicode 转义,输出 UTF-8 编码的中文
    std::string jsonString = Json::writeString(writerBuilder, response);
    std::wcout.imbue(std::locale(""));
    std::wstring wideJsonString = std::wstring_convert<std::codecvt_utf8<wchar_t>>().from_bytes(jsonString);
    std::wcout << L"recv.messages JSON:" << std::endl;
    std::wcout << wideJsonString << std::endl;

    Json::CharReaderBuilder readerBuilder;
    Json::Value root;
    std::string errors;
    std::istringstream iss(response);

    if
 (Json::parseFromStream(readerBuilder, iss, &root, &errors)) {
        if
 (root.isMember("choices") && root["choices"].isArray() && root["choices"].size() > 0) {
            return
 root["choices"][0]["message"]["content"].asString();
        }
    }

    return
 "";
}

callTTS 函数

  • 功能调用上文中Python语音合成工具 text_to_speech.exe,将文本转换为语音。

  • 参数:

    text:待合成的文本

    rate:语速(默认 200)

    volume:音量(默认 1.0)

  • 返回布尔值,表示语音合成是否成功。


    
     
    bool callTTS(const std::string& text, int rate = 200, float volume = 1.0){
    std::string command = "text_to_speech.exe \"" + text + "\" " + std::to_string(rate) + " " + std::to_string(volume);

    // 计算所需的宽字符缓冲区大小,使用 CP_ACP

    int
 wideLength = MultiByteToWideChar(CP_ACP, 0, command.c_str(), -1, nullptr, 0);
    if
 (wideLength == 0) {
        std::cerr << "计算宽字符缓冲区大小时出错,错误代码: " << GetLastError() << std::endl;
        return
 false;
    }

    // 分配宽字符缓冲区

    std::wstring wideCommand(wideLength, 0);

    // 进行实际的转换

    if
 (MultiByteToWideChar(CP_ACP, 0, command.c_str(), -1, &wideCommand[0], wideLength) == 0) {
        std::cerr << "执行多字节到宽字符转换时出错,错误代码: " << GetLastError() << std::endl;
        return
 false;
    }

    STARTUPINFOW si = { sizeof(si) };
    PROCESS_INFORMATION pi;

    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_HIDE; // 隐藏窗口

    // 创建新进程

    if
 (!CreateProcessW(NULL, const_cast<LPWSTR>(wideCommand.c_str()), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) {
        std::cerr << "执行语音转换时创建进程出错,错误代码: " << GetLastError() << std::endl;
        return
 false;
    }

    // 等待进程结束

    WaitForSingleObject
(pi.hProcess, INFINITE);

    // 关闭进程和线程句柄

    CloseHandle
(pi.hProcess);
    CloseHandle
(pi.hThread);

    return
 true;
}

08

最终显示效果

  • 使用OBS Studio进行rtmp推流

  • 编写一个简单的web当作观众端,发送内容到服务端

  • 使用vlc或ffplay进行rtmp拉流

09

应用与优化:挑战与实践经验

在完成从零到一的搭建之后,虚拟主播系统真正投入使用时,往往会遇到各种技术与场景挑战。下面结合实践经验,总结一些常见问题与优化思路。

1. 不同场景的差异化需求

  • 直播带货
    带货类虚拟主播需要语速更快、语调更有激情,以营造“紧迫感”。同时还要能实时识别观众的互动弹幕,在几秒内做出回应,否则容易丧失用户注意力。

  • 在线教育
    教育类场景强调知识传递的准确性与稳定性。虚拟主播需要更严谨的逻辑组织、较慢的语速,以及较少的口语化表达。

  • 虚拟偶像演出
    在娱乐和二次元文化中,虚拟偶像的粉丝更在意角色个性与情绪表现。因此,除了语言输出,还要结合丰富的表情、手势和舞台效果。

  • 企业客服
    客服场景要求 24 小时稳定运行,重点在于响应速度和信息准确,而不是外观或娱乐性。

不同场景的差异,决定了在构建虚拟主播时,需要对 模型参数设定、语音合成风格、场景渲染方式 做针对性调整。

2. 常见技术挑战与优化策略

  • 语音的情绪化不足

    问题:传统 pyttsx3 语音听感单一,容易给人“机器人朗读”的感觉。

    优化:

      引入 ChatTTS、VITS 等开源模型,支持“愤怒、开心、疑问”等情绪标签。

      •结合背景音乐与音效,弱化语音单调感。

  • 口型与表情匹配

    问题:仅用音量驱动口型,容易出现“张嘴大小一致”的僵硬效果。

    优化

      利用能量包络+ 频谱特征来驱动嘴型,模拟“元音/辅音”的差异。

      增加表情绑定,例如语音中检测到“疑问语气”,触发挑眉或歪头动作。

3. 部署与落地的经验

  • 硬件门槛:入门级方案仅需一台普通 PC

CPU:英特尔® 酷睿™ i7-6700处理器

显卡:NVIDIA GeForce GTX 960

内存:8GB

硬盘:固态硬盘500G

若要支持 1080p 高清推流和高并发 AI 生成,建议配置更好的电脑。

  • 网络环境:上行带宽至少 4Mbps,才能保证画面与音频同步稳定。

  • 成本评估:DeepSeek 模型调用成本相对较低,适合长期运行;现在用的是入门的key,导致返回速度比较慢,如果追求更强的多模态效果,可以考虑接入商用 API或其他大模型,但费用会更高。

  • 人性化小技巧

在 OBS 中为主播加上实时字幕,提升观众的可理解性。

使用虚拟声卡通道叠加背景音乐或音效,增强直播氛围。

4. 未来可扩展方向

  • 实时翻译:结合语音识别与机器翻译,主播可支持多语言观众互动。

  • 多角色互动:通过一个服务端管理多个虚拟角色,实现“AI 主播连麦PK”。

  • 动作捕捉融合:接入摄像头或动作捕捉设备,让虚拟主播拥有更丰富的肢体语言。

  • 情绪识别与反馈:通过分析弹幕情绪,主播能在合适的时机调整语气和表情,营造更强的互动感。

10

结语与展望

虚拟主播的核心竞争力,正在从“炫酷外观”转向“智能驱动”。

借助 DeepSeek 模型,我们能够构建一个具备自然对话能力、情感表达和实时交互的虚拟主播系统。

未来,多模态大模型的发展(语音、表情、动作、视频生成)将进一步提升沉浸感,让虚拟主播24小时都成为教育、娱乐、商业领域的 超级助理

11

参考资料

AI虚拟主播居然这么简单就做出来了?



【声明】内容源于网络
0
0
搜狐技术产品
这里是搜狐技术产品的知识分享平台。作为中国领先的互联网品牌,在拥有媒体、视频、搜索、游戏四大业务平台和超7亿用户的背后,搜狐始终致力于技术的创新与实践,更多实战干货和技术资讯将在此与您分享。
内容 1173
粉丝 0
搜狐技术产品 这里是搜狐技术产品的知识分享平台。作为中国领先的互联网品牌,在拥有媒体、视频、搜索、游戏四大业务平台和超7亿用户的背后,搜狐始终致力于技术的创新与实践,更多实战干货和技术资讯将在此与您分享。
总阅读167
粉丝0
内容1.2k