在 LiveKit Agents 中接入 Protoface 虚拟人形象:livekit-plugins-protoface 插件安装、配置与源码解析 在 LiveKit Agents 中接入 Protoface 虚拟人形象livekit-plugins-protoface 插件安装、配置与源码解析【免费下载链接】agentsA framework for building realtime voice AI agents ️项目地址: https://gitcode.com/GitHub_Trending/agen/agents导读本文围绕 livekit-plugins-protoface 插件系统讲解如何在 LiveKit Agents 实时语音 AI 应用中将对话语音输出路由到 Protoface 云端托管的虚拟人virtual avatar实现语音 虚拟形象的实时交互体验。读完本文你将掌握该插件的安装方式、环境变量与参数配置、会话生命周期管理并通过源码理解其与 LiveKit 房间、音频数据流、Worker Token 鉴权之间的底层协作机制。插件定位为 LiveKit Agents 增加虚拟人形象能力Protoface 是一个提供云端托管虚拟人形象的服务商。livekit-plugins-protoface是 LiveKit Agents 生态中的官方插件它把 Protoface 的会话 API 封装成一个与 LiveKit 原生AvatarSession抽象兼容的会话对象让开发者无需关心托管端的接入细节即可把 Agent 的 TTS 音频输出转交给 Protoface 渲染的虚拟人并通过 LiveKit 房间发布为视频与音频轨。从 pyproject.toml 可以看到该插件的关键元数据如下包名livekit-plugins-protoface当前版本1.8.0定义于 version.py依赖livekit-agents1.8.0运行环境Python3.10许可证Apache-2.0插件在导入时即完成注册__init__.py中定义了继承自livekit.agents.Plugin的ProtofacePlugin类并调用Plugin.register_plugin(ProtofacePlugin())挂载到 LiveKit Agents 的插件体系中同时对外导出DEFAULT_STOCK_AVATAR_ID、AvatarSession、ProtofaceException和__version__。安装使用 pip 直接安装即可pip install livekit-plugins-protoface由于插件依赖livekit-agents1.8.0安装器会自动拉取满足版本要求的 livekit-agents 框架。建议在虚拟环境如 uv、venv、poetry中进行安装避免与系统级 Python 环境互相污染。前置条件API Key 与必要环境变量使用该插件前你需要先从 Protoface 申请 API Key。插件支持两种提供方式通过环境变量PROTOFACE_API_KEY设置推荐在创建AvatarSession或ProtofaceAPI时通过api_key参数显式传入。从 api.py 的源码可以看到ProtofaceAPI的构造函数会优先使用显式传入的api_key否则回退读取PROTOFACE_API_KEY环境变量两者都缺失时直接抛出ProtofaceExceptionself._api_key _resolve_optional_string(api_key, PROTOFACE_API_KEY) if not self._api_key: raise ProtofaceException( api_key must be set by passing it to ProtofaceAPI or setting the PROTOFACE_API_KEY environment variable )除 API Key 外AvatarSession.start()在接入 LiveKit 房间时还需要 LiveKit 服务器的连接凭据缺失同样会抛出ProtofaceException见 avatar.py。插件涉及的环境变量汇总如下环境变量用途默认值PROTOFACE_API_KEYProtoface API Key创建会话时的鉴权凭据无必填PROTOFACE_API_URLProtoface API 基础地址便于自建代理或测试环境https://api.protoface.com定义于 api.pyLIVEKIT_URLLiveKit 服务器 WebSocket 地址Protoface 托管端据此加入房间无start()时必填LIVEKIT_API_KEYLiveKit API Key用于签发 Worker Token无start()时必填LIVEKIT_API_SECRETLiveKit API Secret用于签发 Worker Token无start()时必填核心用法创建并启动 AvatarSession插件对外最核心的类是AvatarSession它继承自 LiveKit Agents 语音模块中的抽象基类AvatarSession定义于 livekit-agents/livekit/agents/voice/avatar/_types.py因此可以与其他虚拟人插件以相同的方式集成进 Agent 会话。构造函数参数从 avatar.py 可以看到构造函数支持的参数参数类型默认值说明avatar_idstrav_stock_001要渲染的 Protoface 虚拟人 ID常量DEFAULT_STOCK_AVATAR_ID即av_stock_001api_keystr \| NoneNOT_GIVENProtoface API Key未传则读取PROTOFACE_API_KEYapi_urlstr \| NoneNOT_GIVENAPI 基础地址未传则读取PROTOFACE_API_URL再回退到官方默认地址max_duration_secondsint \| NoneNOT_GIVEN会话最大时长秒Protoface 会取该值与账户套餐上限中较小者avatar_participant_identitystr \| NoneNOT_GIVEN虚拟人在 LiveKit 房间中的参与者身份默认protoface-avatar-agentavatar_participant_namestr \| NoneNOT_GIVEN虚拟人参与者的显示名称默认protoface-avatar-agentconn_optionsAPIConnectOptionsDEFAULT_API_CONNECT_OPTIONSProtoface API 请求的超时与重试配置一个典型的创建方式from livekit.plugins.protoface import AvatarSession avatar AvatarSession( avatar_idav_stock_001, max_duration_seconds600, )启动会话在 Agent 的 Job 入口中将已连接的房间和AgentSession传给start()await avatar.start(agent_session, room)start()内部完成四件事见 avatar.py校验单次启动同一个AvatarSession实例只能启动一次重复调用会抛出RuntimeError(AvatarSession.start() called twice; create a new AvatarSession.)解析 LiveKit 凭据依次使用参数值或LIVEKIT_URL/LIVEKIT_API_KEY/LIVEKIT_API_SECRET环境变量任一缺失即抛ProtofaceException创建托管会话调用 Protoface 的POST /v1/sessions接口携带avatar_id与transport配置详见下文并记录返回的session_id接管音频输出通过agent_session.output.replace_audio_tail(...)把 Agent 的音频输出替换为发往虚拟人的DataStreamAudioOutput。Transport 配置托管端如何加入 LiveKit 房间start()构造的 transport 对象完整展示了 Protoface 托管端与 LiveKit 房间的连接方式transport { type: livekit, url: livekit_url_value, room_name: room.name, worker_token: worker_token, worker_identity: self._avatar_participant_identity, audio_source: data_stream, }type固定为livekit表示托管端以 LiveKit 参与者身份接入room_name即当前 Agent Job 所在的房间名worker_token是插件为本会话临时签发的 JWT见下文audio_source固定为data_stream与 LiveKit Agents 的DataStreamAudioOutput一一对应。底层 API 客户端ProtofaceAPI插件在 api.py 中实现了一个基于aiohttp的异步客户端ProtofaceAPIAvatarSession的所有 HTTP 交互都经由它完成start_session(avatar_id, transport, max_duration_seconds)发起POST /v1/sessions请求体为{avatar_id: ..., transport: ..., max_duration_seconds: ...}仅当显式传入时长时才携带该字段end_session(session_id)发起POST /v1/sessions/{session_id}/end用于优雅结束托管会话。所有请求都会携带以下请求头{ Authorization: fBearer {self._api_key}, User-Agent: livekit-plugins-protoface/{__version__}, Accept: application/json, }超时与重试机制客户端内置了与 LiveKit Agents 一致的错误分级与重试策略api.py超时asyncio.TimeoutError映射为APITimeoutError网络错误aiohttp.ClientError映射为APIConnectionError服务端错误非 2xx 响应映射为APIStatusError其中retryableFalse的错误如非对象 JSON 响应立即抛出、不重试重试总尝试次数为conn_options.max_retry 1重试间隔通过conn_options._interval_for_retry(attempt)计算指数退避全部重试失败后统一抛出APIConnectionError。start_session()返回的响应中必须包含字符串类型的id字段否则AvatarSession.start()会抛出ProtofaceException(Protoface API response missing session id)。音频路由把 TTS 输出喂给虚拟人插件接入虚拟人的关键一步是把 Agent 的 TTS 音频输出替换为发给 Protoface 参与者的数据流。相关实现位于 avatar.pyagent_session.output.replace_audio_tail( DataStreamAudioOutput( roomroom, destination_identityself._avatar_participant_identity, sample_rateSAMPLE_RATE, wait_remote_trackrtc.TrackKind.KIND_VIDEO, ), )其中DataStreamAudioOutput是 LiveKit Agents 语音模块提供的音频输出实现定义于 livekit-agents/livekit/agents/voice/avatar/_datastream_io.py它会把 Agent 生成的音频以数据流形式发送给房间内指定身份的参与者。需要注意两个细节采样率固定为 16 kHzSAMPLE_RATE 16000见 avatar.pywait_remote_trackrtc.TrackKind.KIND_VIDEO表示等待虚拟人的视频轨就绪确保虚拟人真正出现在房间后才开始推流音频避免只闻其声、不见其人。Worker Token 签发与安全边界为了让 Protoface 托管端能够以受控身份加入房间插件在本地用 LiveKit 凭据签发一个短期 JWTavatar.py。签发逻辑要点参与者身份来源优先取get_job_context()中 Agent 的本地参与者身份其次取已连接房间的room.local_participant.identity两者都不可用时抛ProtofaceExceptionToken 类型with_kind(agent)即按 Agent 类型参与者签发权限范围VideoGrants(room_joinTrue, room房间名, can_publishTrue, can_subscribeTrue, can_publish_dataTrue)最小化地覆盖发布音视频轨与订阅房间数据所需的能力身份与属性携带虚拟人参与者的identity、name并通过with_attributes({ATTRIBUTE_PUBLISH_ON_BEHALF: 本地参与者身份})标注该参与者是代表本地 Agent 发布轨道的便于在房间中建立归属关系。会话结束与资源释放AvatarSession.aclose()avatar.py负责优雅关闭记录当前session_id并将其置空防止重复关闭调用ProtofaceAPI.end_session(session_id)请求 Protoface 端优雅结束托管会话若调用失败仅记录告警日志不阻断本地清理委托基类super().aclose()释放 LiveKit 侧的资源数据流、房间监听等。从基类实现livekit-agents/livekit/agents/voice/avatar/_types.py可以看到AvatarSession.start()在 Job 上下文内会自动注册aclose作为关闭回调若在 Job 上下文之外使用则需要手动调用aclose()释放资源。此外基类还定义了插件需要实现的抽象契约avatar_identity虚拟人参与者标识与provider供应商名称本插件返回protoface并通过rtc.EventEmitter支持metrics_collected等事件订阅。异常体系速查插件定义了独立的异常类型 errors.pyProtofaceException配置或协议层面的错误例如缺少 API Key、缺少 LiveKit 凭据、Protoface 响应缺少session id、无法获取本地参与者身份、重复调用start()后者以RuntimeError抛出网络/服务端错误复用 LiveKit Agents 的APIConnectionError、APITimeoutError、APIStatusError并遵循统一的重试语义。调试时可通过日志定位问题插件日志以livekit.plugins.protoface为 logger 名输出见 log.py会话创建成功与结束失败等关键事件均记录有session_id与avatar_id。常见问题排查清单启动即报ProtofaceException: api_key must be set...确认已设置PROTOFACE_API_KEY环境变量或在构造AvatarSession(api_key...)时显式传入start()报缺少 LiveKit 凭据确认已设置LIVEKIT_URL、LIVEKIT_API_KEY、LIVEKIT_API_SECRET三者且 Agent 端与托管端能访问同一 LiveKit 服务器RuntimeError: AvatarSession.start() called twice一个实例只能启动一次会话结束后如需重启请新建AvatarSession房间中看不到虚拟人检查avatar_id是否有效以及 Protoface 账户套餐是否允许当前会话时长max_duration_seconds取配置值与套餐上限的较小者需要自定义 API 地址如私有部署或代理设置PROTOFACE_API_URL环境变量即可覆盖默认的https://api.protoface.com。小结livekit-plugins-protoface是一个轻量而完整的 LiveKit Agents 虚拟人插件安装一条命令、配置一个环境变量即可接入AvatarSession在启动时自动完成托管会话创建、Worker Token 签发与音频流接管。透过源码可以看到它与 LiveKit Agents 的AvatarSession抽象、DataStreamAudioOutput音频通道以及统一的 API 错误重试体系深度集成为实时语音 Agent 增加可见的虚拟形象提供了可靠的落地路径。【免费下载链接】agentsA framework for building realtime voice AI agents ️项目地址: https://gitcode.com/GitHub_Trending/agen/agents创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考