Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def __init__(
api_key: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_identity: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_name: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_attributes: NotGivenOr[dict[str, str]] = NOT_GIVEN,
conn_options: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,
) -> None:
self._http_session: aiohttp.ClientSession | None = None
Expand All @@ -58,6 +59,16 @@ def __init__(
self._api_url = api_url_val
self._api_key = api_key_val

job_ctx = get_job_context()
local_participant_identity = job_ctx.local_participant_identity
attributes = {
ATTRIBUTE_PUBLISH_ON_BEHALF: local_participant_identity # allow the avatar agent to publish audio and video on behalf of your local agent
}
if utils.is_given(avatar_participant_attributes):
attributes.update(avatar_participant_attributes)

self._avatar_participant_attributes = attributes

def _ensure_http_session(self) -> aiohttp.ClientSession:
if self._http_session is None:
self._http_session = utils.http_context.http_session()
Expand All @@ -82,8 +93,6 @@ async def start(
"by arguments or environment variables"
)

job_ctx = get_job_context()
local_participant_identity = job_ctx.local_participant_identity
livekit_token = (
api.AccessToken(
api_key=livekit_api_key,
Expand All @@ -93,8 +102,7 @@ async def start(
.with_identity(self._avatar_participant_identity)
.with_name(self._avatar_participant_name)
.with_grants(api.VideoGrants(room_join=True, room=room.name))
# allow the avatar agent to publish audio and video on behalf of your local agent
.with_attributes({ATTRIBUTE_PUBLISH_ON_BEHALF: local_participant_identity})
.with_attributes(self._avatar_participant_attributes)
.to_jwt()
)
async with AnamAPI(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ def __init__(
api_key: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_identity: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_name: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_attributes: NotGivenOr[dict[str, str]] = NOT_GIVEN,
conn_options: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,
) -> None:
"""
Expand All @@ -61,6 +62,7 @@ def __init__(
join the room. Defaults to "avatario-avatar-agent"
avatar_participant_name: Name of the avatario participant that will join the
room. Defaults to "avatario-avatar-agent"
avatar_participant_attributes: avatario participant attributes
conn_options: Connection options for the aiohttp session.
"""
self._http_session: aiohttp.ClientSession | None = None
Expand Down Expand Up @@ -91,6 +93,16 @@ def __init__(
else _AVATAR_AGENT_NAME
)

job_ctx = get_job_context()
self._local_participant_identity = job_ctx.local_participant_identity
attributes = {
ATTRIBUTE_PUBLISH_ON_BEHALF: self._local_participant_identity # allow the avatar agent to publish audio and video on behalf of your local agent
}
if utils.is_given(avatar_participant_attributes):
attributes.update(avatar_participant_attributes)

self._avatar_participant_attributes = attributes

def _ensure_http_session(self) -> aiohttp.ClientSession:
if self._http_session is None:
self._http_session = utils.http_context.http_session()
Expand All @@ -115,16 +127,13 @@ async def start(
"livekit_url, livekit_api_key, and livekit_api_secret must be set "
"by arguments or environment variables"
)
job_ctx = get_job_context()
local_participant_identity = job_ctx.local_participant_identity
livekit_token = (
api.AccessToken(api_key=livekit_api_key, api_secret=livekit_api_secret)
.with_kind("agent")
.with_identity(self._avatar_participant_identity)
.with_name(self._avatar_participant_name)
.with_grants(api.VideoGrants(room_join=True, room=room.name))
# allow the avatar agent to publish audio and video on behalf of your local agent
.with_attributes({ATTRIBUTE_PUBLISH_ON_BEHALF: local_participant_identity})
.with_attributes(self._avatar_participant_attributes)
.to_jwt()
)

Expand All @@ -136,7 +145,7 @@ async def start(
) as avatario_api:
logger.debug("starting avatar session")
await avatario_api.start_session(
livekit_agent_identity=local_participant_identity,
livekit_agent_identity=self._local_participant_identity,
properties={
"url": livekit_url,
"token": livekit_token,
Expand Down
15 changes: 12 additions & 3 deletions livekit-plugins/livekit-plugins-bey/livekit/plugins/bey/avatar.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ def __init__(
api_key: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_identity: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_name: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_attributes: NotGivenOr[dict[str, str]] = NOT_GIVEN,
conn_options: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,
) -> None:
self._avatar_id = avatar_id or EGE_STOCK_AVATAR_ID
Expand All @@ -60,6 +61,16 @@ def __init__(
self._http_session: aiohttp.ClientSession | None = None
self._conn_options = conn_options

job_ctx = get_job_context()
local_participant_identity = job_ctx.local_participant_identity
attributes = {
ATTRIBUTE_PUBLISH_ON_BEHALF: local_participant_identity # allow the avatar agent to publish audio and video on behalf of your local agent
}
if utils.is_given(avatar_participant_attributes):
attributes.update(avatar_participant_attributes)

self._avatar_participant_attributes = attributes

def _ensure_http_session(self) -> aiohttp.ClientSession:
if self._http_session is None:
self._http_session = utils.http_context.http_session()
Expand All @@ -84,16 +95,14 @@ async def start(
"by arguments or environment variables"
)

job_ctx = get_job_context()
local_participant_identity = job_ctx.local_participant_identity
livekit_token = (
api.AccessToken(api_key=livekit_api_key, api_secret=livekit_api_secret)
.with_kind("agent")
.with_identity(self._avatar_participant_identity)
.with_name(self._avatar_participant_name)
.with_grants(api.VideoGrants(room_join=True, room=room.name))
# allow the avatar agent to publish audio and video on behalf of your local agent
.with_attributes({ATTRIBUTE_PUBLISH_ON_BEHALF: local_participant_identity})
.with_attributes(self._avatar_participant_attributes)
.to_jwt()
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ def __init__(
conn_options: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,
avatar_participant_identity: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_name: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_attributes: NotGivenOr[dict[str, str]] = NOT_GIVEN,
) -> None:
"""
Initialize a BitHuman avatar session.
Expand Down Expand Up @@ -168,6 +169,7 @@ def __init__(
self._avatar_id = avatar_id
self._avatar_participant_identity = avatar_participant_identity or _AVATAR_AGENT_IDENTITY
self._avatar_participant_name = avatar_participant_name or _AVATAR_AGENT_NAME
self._avatar_participant_attributes = avatar_participant_attributes

# set default mode based on model_path, avatar_image or avatar_id presence
self._mode = (
Expand Down Expand Up @@ -315,6 +317,9 @@ async def _start_cloud(
ATTRIBUTE_PUBLISH_ON_BEHALF: local_participant_identity,
}

if utils.is_given(self._avatar_participant_attributes):
attributes.update(self._avatar_participant_attributes)

# Only add api_secret if it's not None
if self._api_secret is not None:
attributes["api_secret"] = self._api_secret
Expand Down
13 changes: 10 additions & 3 deletions livekit-plugins/livekit-plugins-did/livekit/plugins/did/avatar.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ def __init__(
avatar_participant_identity: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_name: NotGivenOr[str] = NOT_GIVEN,
conn_options: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,
avatar_participant_attributes: NotGivenOr[dict[str, str]] = NOT_GIVEN,
) -> None:
self._http_session: aiohttp.ClientSession | None = None
self._conn_options = conn_options
Expand All @@ -64,6 +65,14 @@ def __init__(
else _AVATAR_AGENT_NAME
)

job_ctx = get_job_context()
local_participant_identity = job_ctx.local_participant_identity
attributes = {ATTRIBUTE_PUBLISH_ON_BEHALF: local_participant_identity}
if utils.is_given(avatar_participant_attributes):
attributes.update(avatar_participant_attributes)

self._avatar_participant_attributes = attributes

def _ensure_http_session(self) -> aiohttp.ClientSession:
if self._http_session is None:
self._http_session = utils.http_context.http_session()
Expand Down Expand Up @@ -94,15 +103,13 @@ async def start(
"by arguments or environment variables"
)

job_ctx = get_job_context()
local_participant_identity = job_ctx.local_participant_identity
livekit_token = (
api.AccessToken(api_key=_livekit_api_key, api_secret=_livekit_api_secret)
.with_kind("agent")
.with_identity(self._avatar_participant_identity)
.with_name(self._avatar_participant_name)
.with_grants(api.VideoGrants(room_join=True, room=room.name))
.with_attributes({ATTRIBUTE_PUBLISH_ON_BEHALF: local_participant_identity})
.with_attributes(self._avatar_participant_attributes)
.to_jwt()
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ def __init__(
api_key: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_identity: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_name: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_attributes: NotGivenOr[dict[str, str]] = NOT_GIVEN,
conn_options: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,
) -> None:
self._room: rtc.Room | None = None
Expand Down Expand Up @@ -80,6 +81,14 @@ def __init__(
self._api_url = api_url_val
self._api_key = api_key_val

job_ctx = get_job_context()
self._local_participant_identity = job_ctx.local_participant_identity
attributes = {ATTRIBUTE_PUBLISH_ON_BEHALF: self._local_participant_identity}
if utils.is_given(avatar_participant_attributes):
attributes.update(avatar_participant_attributes)

self._avatar_participant_attributes = attributes

async def start(
self,
agent_session: AgentSession,
Expand All @@ -98,9 +107,6 @@ async def start(
"by arguments or environment variables"
)

job_ctx = get_job_context()
local_participant_identity = job_ctx.local_participant_identity

# Mint a LiveKit token for the avatar worker with publish_on_behalf
livekit_token = (
api.AccessToken(
Expand All @@ -118,7 +124,7 @@ async def start(
can_subscribe=True,
)
)
.with_attributes({ATTRIBUTE_PUBLISH_ON_BEHALF: local_participant_identity})
.with_attributes(self._avatar_participant_attributes)
.to_jwt()
)

Expand All @@ -134,7 +140,7 @@ async def start(
room_name=room.name,
livekit_url=livekit_url,
livekit_token=livekit_token,
source_participant_identity=local_participant_identity,
source_participant_identity=self._local_participant_identity,
)
logger.debug(
"Keyframe plugin session created: reservation_id=%s",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
APIConnectOptions,
NotGivenOr,
get_job_context,
utils,
)
from livekit.agents.voice.avatar import DataStreamAudioOutput
from livekit.agents.voice.room_io import ATTRIBUTE_PUBLISH_ON_BEHALF
Expand All @@ -39,6 +40,7 @@ def __init__(
api_key: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_identity: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_name: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_attributes: NotGivenOr[dict[str, str]] = NOT_GIVEN,
conn_options: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,
**kwargs: Any,
) -> None:
Expand All @@ -56,6 +58,14 @@ def __init__(
self._avatar_participant_identity = avatar_participant_identity or _AVATAR_AGENT_IDENTITY
self._avatar_participant_name = avatar_participant_name or _AVATAR_AGENT_NAME

job_ctx = get_job_context()
local_participant_identity = job_ctx.local_participant_identity
attributes = {ATTRIBUTE_PUBLISH_ON_BEHALF: local_participant_identity}
if utils.is_given(avatar_participant_attributes):
attributes.update(avatar_participant_attributes)

self._avatar_participant_attributes = attributes

async def start(
self,
agent_session: AgentSession,
Expand All @@ -74,16 +84,14 @@ async def start(
"by arguments or environment variables"
)

job_ctx = get_job_context()
local_participant_identity = job_ctx.local_participant_identity
livekit_token = (
api.AccessToken(api_key=livekit_api_key, api_secret=livekit_api_secret)
.with_kind("agent")
.with_identity(self._avatar_participant_identity)
.with_name(self._avatar_participant_name)
.with_grants(api.VideoGrants(room_join=True, room=room.name))
# allow the avatar agent to publish audio and video on behalf of your local agent
.with_attributes({ATTRIBUTE_PUBLISH_ON_BEHALF: local_participant_identity})
.with_attributes(self._avatar_participant_attributes)
.to_jwt()
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def __init__(
is_sandbox: NotGivenOr[bool] = NOT_GIVEN,
avatar_participant_identity: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_name: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_attributes: NotGivenOr[dict[str, str]] = NOT_GIVEN,
conn_options: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,
) -> None:
self._avatar_id = avatar_id if is_given(avatar_id) else os.getenv("LIVEAVATAR_AVATAR_ID")
Expand Down Expand Up @@ -79,6 +80,7 @@ def __init__(
self._playback_position = 0.0
self._session_connected = asyncio.Event()
self._chunk_interrupted = asyncio.Event()
self._avatar_participant_attributes = avatar_participant_attributes

async def start(
self,
Expand Down Expand Up @@ -107,6 +109,10 @@ async def start(
raise LiveAvatarException("failed to get local participant identity") from e
self._local_participant_identity = room.local_participant.identity

attributes = {ATTRIBUTE_PUBLISH_ON_BEHALF: self._local_participant_identity}
if is_given(self._avatar_participant_attributes):
attributes.update(self._avatar_participant_attributes)

livekit_token = (
api.AccessToken(
api_key=livekit_api_key,
Expand All @@ -116,7 +122,7 @@ async def start(
.with_identity(self._avatar_participant_identity)
.with_name(self._avatar_participant_name)
.with_grants(api.VideoGrants(room_join=True, room=self._room.name))
.with_attributes({ATTRIBUTE_PUBLISH_ON_BEHALF: self._local_participant_identity})
.with_attributes(attributes)
.to_jwt()
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ def __init__(
api_url: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_identity: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_name: NotGivenOr[str] = NOT_GIVEN,
avatar_participant_attributes: NotGivenOr[dict[str, str]] = NOT_GIVEN,
) -> None:
self._http_session: aiohttp.ClientSession | None = None
self.conversation_id: str | None = None
Expand All @@ -75,6 +76,16 @@ def __init__(
self._avatar_participant_name = avatar_participant_name or _AVATAR_AGENT_NAME
self._ensure_http_session()

job_ctx = get_job_context()
local_participant_identity = job_ctx.local_participant_identity
attributes = {
ATTRIBUTE_PUBLISH_ON_BEHALF: local_participant_identity # allow the avatar agent to publish audio and video on behalf of your local agent
}
if utils.is_given(avatar_participant_attributes):
attributes.update(avatar_participant_attributes)

self._avatar_participant_attributes = attributes

def _ensure_http_session(self) -> aiohttp.ClientSession:
if self._http_session is None:
self._http_session = utils.http_context.http_session()
Expand All @@ -99,16 +110,13 @@ async def start(
"by arguments or environment variables"
)

job_ctx = get_job_context()
local_participant_identity = job_ctx.local_participant_identity
livekit_token = (
api.AccessToken(api_key=livekit_api_key, api_secret=livekit_api_secret)
.with_kind("agent")
.with_identity(self._avatar_participant_identity)
.with_name(self._avatar_participant_name)
.with_grants(api.VideoGrants(room_join=True, room=room.name))
# allow the avatar agent to publish audio and video on behalf of your local agent
.with_attributes({ATTRIBUTE_PUBLISH_ON_BEHALF: local_participant_identity})
.with_attributes(self._avatar_participant_attributes)
.to_jwt()
)

Expand Down
Loading
Loading