livekit-plugins-hedra 1.3.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,35 @@
1
+ # Copyright 2023 LiveKit, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ from .avatar import AvatarSession, HedraException
17
+ from .version import __version__
18
+
19
+ __all__ = [
20
+ "HedraException",
21
+ "AvatarSession",
22
+ "__version__",
23
+ ]
24
+
25
+ from livekit.agents import Plugin
26
+
27
+ from .log import logger
28
+
29
+
30
+ class HedraPlugin(Plugin):
31
+ def __init__(self) -> None:
32
+ super().__init__(__name__, __version__, __package__, logger)
33
+
34
+
35
+ Plugin.register_plugin(HedraPlugin())
@@ -0,0 +1,159 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import io
5
+ import os
6
+
7
+ import aiohttp
8
+ from PIL.Image import Image
9
+
10
+ from livekit import api, rtc
11
+ from livekit.agents import (
12
+ DEFAULT_API_CONNECT_OPTIONS,
13
+ NOT_GIVEN,
14
+ AgentSession,
15
+ APIConnectionError,
16
+ APIConnectOptions,
17
+ APIStatusError,
18
+ NotGivenOr,
19
+ get_job_context,
20
+ utils,
21
+ )
22
+ from livekit.agents.voice.avatar import DataStreamAudioOutput
23
+ from livekit.agents.voice.room_io import ATTRIBUTE_PUBLISH_ON_BEHALF
24
+
25
+ from .log import logger
26
+
27
+ DEFAULT_API_URL = "https://api.hedra.com/public/livekit/v1/session"
28
+ SAMPLE_RATE = 16000
29
+ _AVATAR_AGENT_IDENTITY = "hedra-avatar-agent"
30
+ _AVATAR_AGENT_NAME = "hedra-avatar-agent"
31
+
32
+
33
+ class HedraException(Exception):
34
+ """Exception for Hedra errors"""
35
+
36
+
37
+ class AvatarSession:
38
+ """A Hedra avatar session"""
39
+
40
+ def __init__(
41
+ self,
42
+ *,
43
+ avatar_id: NotGivenOr[str | None] = NOT_GIVEN,
44
+ avatar_image: NotGivenOr[Image] = NOT_GIVEN,
45
+ api_url: NotGivenOr[str] = NOT_GIVEN,
46
+ api_key: NotGivenOr[str] = NOT_GIVEN,
47
+ avatar_participant_identity: NotGivenOr[str] = NOT_GIVEN,
48
+ avatar_participant_name: NotGivenOr[str] = NOT_GIVEN,
49
+ conn_options: APIConnectOptions = DEFAULT_API_CONNECT_OPTIONS,
50
+ ) -> None:
51
+ self._avatar_id = avatar_id
52
+ self._avatar_image = avatar_image
53
+ if not self._avatar_id and not self._avatar_image:
54
+ raise HedraException("avatar_id or avatar_image must be provided")
55
+
56
+ self._api_url = api_url or os.getenv("HEDRA_API_URL", DEFAULT_API_URL)
57
+ self._api_key = api_key or os.getenv("HEDRA_API_KEY")
58
+ if self._api_key is None:
59
+ raise HedraException(
60
+ "The api_key must be set either by passing api_key to the client or "
61
+ "by setting the HEDRA_API_KEY environment variable"
62
+ )
63
+
64
+ self._avatar_participant_identity = avatar_participant_identity or _AVATAR_AGENT_IDENTITY
65
+ self._avatar_participant_name = avatar_participant_name or _AVATAR_AGENT_NAME
66
+ self._http_session: aiohttp.ClientSession | None = None
67
+ self._conn_options = conn_options
68
+
69
+ def _ensure_http_session(self) -> aiohttp.ClientSession:
70
+ if self._http_session is None:
71
+ self._http_session = utils.http_context.http_session()
72
+
73
+ return self._http_session
74
+
75
+ async def start(
76
+ self,
77
+ agent_session: AgentSession,
78
+ room: rtc.Room,
79
+ *,
80
+ livekit_url: NotGivenOr[str] = NOT_GIVEN,
81
+ livekit_api_key: NotGivenOr[str] = NOT_GIVEN,
82
+ livekit_api_secret: NotGivenOr[str] = NOT_GIVEN,
83
+ ) -> None:
84
+ livekit_url = livekit_url or (os.getenv("LIVEKIT_URL") or NOT_GIVEN)
85
+ livekit_api_key = livekit_api_key or (os.getenv("LIVEKIT_API_KEY") or NOT_GIVEN)
86
+ livekit_api_secret = livekit_api_secret or (os.getenv("LIVEKIT_API_SECRET") or NOT_GIVEN)
87
+ if not livekit_url or not livekit_api_key or not livekit_api_secret:
88
+ raise HedraException(
89
+ "livekit_url, livekit_api_key, and livekit_api_secret must be set "
90
+ "by arguments or environment variables"
91
+ )
92
+
93
+ job_ctx = get_job_context()
94
+ local_participant_identity = job_ctx.local_participant_identity
95
+ livekit_token = (
96
+ api.AccessToken(api_key=livekit_api_key, api_secret=livekit_api_secret)
97
+ .with_kind("agent")
98
+ .with_identity(self._avatar_participant_identity)
99
+ .with_name(self._avatar_participant_name)
100
+ .with_grants(api.VideoGrants(room_join=True, room=room.name))
101
+ # allow the avatar agent to publish audio and video on behalf of your local agent
102
+ .with_attributes({ATTRIBUTE_PUBLISH_ON_BEHALF: local_participant_identity})
103
+ .to_jwt()
104
+ )
105
+
106
+ logger.debug("starting avatar session")
107
+ await self._start_agent(livekit_url, livekit_token)
108
+
109
+ agent_session.output.audio = DataStreamAudioOutput(
110
+ room=room,
111
+ destination_identity=self._avatar_participant_identity,
112
+ wait_remote_track=rtc.TrackKind.KIND_VIDEO,
113
+ sample_rate=SAMPLE_RATE,
114
+ )
115
+
116
+ async def _start_agent(self, livekit_url: str, livekit_token: str) -> None:
117
+ assert self._api_key is not None
118
+ assert isinstance(self._api_url, str)
119
+
120
+ data = aiohttp.FormData({"livekit_url": livekit_url, "livekit_token": livekit_token})
121
+
122
+ if self._avatar_id:
123
+ data.add_field("avatar_id", self._avatar_id)
124
+
125
+ if self._avatar_image:
126
+ img_byte_arr = io.BytesIO()
127
+ self._avatar_image.save(img_byte_arr, format="JPEG", quality=95)
128
+ img_byte_arr.seek(0)
129
+ data.add_field(
130
+ "avatar_image", img_byte_arr, filename="avatar.jpg", content_type="image/jpeg"
131
+ )
132
+
133
+ for i in range(self._conn_options.max_retry):
134
+ try:
135
+ async with self._ensure_http_session().post(
136
+ self._api_url,
137
+ headers={
138
+ "x-api-key": self._api_key,
139
+ },
140
+ data=data,
141
+ timeout=aiohttp.ClientTimeout(sock_connect=self._conn_options.timeout),
142
+ ) as response:
143
+ if not response.ok:
144
+ text = await response.text()
145
+ raise APIStatusError(
146
+ "Server returned an error", status_code=response.status, body=text
147
+ )
148
+ return
149
+
150
+ except Exception as e:
151
+ if isinstance(e, APIConnectionError):
152
+ logger.warning("failed to call hedra avatar api", extra={"error": str(e)})
153
+ else:
154
+ logger.exception("failed to call hedra avatar api")
155
+
156
+ if i < self._conn_options.max_retry - 1:
157
+ await asyncio.sleep(self._conn_options.retry_interval)
158
+
159
+ raise APIConnectionError("Failed to start Hedra Avatar Session after all retries")
@@ -0,0 +1,3 @@
1
+ import logging
2
+
3
+ logger = logging.getLogger("livekit.plugins.hedra")
File without changes
@@ -0,0 +1,15 @@
1
+ # Copyright 2025 LiveKit, Inc.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+ __version__ = "1.3.12"
@@ -0,0 +1,38 @@
1
+ Metadata-Version: 2.4
2
+ Name: livekit-plugins-hedra
3
+ Version: 1.3.12
4
+ Summary: Agent Framework plugin for Hedra Avatar
5
+ Project-URL: Documentation, https://docs.livekit.io
6
+ Project-URL: Website, https://livekit.io/
7
+ Project-URL: Source, https://github.com/livekit/agents
8
+ Author-email: LiveKit <support@livekit.io>
9
+ License-Expression: Apache-2.0
10
+ Keywords: ai,audio,avatar,hedra,livekit,realtime,video,voice
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: Apache Software License
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3 :: Only
15
+ Classifier: Programming Language :: Python :: 3.9
16
+ Classifier: Programming Language :: Python :: 3.10
17
+ Classifier: Topic :: Multimedia :: Sound/Audio
18
+ Classifier: Topic :: Multimedia :: Video
19
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
20
+ Requires-Python: >=3.9.0
21
+ Requires-Dist: livekit-agents>=1.3.12
22
+ Description-Content-Type: text/markdown
23
+
24
+ # Hedra plugin for LiveKit Agents
25
+
26
+ Support for avatar generation and animation with [Hedra](https://hedra.ai/).
27
+
28
+ See [https://docs.livekit.io/agents/integrations/avatar/hedra/](https://docs.livekit.io/agents/integrations/avatar/hedra/) for more information.
29
+
30
+ ## Installation
31
+
32
+ ```bash
33
+ pip install livekit-plugins-hedra
34
+ ```
35
+
36
+ ## Pre-requisites
37
+
38
+ You'll need an API key from Hedra. It can be set as an environment variable: `HEDRA_API_KEY`
@@ -0,0 +1,8 @@
1
+ livekit/plugins/hedra/__init__.py,sha256=L8F2XyHfOLqeB6Y4iSvQNCUOW5KKIBw6HgF5MNCdvNY,969
2
+ livekit/plugins/hedra/avatar.py,sha256=TcTaPSX-Gl-rqpfzfWIAVmlHknepexg6NWtv39rNEBg,6082
3
+ livekit/plugins/hedra/log.py,sha256=vh-X7bs38yHVN8TNZcWVBvBcnALN-M_UGvWIgI6zi7k,68
4
+ livekit/plugins/hedra/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ livekit/plugins/hedra/version.py,sha256=UoTDvF115mviqqMEpGToG4ItmCSiA1i3wTiugW1Dyw8,601
6
+ livekit_plugins_hedra-1.3.12.dist-info/METADATA,sha256=FjBUJ9iHsXSa-upA7WIfD9IgP1LDrxRzfaYaXjqvUX4,1408
7
+ livekit_plugins_hedra-1.3.12.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
8
+ livekit_plugins_hedra-1.3.12.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.28.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any