Virtual Avatar Models Overview

参照元: LiveKit Agents Documentation ロードマップ: 学習ロードマップ

What(何についてか)

バーチャルアバターは、音声AIエージェントに「顔のある動画出力」を追加する。音声だけでなく、口の動きや表情が同期した映像を配信できる。AgentSessionの音声出力をAvatarSessionが受け取り、同期された音声+動画としてRoomにpublishする仕組み。

Why(なぜ必要か)

音声のみのエージェントより、視覚的なプレゼンスがある方がユーザー体験が向上する。カスタマーサポート、バーチャルアシスタント、教育などのユースケースで需要がある。動画の口の動きが音声と同期するため、自然な対話感を演出できる。

How(どう動くか)

AgentSessionにAvatarSessionを組み合わせる。avatar.start(session, room=ctx.room) を呼ぶと、AvatarSessionがAgentSessionの音声出力を内部でフックし、Roomへの直接publishを止めて代わりにAvatar Workerに送るよう切り替える。開発者が明示的に音声無効化を設定する必要はない。

from livekit import agents
from livekit.agents import AgentServer, AgentSession
from livekit.plugins import hedra
 
server = AgentServer()
 
@server.rtc_session(agent_name="my-agent")
async def my_agent(ctx: agents.JobContext):
    session = AgentSession(
        # ... stt, llm, tts, etc.
    )
    avatar = hedra.AvatarSession(
        avatar_id="...",
    )
    # AvatarSessionがAgentSessionの音声出力をフック
    await avatar.start(session, room=ctx.room)
    # 通常通りstart。音声は自動的にAvatar Workerに送られる
    await session.start(
        # ... room, agent, room_options, etc.
    )

対応プラグイン

12のプロバイダーがPlugin形式で対応。Inference対応はない。

Python/Node.js両対応: Anam, Beyond Presence, Hedra, LemonSlice, TruGen。 Pythonのみ: Avatario, AvatarTalk, bitHuman, Keyframe, LiveAvatar, Simli, Tavus。

2参加者モデル(Avatar Workers)

アバタープロバイダーはRoomに別参加者(Avatar Worker)として直接参加し、同期された音声+動画トラックをpublishする。これによりレイテンシを最小化している。

graph TD
    A["Agent<br/>Pythonプロセス<br/>publish_on_behalf: null"] -->|"音声を送る"| B["Avatar Worker<br/>プロバイダーサーバー<br/>publish_on_behalf: agent.identity"]
    B -->|"同期された<br/>audio + video"| C["Room"]
    C --> D["User Frontend"]

Agent側は音声を直接Roomにpublishせず、Avatar Workerに送る。Avatar Workerが音声を受け取って口の動きを同期した動画を生成し、Roomにpublishする。

フロントエンド側の識別

Room内にはAgentとAvatar Workerの2つの参加者がいる。Avatar Workerは kind: "agent"lk.publish_on_behalf 属性に元のAgentのidentityが設定されている。この属性で両者を識別する。

バニラJSの場合:

const agent = room.remoteParticipants.find(
  p => p.kind === Kind.Agent && p.attributes['lk.publish_on_behalf'] === null
);
const avatarWorker = room.remoteParticipants.find(
  p => p.kind === Kind.Agent && p.attributes['lk.publish_on_behalf'] === agent.identity
);

Reactの場合は useVoiceAssistant フックが自動で正しいトラックを取得する:

const { agent, audioTrack, videoTrack } = useVoiceAssistant();

フロントエンドスターターアプリ

アバター対応のスターターアプリが用意されている。SwiftUI(iOS/macOS/visionOS)、Next.js(Web)、Flutter、React Native、Android(Kotlin)、Agents Playground(テスト用)。

実装時の判断軸

アバター導入時は以下の順で進める。まずプロバイダーを選び(対応プラットフォームと品質で判断)、AvatarSessionをAgentSessionに組み込み、フロントエンドでAvatar Workerを識別して描画する。avatar.start() が音声ルーティングの切り替えを透過的に処理するため、開発者はセッションの開始順序以外で意識すべきことは少ない。