
LiveKit Agents 如何给语音 Agent 添加 LemonSlice 数字人并在通话中实时切换人物形象【免费下载链接】agentsA framework for building realtime voice AI agents ️项目地址: https://gitcode.com/GitHub_Trending/agen/agents如果你的语音 Agent 需要一张会动的“脸”LiveKit Agents 仓库的 avatar 示例 给出了完整做法用 LemonSlice 把一张静态图片做成说话的虚拟形象talking-head avatar并且支持通话中通过下拉框切换人物——Leila、Jess、软件工程师、猫娘、狐狸等 9 种 persona每次切换后 Agent 的脸、声音和性格都会改变而通话本身不断开。本文按这个示例梳理一条可执行路径准备凭证、创建 avatar 会话、接入 Agent再用 RPC 实现通话中实时换人。前提条件来自示例 README 与插件说明一个 LiveKit Cloud 项目提供LIVEKIT_API_KEY、LIVEKIT_API_SECRET、LIVEKIT_URL三个环境变量一个 LemonSlice API key从 lemonslice.com 获取导出为LEMONSLICE_API_KEY示例代码要求 Python 3.10 及以上见 examples/avatar/pyproject.toml核心依赖是livekit-agents1.6和livekit-plugins-lemonslice1.5.7。在仓库根目录执行uv sync --all-extras --dev # from the repository root uv run agent.py dev如果你只在自己的项目里单独引入插件而不跑示例按插件 README 安装即可pip install livekit-plugins-lemonslice创建 LemonSlice Avatar 会话插件核心是lemonslice.AvatarSession构造参数在 avatar.py 中定义agent_idLemonSlice 目录里的现成数字人、agent_image_url或agent_image要驱动的图片URL 或 PIL 图片、agent_prompt/agent_idle_prompt说话与空闲时的肢体语言提示发给 LemonSlice 的agent_prompt/agent_idle_prompt、idle_timeout、api_key等。examples/avatar/agent.py 中的实际用法def make_avatar(p: Persona) - lemonslice.AvatarSession: return lemonslice.AvatarSession( agent_image_urlp.image_url, agent_promptp.speaking_prompt, agent_idle_promptp.idle_prompt, idle_timeout120, response_done_timeout2, )每个 persona 的image_url是 LemonSlice 要驱动的图片speaking_prompt/idle_prompt是简短的肢体语言提示这些值都定义在 personas.py 里。启动会话时调用start()并等待数字人加入房间avatar make_avatar(initial) session_id await avatar.start(session, roomctx.room) await state.avatar.wait_for_join()注意start()会校验 LiveKit 凭证livekit_url、livekit_api_key、livekit_api_secret必须通过参数传入或来自环境变量否则抛出LemonSliceException。所以本地运行前先把三个LIVEKIT_*变量配好。把 Avatar 接入 Agent 会话示例的 Agent 侧管线用 LiveKit Inference 配置见 agent.pysession AgentSession( sttinference.STT(deepgram/nova-3), llminference.LLM(google/gemini-3.5-flash), turn_handlingTurnHandlingOptions( interruption{resume_false_interruption: False}, ), )Agent 的 TTS 使用inference.TTS(cartesia/sonic-3.5, voicepersona.voice_id)——每个 persona 有自己独立的 Cartesia 声音 id。avatar 会话启动后await session.start(agentmake_agent(initial), roomctx.room)初始 persona 从 job metadata 读取meta json.loads(ctx.job.metadata) if ctx.job.metadata else {} initial resolve_persona(meta.get(set_avatar))如果连接方没有发送 metadataresolve_persona会回落到DEFAULT_PERSONA_ID leila即默认以 Leila 形象开场服务器日志会输出starting session with persona leila。通话中实时切换人物形象切换由前端触发playground 下拉框变化时调用 Agent 注册的set_avatarRPCpayload 为{value: persona_id}。agent.py 中的实现流程是播放一段短等待音hold_music.py 的三音“请稍候”提示通过BackgroundAudioPlayer播放关闭当前 avatar 会话await state.avatar.aclose()用新 persona 的图片和肢体语言提示创建新会话并start再wait_for_join()切换 TTS 声音和系统提示词session.update_agent(make_agent(new_persona))让新 persona 以角色身份开口打招呼session.generate_reply(...)。README 总结为“No reconnect, no page refresh — the same call, with a different face”整个通话不断线只在数字人重连期间听到等待音。几个值得保留的细节switch_lockasyncio.Lock防止并发切换上一次切换还没完成时再次调用会收到RpcError错误信息是 “Still switching to the previous persona, please try again in a moment.”如果选中的是同一个 personaRPC 直接返回当前 id不重建会话新会话wait_for_join之后还有一段await asyncio.sleep(1.2)代码注释说明原因LemonSlice 的视频管线在 join 后需要一点时间才会真正消费音频并开始出帧。RPC 成功时返回{id: persona_id}可作为切换完成的判断依据。切换过程中服务器日志会记录switching persona: old - new。添加或修改 persona所有 persona 集中在 personas.py 的PERSONAS字典里。每条Persona包含id、name、image_url、voice_id、system_prompt这个角色的性格以及speaking_prompt/idle_prompt肢体语言提示。compose_instructions会把 persona 提示词和共享的COMMON_INSTRUCTIONS口语化短句、不用 markdown、只说英文等全局规则拼成最终系统提示。新增 persona 的步骤在PERSONAS字典中追加一个Persona(...)条目如果你使用 playground UI还要同步更新 examples/playground.yamlREADME 说明 UI 会在该文件更新后自动发现新 persona。另外Leila、Jess 和 Mr Fox 三个 hero persona 还支持 LLM 通过工具调用触发挥手、跳舞、转身动作一次一个动作约 6 秒会话开始时会自动挥一次手这部分逻辑在 actions.py。可选分支通过 LiveKit Inference 开通道免 LemonSlice 密钥inference_agent.py 是同一思路的极简变体不直接用 BYOK 的 LemonSlice 插件而是让 Inference 网关用 LiveKit 自己的批发密钥创建 LemonSlice 会话因此不需要LEMONSLICE_API_KEYAgent 只用 LiveKit 凭证认证。使用条件与命令你的项目需要开启avatar_lemonslicefeature flag未开启时网关返回 HTTP 403 “Inference Avatar is not enabled for this project”设置LIVEKIT_URL、LIVEKIT_API_KEY、LIVEKIT_API_SECRET以及要驱动的图片地址LEMONSLICE_IMAGE_URL未设置时直接抛ValueError运行uv run inference_agent.py dev。核心代码avatar inference.AvatarSession( lemonslice, extra_kwargsinference.LemonSliceOptions( image_urlavatar_image_url, promptBe expressive in your movements and use your hands while talking., ), ) await avatar.start(session, roomctx.room) await avatar.wait_for_join()如果不用自定义图片而是在模型串里传 LemonSlice 目录中的现成 agent idinference.AvatarSession(lemonslice/agent_id, ...)并去掉image_url两者互斥。该变体只创建单个固定形象不包含 persona 切换 RPC要实时换人仍以主路径的agent.py为准。运行后如何验证启动后从任意 LiveKit 客户端连接或在 LiveKit Playground 中选择 avatar 示例README 中的入口Agent 应以默认 persona Leila 的形象入场并主动打招呼在下拉框选择其他 persona 时先听到短等待音随后画面切换为新角色的脸声音和说话风格同时变化新角色用一句话确认自己是谁通话不中断服务器日志出现starting session with persona id与switching persona: old - new可作为状态变化的核对依据若走 Inference 变体且未开启 feature flag看到 403 “Inference Avatar is not enabled for this project” 就说明项目上还没开avatar_lemonslice开关而不是代码问题。限制与边界默认 persona 固定为 Leila未发送 job metadata 时不会随机选择形象同一个 persona 的重复切换不会重建会话并发切换会被 RPC 拒绝需要稍等重试挥手/跳舞/转身动作只对 Leila、Jess、Mr Fox 生效supports_actions判定其他 persona 的 Agent 不注册这些工具插件start()对 LiveKit 凭证缺失会直接抛错排查“会话起不来”时先确认LIVEKIT_URL、LIVEKIT_API_KEY、LIVEKIT_API_SECRET已设置。想继续深入时可直接阅读 examples/avatar/agent.py 中set_avatarRPC 的完整实现和 livekit-plugins-lemonslice 的AvatarSession接口定义agent_participant_identity、api_url、api_key等可覆写项。【免费下载链接】agentsA framework for building realtime voice AI agents ️项目地址: https://gitcode.com/GitHub_Trending/agen/agents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考