Creating the bot when pressing to connect.
This commit is contained in:
@@ -19,13 +19,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="main-content">
|
<audio id="bot-audio" autoplay></audio>
|
||||||
<div class="bot-container">
|
|
||||||
<div id="bot-video-container">
|
|
||||||
</div>
|
|
||||||
<audio id="bot-audio" autoplay></audio>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="debug-panel">
|
<div class="debug-panel">
|
||||||
<h3>Debug Info</h3>
|
<h3>Debug Info</h3>
|
||||||
|
|||||||
@@ -110,6 +110,20 @@ class ChatbotClient {
|
|||||||
this.botAudio.srcObject = new MediaStream([track]);
|
this.botAudio.srcObject = new MediaStream([track]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fetchRoomInfo() {
|
||||||
|
let connectUrl = 'http://0.0.0.0:7860/connect'
|
||||||
|
let res = await fetch(connectUrl, {
|
||||||
|
method: "POST",
|
||||||
|
mode: "cors",
|
||||||
|
headers: new Headers({
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
if (res.ok) {
|
||||||
|
return res.json();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize and connect to the bot
|
* Initialize and connect to the bot
|
||||||
* This sets up the RTVI client, initializes devices, and establishes the connection
|
* This sets up the RTVI client, initializes devices, and establishes the connection
|
||||||
@@ -124,13 +138,15 @@ class ChatbotClient {
|
|||||||
// Set up listeners for media track events
|
// Set up listeners for media track events
|
||||||
this.setupTrackListeners();
|
this.setupTrackListeners();
|
||||||
|
|
||||||
|
this.log('Creating the bot...');
|
||||||
|
let roomInfo = await this.fetchRoomInfo()
|
||||||
|
|
||||||
// Connect to the bot
|
// Connect to the bot
|
||||||
this.log('Connecting to bot...');
|
this.log('Connecting to bot...');
|
||||||
// Only for making debugger easier
|
// Only for making debugger easier
|
||||||
window.callObject = this.dailyCallObject;
|
window.callObject = this.dailyCallObject;
|
||||||
await this.dailyCallObject.join({
|
await this.dailyCallObject.join({
|
||||||
//TODO fixme, use the URL that we are going to receive from bot
|
url: roomInfo.room_url,
|
||||||
url: "https://filipi.daily.co/public",
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.log('Connection complete');
|
this.log('Connection complete');
|
||||||
|
|||||||
147
examples/bot-ready-signalling/server/server.py
Normal file
147
examples/bot-ready-signalling/server/server.py
Normal file
@@ -0,0 +1,147 @@
|
|||||||
|
#
|
||||||
|
# Copyright (c) 2025, Daily
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: BSD 2-Clause License
|
||||||
|
#
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
from contextlib import asynccontextmanager
|
||||||
|
from typing import Any, Dict
|
||||||
|
|
||||||
|
import aiohttp
|
||||||
|
from dotenv import load_dotenv
|
||||||
|
from fastapi import FastAPI, HTTPException, Request
|
||||||
|
from fastapi.middleware.cors import CORSMiddleware
|
||||||
|
from fastapi.responses import JSONResponse
|
||||||
|
|
||||||
|
from pipecat.transports.services.helpers.daily_rest import DailyRESTHelper, DailyRoomParams
|
||||||
|
|
||||||
|
# Load environment variables from .env file
|
||||||
|
load_dotenv(override=True)
|
||||||
|
|
||||||
|
# Dictionary to track bot processes: {pid: (process, room_url)}
|
||||||
|
bot_procs = {}
|
||||||
|
|
||||||
|
# Store Daily API helpers
|
||||||
|
daily_helpers = {}
|
||||||
|
|
||||||
|
|
||||||
|
def cleanup():
|
||||||
|
"""Cleanup function to terminate all bot processes.
|
||||||
|
|
||||||
|
Called during server shutdown.
|
||||||
|
"""
|
||||||
|
for entry in bot_procs.values():
|
||||||
|
proc = entry[0]
|
||||||
|
proc.terminate()
|
||||||
|
proc.wait()
|
||||||
|
|
||||||
|
|
||||||
|
@asynccontextmanager
|
||||||
|
async def lifespan(app: FastAPI):
|
||||||
|
"""FastAPI lifespan manager that handles startup and shutdown tasks.
|
||||||
|
|
||||||
|
- Creates aiohttp session
|
||||||
|
- Initializes Daily API helper
|
||||||
|
- Cleans up resources on shutdown
|
||||||
|
"""
|
||||||
|
aiohttp_session = aiohttp.ClientSession()
|
||||||
|
daily_helpers["rest"] = DailyRESTHelper(
|
||||||
|
daily_api_key=os.getenv("DAILY_API_KEY", ""),
|
||||||
|
daily_api_url=os.getenv("DAILY_API_URL", "https://api.daily.co/v1"),
|
||||||
|
aiohttp_session=aiohttp_session,
|
||||||
|
)
|
||||||
|
yield
|
||||||
|
await aiohttp_session.close()
|
||||||
|
cleanup()
|
||||||
|
|
||||||
|
|
||||||
|
# Initialize FastAPI app with lifespan manager
|
||||||
|
app = FastAPI(lifespan=lifespan)
|
||||||
|
|
||||||
|
# Configure CORS to allow requests from any origin
|
||||||
|
app.add_middleware(
|
||||||
|
CORSMiddleware,
|
||||||
|
allow_origins=["*"],
|
||||||
|
allow_credentials=True,
|
||||||
|
allow_methods=["*"],
|
||||||
|
allow_headers=["*"],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
async def create_room_and_token() -> tuple[str, str]:
|
||||||
|
"""Helper function to create a Daily room and generate an access token.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple[str, str]: A tuple containing (room_url, token)
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
HTTPException: If room creation or token generation fails
|
||||||
|
"""
|
||||||
|
room = await daily_helpers["rest"].create_room(DailyRoomParams())
|
||||||
|
if not room.url:
|
||||||
|
raise HTTPException(status_code=500, detail="Failed to create room")
|
||||||
|
|
||||||
|
token = await daily_helpers["rest"].get_token(room.url)
|
||||||
|
if not token:
|
||||||
|
raise HTTPException(status_code=500, detail=f"Failed to get token for room: {room.url}")
|
||||||
|
|
||||||
|
return room.url, token
|
||||||
|
|
||||||
|
|
||||||
|
@app.post("/connect")
|
||||||
|
async def bot_connect(request: Request) -> Dict[Any, Any]:
|
||||||
|
"""Connect endpoint that creates a room and returns connection credentials.
|
||||||
|
|
||||||
|
This endpoint is called by client to establish a connection.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict[Any, Any]: Authentication bundle containing room_url and token
|
||||||
|
|
||||||
|
Raises:
|
||||||
|
HTTPException: If room creation, token generation, or bot startup fails
|
||||||
|
"""
|
||||||
|
print("Creating room for RTVI connection")
|
||||||
|
room_url, token = await create_room_and_token()
|
||||||
|
print(f"Room URL: {room_url}")
|
||||||
|
|
||||||
|
# Start the bot process
|
||||||
|
try:
|
||||||
|
bot_file = "signalling_bot"
|
||||||
|
proc = subprocess.Popen(
|
||||||
|
[f"python3 -m {bot_file} -u {room_url} -t {token}"],
|
||||||
|
shell=True,
|
||||||
|
bufsize=1,
|
||||||
|
cwd=os.path.dirname(os.path.abspath(__file__)),
|
||||||
|
)
|
||||||
|
bot_procs[proc.pid] = (proc, room_url)
|
||||||
|
except Exception as e:
|
||||||
|
raise HTTPException(status_code=500, detail=f"Failed to start subprocess: {e}")
|
||||||
|
|
||||||
|
# Return the authentication bundle in format expected by DailyTransport
|
||||||
|
return {"room_url": room_url, "token": token}
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import uvicorn
|
||||||
|
|
||||||
|
# Parse command line arguments for server configuration
|
||||||
|
default_host = os.getenv("HOST", "0.0.0.0")
|
||||||
|
default_port = int(os.getenv("FAST_API_PORT", "7860"))
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description="Daily Travel Companion FastAPI server")
|
||||||
|
parser.add_argument("--host", type=str, default=default_host, help="Host address")
|
||||||
|
parser.add_argument("--port", type=int, default=default_port, help="Port number")
|
||||||
|
parser.add_argument("--reload", action="store_true", help="Reload code on change")
|
||||||
|
|
||||||
|
config = parser.parse_args()
|
||||||
|
|
||||||
|
# Start the FastAPI server
|
||||||
|
uvicorn.run(
|
||||||
|
"server:app",
|
||||||
|
host=config.host,
|
||||||
|
port=config.port,
|
||||||
|
reload=config.reload,
|
||||||
|
)
|
||||||
Reference in New Issue
Block a user