Spaces:
Sleeping
Sleeping
File size: 5,554 Bytes
bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 |
import argparse
import queue
import time
import threading
import logging
import os
from PIL import Image
from typing import Any, Mapping
from daily import EventHandler, CallClient, Daily
from datetime import datetime
from dotenv import load_dotenv
from auth import get_meeting_token, get_room_name
load_dotenv()
class DailyVision(EventHandler):
def __init__(
self,
room_url,
room_name,
expiration,
bot_name="Daily Bot",
):
self.__client = CallClient(event_handler=self)
self.__pipeline = None
self.__camera = None
self.__time = time.time()
self.__queue = queue.Queue()
self.__app_quit = False
self.__bot_name = bot_name
self.__room_url = room_url
self.__room_name = room_name
self.__expiration = expiration
# Configure logger
FORMAT = f"%(asctime)s {self.__room_url} %(message)s"
logging.basicConfig(format=FORMAT)
self.logger = logging.getLogger("bot-instance")
self.logger.setLevel(logging.DEBUG)
self.logger.info(f"Expiration timer set to: {self.__expiration}")
# Start thread
self.__thread = threading.Thread(target = self.process_frames)
self.__thread.start()
def run(self, meeting_url, token):
# Join
self.logger.info(f"Connecting to room {meeting_url} as {self.__bot_name}")
self.__client.set_user_name(self.__bot_name)
self.__client.join(meeting_url, token, completion=self.on_joined)
#self.__participant_id = self.client.participants()["local"]["id"]
# Keep-alive on thread
self.__thread.join()
def leave(self):
self.logger.info(f"Leaving...")
self.__app_quit = True
self.__thread.join()
self.__client.leave()
def on_joined(self, join_data, client_error):
self.logger.info(f"call_joined: {join_data}, {client_error}")
def on_participant_joined(self, participant):
self.logger.info(f"Participant {participant['id']} joined, analyzing frames...")
self.__client.set_video_renderer(participant["id"], self.on_video_frame)
# Say hello
self.wave()
def setup_camera(self, video_frame):
if not self.__camera:
self.__camera = Daily.create_camera_device("camera",
width = video_frame.width,
height = video_frame.height,
color_format="RGB")
self.__client.update_inputs({
"camera": {
"isEnabled": True,
"settings": {
"deviceId": "camera"
}
}
})
def process_frames(self):
while not self.__app_quit:
# Check expiry timer
if time.time() > self.__expiration:
self.logger.info(f"Expiration timer exceeded. Exiting...")
self.__app_quit = True
return
try:
video_frame = self.__queue.get(timeout=5)
if video_frame:
image = Image.frombytes("RGBA", (video_frame.width, video_frame.height), video_frame.buffer)
result = self.__pipeline(image)
pil = Image.fromarray(result.render()[0], mode="RGB").tobytes()
self.__camera.write_frame(pil)
except queue.Empty:
pass
def on_video_frame(self, participant_id, video_frame):
# Process ~15 frames per second (considering incoming frames at 30fps).
if time.time() - self.__time > 0.05:
self.__time = time.time()
self.setup_camera(video_frame)
self.__queue.put(video_frame)
def wave(self, emoji="👋"):
self.__client.send_app_message(
{
"event": "sync-emoji-reaction",
"reaction": {
"emoji": emoji,
"room": "main-room",
"sessionId": "bot",
"id": time.time(),
},
}
)
def main():
parser = argparse.ArgumentParser(description="Daily Bot")
# Required args
parser.add_argument("-u", "--url", required=True, type=str, help="URL of the Daily room")
parser.add_argument("-k", "--api_key", required=True, type=str, help="Daily API key")
# Optional args
parser.add_argument("-t", "--private", type=bool, help="Is this room private?", default=True)
parser.add_argument("-n", "--bot-name", type=str, help="Name of the bot", default="Daily Bot")
parser.add_argument("-e", "--expiration", type=int, help="Duration of bot", default=os.getenv("BOT_MAX_DURATION", 300))
args = parser.parse_args()
Daily.init()
expiration = time.time() + args.expiration
room_name = get_room_name(args.url)
# Retrieve a meeting token, if not provided
#@TODO do room lookup to check privacy
if args.private:
token = get_meeting_token(room_name, args.api_key, expiration)
app = DailyVision(args.url, room_name, expiration, args.bot_name)
try :
app.run(args.url, token)
except KeyboardInterrupt:
print("Ctrl-C detected. Exiting!")
finally:
print("Bot loop completed. Exiting")
app.leave()
# Let leave finish
time.sleep(2)
if __name__ == '__main__':
main() |