Metadata-Version: 2.4
Name: applooma-bot
Version: 0.1.0
Summary: AppLooma RTC server-side participants (bots) for Python: publish and receive raw audio/video, exchange messages
Author: AppLooma LLC
License-Expression: MIT
Project-URL: Homepage, https://applooma.dev
Project-URL: Documentation, https://docs.applooma.dev/sdk/server-participant
Keywords: applooma,rtc,bot,voice-agent,audio,video,live-streaming
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Framework :: AsyncIO
Classifier: Programming Language :: Python :: 3
Classifier: Topic :: Communications :: Conferencing
Classifier: Topic :: Multimedia :: Sound/Audio
Requires-Python: >=3.9
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: applooma-rtc-native==0.1.0
Dynamic: license-file

# applooma-bot

Join an AppLooma RTC channel from Python as a regular participant (a bot): a
voice agent, a transcription listener, a media relay, a moderation bot. Publish
raw 16-bit PCM audio and raw I420/RGBA video, receive everyone else's media as
raw frames, and exchange messages with the client SDKs.

```bash
pip install applooma applooma-bot
```

Python 3.9+. Prebuilt for Linux x86_64/aarch64 (glibc 2.28+), macOS arm64/x86_64
and Windows x64; no compiler needed. Beta (0.1.0): the API may change before 1.0.

```python
import asyncio
from applooma import AppServerClient
from applooma_bot import AppBot, AppBotError

async def main():
    t = AppServerClient(api_key="...", api_secret="...").create_token(
        room_name="room1", identity="echo-bot", role="host")
    bot = await AppBot.join(url=t["wsUrl"], token=t["token"])

    @bot.on("user_joined")
    def joined(user):
        print(user.uid, "joined")

    @bot.on("audio_frame")            # frame.data: interleaved int16 PCM bytes
    async def echo(frame, user):
        await bot.publish_audio(frame)

    @bot.on("message")
    async def on_message(msg):
        if msg.text == "!bye":
            await bot.leave()
        else:
            await bot.send_message(f"echo: {msg.text}")

    await asyncio.sleep(3600)

asyncio.run(main())
```

## API

- `await AppBot.join(url, token, *, auto_subscribe=True, receive_sample_rate=48000, receive_channels=1, receive_video_format="rgba")`
- `await bot.publish_audio(AppAudioFrame(data, sample_rate, channels))` or `publish_audio(pcm_bytes, sample_rate=48000, channels=1)`. The first call publishes the microphone; awaiting each call paces you to real time.
- `bot.publish_video(AppVideoFrame(data, width, height, "i420" | "rgba"))`. The first call publishes the camera.
- `await bot.send_message("text" | {...})`: arrives on the client SDKs' `message` event.
- `await bot.leave()`; `AppBot` is also an async context manager.
- Events (`bot.on(name, handler)` or `@bot.on(name)`, sync or async handlers):
  `audio_frame(frame, user)`, `video_frame(frame, user)`, `message(msg)`,
  `user_joined(user)`, `user_left(user)`, `disconnected(reason)`, `error(err)`.
  Register frame handlers right after joining: frames are decoded only for
  tracks subscribed while a handler is attached.
- Errors: `AppBotError` with `.code` one of `unsupported_platform`, `join_failed`,
  `not_joined`, `invalid_frame`, `send_failed`.

Docs: https://docs.applooma.dev/sdk/server-participant
