billowy-analyst-47555
08/02/2025, 10:19 PMtall-airline-16756
08/02/2025, 10:19 PMtall-airline-16756
08/02/2025, 10:20 PMbillowy-analyst-47555
08/02/2025, 10:24 PMtall-airline-16756
08/02/2025, 10:24 PMbillowy-analyst-47555
08/02/2025, 10:30 PMtall-airline-16756
08/02/2025, 10:31 PMconst file = document.getElementById('file')?.files?.[0];
if (file) {
const info = await room.localParticipant.sendFile(
file,
{
mimeType: file.type,
topic: 'files',
onProgress: (progress) => console.log(`Sending file, progress: ${Math.ceil(progress * 100)}%`),
}
);
console.log(`Sent file with stream ID: ${info.id}`);
}
Receiving Files
room.registerByteStreamHandler('files', (reader, participant) => {
const info = <http://reader.info|reader.info>;
reader.onProgress = (progress) => {
console.log(`Receiving file "${info.name}" from ${participant.identity}, progress: ${Math.round(progress * 100)}%`);
};
const chunks = [];
for await (const chunk of reader) {
chunks.push(chunk);
}
const fileBlob = new Blob(chunks, { type: info.mimeType });
if (info.mimeType.startsWith('image/')) {
const imageUrl = URL.createObjectURL(fileBlob);
console.log('Received image:', imageUrl);
} else if (info.mimeType === 'application/pdf') {
const pdfUrl = URL.createObjectURL(fileBlob);
console.log('Received PDF:', pdfUrl);
}
});
This example shows you how to send and receive files smoothly, keeping track of progress and handling different file types with ease. If anything’s unclear or you want me to walk you through more examples, just let me know—I’m here to help!billowy-analyst-47555
08/02/2025, 11:11 PMtall-airline-16756
08/02/2025, 11:11 PMclass VisionAssistant(Agent):
async def on_enter(self):
def _image_received_handler(reader, participant_identity):
task = asyncio.create_task(
self._image_received(reader, participant_identity)
)
self._tasks.append(task)
task.add_done_callback(lambda t: self._tasks.remove(t))
get_job_context().room.register_byte_stream_handler("test", _image_received_handler)
2. Process Received Files/Byte Streams:
async def _image_received(self, reader, participant_identity):
<http://logger.info|logger.info>("Received image from %s: '%s'", participant_identity, reader.info.name)
try:
image_bytes = bytes()
async for chunk in reader:
image_bytes += chunk
chat_ctx = self.chat_ctx.copy()
chat_ctx.add_message(
role="user",
content=[
ImageContent(
image=f"data:image/png;base64,{base64.b64encode(image_bytes).decode('utf-8')}"
)
],
)
await self.update_chat_ctx(chat_ctx)
print("Image received", self.chat_ctx.copy().to_dict(exclude_image=False))
3. Sending Files from the Frontend:
# Use the LiveKit SDK's send_file method to send files
await room.localParticipant.send_file(
file_path="path/to/image.jpg",
topic="images",
destination_identities=["agent"], # Optional, if you want to send to specific participants
)
These tweaks will get your agent ready to handle file uploads and byte streams like a pro. If anything’s unclear or you want me to walk you through more examples, just give me a shout!billowy-analyst-47555
08/02/2025, 11:13 PMtall-airline-16756
08/02/2025, 11:13 PMagent.py)
This is where your agent class and its handlers live. You’ll want to:
• Set up a byte stream handler to catch uploaded files or byte streams.
• Process the data right inside that handler.
Here’s a quick example:
class VisionAssistant(Agent):
async def on_enter(self):
def _image_received_handler(reader, participant_identity):
task = asyncio.create_task(
self._image_received(reader, participant_identity)
)
self._tasks.append(task)
task.add_done_callback(lambda t: self._tasks.remove(t))
get_job_context().room.register_byte_stream_handler("test", _image_received_handler)
async def _image_received(self, reader, participant_identity):
image_bytes = bytes()
async for chunk in reader:
image_bytes += chunk
chat_ctx = self.chat_ctx.copy()
chat_ctx.add_message(
role="user",
content=[
ImageContent(
image=f"data:image/png;base64,{base64.b64encode(image_bytes).decode('utf-8')}"
)
],
)
await self.update_chat_ctx(chat_ctx)
2. FastAPI Route Handler File (like main.py)
Next up, create or update a FastAPI route that handles file uploads and sends them over to your LiveKit agent using byte streams. Something like this:
from fastapi import FastAPI, File, UploadFile
from livekit import rtc
app = FastAPI()
@app.post("/upload-file")
async def upload_file(file: UploadFile = File(...)):
# Connect to LiveKit room and get the local participant
await room.local_participant.send_file(
file.file,
topic="test",
)
return {"message": "File uploaded successfully"}
If anything’s unclear or you’d like more examples, just give me a shout—I’m here to help!
Sources: Vision | LiveKit Docsbillowy-analyst-47555
08/02/2025, 11:57 PMtall-airline-16756
08/03/2025, 12:03 AMsendFile method to send files like images or PDFs to the agent. It’s a smooth way to transfer files without any hassle.
2. Streaming Bytes: For sending binary data bit by bit, the streamBytes method is your friend. This works great for real-time stuff like audio or video frames.
3. Handling Incoming Byte Streams: Don’t forget to register a byte stream handler in your agent with register_byte_stream_handler. This helps your agent process incoming streams either as they come in or once the whole stream is received.
4. Limitations and Considerations:
• Chunk Sizes: The system smartly optimizes chunk sizes for reading and writing, so make sure your agent can handle data in chunks.
• Concurrency: It’s important to manage multiple streams properly, especially if you have several participants involved.
5. Integration with Vision: If you’re working with vision tasks, double-check that the images you receive play nicely with your vision model. Process the image bytes accordingly to get the best results.
6. Additional Resources: You might find the Byte Streams Documentation and the Vision Guide super helpful for more details and tips.
Feel free to reach out if you want me to walk you through anything or share some examples!
Sources: Sending files & bytes | LiveKit Docs | Vision | LiveKit Docs | Bringing AI avatars to voice agentsbillowy-analyst-47555
08/04/2025, 6:51 PMtall-airline-16756
08/04/2025, 6:52 PMbillowy-analyst-47555
08/05/2025, 9:55 PMtall-airline-16756
08/05/2025, 9:55 PMvar fileToSend = File('path/to/file.jpg');
var info = await room.localParticipant?.sendFile(
fileToSend,
options: SendFileOptions(
topic: 'file-topic',
onProgress: (progress) {
// Keep track of progress here
print('Progress: ${progress * 100}%');
},
));
2. Streaming Bytes:
var writer = await room.localParticipant?.streamBytes(
StreamBytesOptions(topic: 'byte-stream-topic'));
await writer?.write(utf8.encode('Hello, world!'));
await writer?.close();
3. Receiving Files and Bytes:
room.registerByteStreamHandler(
'file-topic',
(ByteStreamReader reader, String participantIdentity) async {
// Here’s where you process the incoming file chunks
var file = await reader.readAll();
// Then handle the file data (like saving it)
});
Important Things to Keep in Mind:
• You can use readAll() to grab the whole content at once, or listen for chunks as they come in.
• Both sendFile and streamBytes let you track progress with callbacks.
• Remember to close streams when you’re done to keep everything running smoothly.
If anything’s unclear or you want me to walk you through more examples, just let me know—I’m here to help!