Skip to content
Merged
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
14 changes: 7 additions & 7 deletions docs/explanation/livestreams.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,15 +41,15 @@ By default, created livestreams are `private`, to prevent possible bugs.
<TabItem value="python" label="Python">

```python
from fishjam import FishjamClient
from fishjam import FishjamClient, RoomOptions

fishjam_client = FishjamClient(
fishjam_id=fishjam_id,
management_token=management_token,
);
)

private_room = fishjam_client.create_room(room_type="livestream") # [!code highlight]
public_room = fishjam_client.create_room(room_type="livestream", public=True) # [!code highlight]
private_room = fishjam_client.create_room(RoomOptions(room_type="livestream")) # [!code highlight]
public_room = fishjam_client.create_room(RoomOptions(room_type="livestream", public=True)) # [!code highlight]
```

</TabItem>
Expand Down Expand Up @@ -93,14 +93,14 @@ Note that for development purposes, you can [use the Sandbox API to generate a v
<TabItem value="python" label="Python">

```python
from fishjam import FishjamClient
from fishjam import FishjamClient, RoomOptions

fishjam_client = FishjamClient(
fishjam_id=fishjam_id,
management_token=management_token,
);
)

private_room = fishjam_client.create_room(room_type="livestream")
private_room = fishjam_client.create_room(RoomOptions(room_type="livestream"))
viewer_token = fishjam_client.create_livestream_viewer_token(private_room.id) # [!code highlight]
```

Expand Down
3 changes: 2 additions & 1 deletion docs/how-to/backend/fastapi-example.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,9 @@ It doesn't interact with the FastAPI library per se, just start the event loop a
```python
import asyncio
from fishjam import FishjamNotifier
from fishjam.events import ServerMessagePeerAdded

notifier = FishjamNotifier(server_address=fishjam_id, server_api_token=management_token)
notifier = FishjamNotifier(fishjam_id=fishjam_id, management_token=management_token)

@notifier.on_server_notification
def handle_notification(notification):
Expand Down
1 change: 1 addition & 0 deletions docs/how-to/backend/server-setup.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,7 @@ It sets up a websocket connection with a Fishjam instance and provides a simple
```python
import asyncio
from fishjam import FishjamNotifier
from fishjam.events import ServerMessageRoomCreated

notifier = FishjamNotifier(fishjam_id, management_token)

Expand Down
12 changes: 6 additions & 6 deletions docs/how-to/backend/whip-whep.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,14 @@ You can read about this in detail in [Production Livestreaming with Server SDKs]
<TabItem value="python" label="Python">

```python
from fishjam import FishjamClient
from fishjam import FishjamClient, RoomOptions

fishjam_client = FishjamClient(
fishjam_id=fishjam_id,
management_token=management_token,
);
)

room = fishjam_client.create_room(room_type="livestream")
room = fishjam_client.create_room(RoomOptions(room_type="livestream"))
streamer_token = fishjam_client.create_livestream_streamer_token(room.id) # [!code highlight]
```

Expand Down Expand Up @@ -150,14 +150,14 @@ You can read about this in detail in [Production Livestreaming with Server SDKs]
<TabItem value="python" label="Python">

```python
from fishjam import FishjamClient
from fishjam import FishjamClient, RoomOptions

fishjam_client = FishjamClient(
fishjam_id=fishjam_id,
management_token=management_token,
);
)

room = fishjam_client.create_room(room_type="livestream", public=False)
room = fishjam_client.create_room(RoomOptions(room_type="livestream", public=False))

# ...

Expand Down
83 changes: 43 additions & 40 deletions docs/integrations/gemini-live-integration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -227,50 +227,53 @@ Fishjam handles raw bytes, while Google GenAI SDKs often expect Base64 strings.
Now we connect the websocket loops. We need to forward incoming Fishjam audio to Google, and forward incoming Google audio to Fishjam.
```python
import asyncio
from fishjam.integrations.gemini import GeminiIntegration
from google.genai.types import Blob, Modality
from fishjam.integrations.gemini import GeminiIntegration

GEMINI_MODEL = "gemini-2.5-flash-native-audio-preview-12-2025"

async with agent.connect() as fishjam_session:

# Use our preset to match the required audio format (24kHz)
outgoing_track = await fishjam_session.add_track(GeminiIntegration.GEMINI_OUTPUT_AUDIO_SETTINGS)

async with gen_ai.aio.live.connect(
model=GEMINI_MODEL,
config={"response_modalities": [Modality.AUDIO]}
) as gemini_session:

# Fishjam -> Google
async def forward_audio_to_gemini():
async for track_data in fishjam_session.receive():
await gemini_session.send_realtime_input(audio=Blob(
mime_type=GeminiIntegration.GEMINI_AUDIO_MIME_TYPE,
data=track_data.data
))

# Google -> Fishjam
async def forward_audio_to_fishjam():
async for msg in gemini_session.receive():
server_content = msg.server_content

if server_content is None:
continue

if server_content.interrupted:
await outgoing_track.interrupt()

if server_content.model_turn and server_content.model_turn.parts:
for part in server_content.model_turn.parts:
if part.inline_data and part.inline_data.data:
await outgoing_track.send_chunk(part.inline_data.data)

# Run both loops concurrently
await asyncio.gather(
forward_audio_to_gemini(),
forward_audio_to_fishjam()
)
async def run():
async with agent.connect() as fishjam_session:

# Use our preset to match the required audio format (24kHz)
outgoing_track = await fishjam_session.add_track(GeminiIntegration.GEMINI_OUTPUT_AUDIO_SETTINGS)

async with gen_ai.aio.live.connect(
model=GEMINI_MODEL,
config={"response_modalities": [Modality.AUDIO]}
) as gemini_session:

# Fishjam -> Google
async def forward_audio_to_gemini():
async for track_data in fishjam_session.receive():
await gemini_session.send_realtime_input(audio=Blob(
mime_type=GeminiIntegration.GEMINI_AUDIO_MIME_TYPE,
data=track_data.data
))

# Google -> Fishjam
async def forward_audio_to_fishjam():
async for msg in gemini_session.receive():
server_content = msg.server_content

if server_content is None:
continue

if server_content.interrupted:
await outgoing_track.interrupt()

if server_content.model_turn and server_content.model_turn.parts:
for part in server_content.model_turn.parts:
if part.inline_data and part.inline_data.data:
await outgoing_track.send_chunk(part.inline_data.data)

# Run both loops concurrently
await asyncio.gather(
forward_audio_to_gemini(),
forward_audio_to_fishjam()
)

asyncio.run(run())
```

</TabItem>
Expand Down
2 changes: 1 addition & 1 deletion docs/integrations/vapi-integration.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ You will need:
<TabItem value="python" label="Python">

```bash
pip install fishjam-server-sdk vapi
pip install fishjam-server-sdk vapi_server_sdk
```

</TabItem>
Expand Down
89 changes: 53 additions & 36 deletions docs/tutorials/agents.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,23 @@ However, it's likely that in your scenario you'll want to use the [Selective Sub
<TabItem value="python" label="Python">

```python
from fishjam import FishjamClient
from fishjam.agent import AgentResponseTrackData
import asyncio
from fishjam import FishjamClient, AgentOptions
from fishjam.agent import IncomingTrackData

fishjam_client = FishjamClient(fishjam_id, management_token)

agent_options = AgentOptions(subscribe_mode="auto")
agent = fishjam_client.create_agent(room_id)
agent = fishjam_client.create_agent(room_id, agent_options)

# the agent will disconnect once you exit the context
async with agent.connect() as session:
async for track_data in session.receive():
# process the incoming data
pass
async def run():
# the agent will disconnect once you exit the context
async with agent.connect() as session:
async for track_data in session.receive():
# process the incoming data
pass

asyncio.run(run())
```

</TabItem>
Expand Down Expand Up @@ -239,28 +243,33 @@ You can interrupt the currently played audio chunk. See the example below.
<TabItem value="python" label="Python">

```python
from fishjam import FishjamClient
from fishjam.agent import AgentResponseTrackData, OutgoingAudioTrackOptions, TrackEncoding
import asyncio
from fishjam import FishjamClient, AgentOptions
from fishjam.agent import OutgoingAudioTrackOptions
from fishjam.events import TrackEncoding

fishjam_client = FishjamClient(fishjam_id, management_token)

agent_options = AgentOptions(subscribe_mode="auto")

agent = fishjam_client.create_agent(room_id)
agent = fishjam_client.create_agent(room_id, agent_options)

track_options = OutgoingAudioTrackOptions(encoding=TrackEncoding.TRACK_ENCODING_PCM16)

track_options = OutgoingAudioTrackOptions(encoding=TrackEncoding.PCM16)
async def run():
# the agent will disconnect once you exit the context
async with agent.connect() as session:
outgoing_track = await session.add_track(track_options)

# the agent will disconnect once you exit the context
async with agent.connect() as session:
outgoing_track = session.create_track(track_options)
# that's a dummy chatbot
async for chatbot_data in chatbot.receive():
await outgoing_track.send_chunk(chatbot_data)
Comment thread
PiotrWodecki marked this conversation as resolved.
Comment thread
PiotrWodecki marked this conversation as resolved.

# that's a dummy chatbot
async for chatbot_data in chatbot.receive():
outgoing_track.send_chunk(chatbot_data)
# you're able to interrupt the currently played audio chunk
# [!code highlight:1]
await outgoing_track.interrupt()

# you're able to interrupt the currently played audio chunk
# [!code highlight:1]
ongoing_track.interrupt()
asyncio.run(run())
```

</TabItem>
Expand Down Expand Up @@ -321,18 +330,21 @@ Video frame capture is rate-limited to one frame per second per track.

agent = fishjam_client.create_agent(room_id)

async with agent.connect() as session:
# Request a frame
# [!code highlight:1]
await session.capture_image(track_id)

# Captured frames arrive as IncomingTrackImage messages
async for message in session.receive():
match message:
case IncomingTrackImage() as msg if msg.track_id == track_id:
data = msg.data
# process the image data
pass
async def run():
async with agent.connect() as session:
# Request a frame
# [!code highlight:1]
await session.capture_image(track_id)
Comment thread
PiotrWodecki marked this conversation as resolved.

# Captured frames arrive as IncomingTrackImage messages
async for message in session.receive():
match message:
case IncomingTrackImage() as msg if msg.track_id == track_id:
data = msg.data
# process the image data
pass

asyncio.run(run())
```

</TabItem>
Expand Down Expand Up @@ -365,9 +377,14 @@ After you're done using an agent, you can disconnect it from the room.
<TabItem value="python" label="Python">

```python
# the agent will disconnect once you exit the context
async with agent.connect() as session:
pass
import asyncio

async def run():
# the agent will disconnect once you exit the context
async with agent.connect() as session:
pass
Comment thread
PiotrWodecki marked this conversation as resolved.

asyncio.run(run())
```

</TabItem>
Expand Down
1 change: 1 addition & 0 deletions docs/tutorials/backend-quick-start.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ Build a simple HTTP endpoint that your client apps can call:
```python
import os
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from fishjam import FishjamClient, PeerOptions

app = FastAPI()
Expand Down
6 changes: 3 additions & 3 deletions docs/tutorials/livestreaming.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -429,15 +429,15 @@ Our backend needs to do three things to be ready for streaming:
<TabItem value="python" label="Python">

```python
from fishjam import FishjamClient
from fishjam import FishjamClient, RoomOptions

fishjam_client = FishjamClient(
fishjam_id=fishjam_id,
management_token=management_token,
);
)

# 1.
room = fishjam_client.create_room(room_type="livestream")
room = fishjam_client.create_room(RoomOptions(room_type="livestream"))
# 2.
streamer_token = fishjam_client.create_livestream_streamer_token(room.id)
# 3.
Expand Down
4 changes: 2 additions & 2 deletions scripts/prepare.sh
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ echo $ROOTDIR
cd $ROOTDIR

printf "Synchronising submodules... "
git submodule sync >>/dev/null
git submodule update --init --remote >>/dev/null
git submodule sync --recursive >>/dev/null
git submodule update --init --recursive >>/dev/null
Comment thread
PiotrWodecki marked this conversation as resolved.

# cd packages/web-client-sdk/
# yarn && yarn build
Expand Down
Loading