Spaces:
Sleeping
Sleeping
File size: 6,306 Bytes
bd1c43c 4d3af55 bd1c43c 4d3af55 bd1c43c 70de1d6 bd1c43c 4d3af55 bd1c43c 4d3af55 70de1d6 bd1c43c 4d3af55 70de1d6 4d3af55 690cc6d 4d3af55 70de1d6 4d3af55 bd1c43c 4d3af55 bd1c43c 6e1bb73 4d3af55 70de1d6 4d3af55 bd1c43c 70de1d6 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 690cc6d bd1c43c 4d3af55 bd1c43c 6e1bb73 4d3af55 8354b1a 6e1bb73 4d3af55 bd1c43c 4d3af55 e606d44 4d3af55 70de1d6 4d3af55 70de1d6 4d3af55 690cc6d 4d3af55 690cc6d 6e1bb73 0ce0c17 e606d44 4d3af55 2bca5f7 4d3af55 690cc6d 4d3af55 bd1c43c 4d3af55 bd1c43c 4d3af55 fcfd230 bd1c43c 4d3af55 70de1d6 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 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
import argparse
import queue
import time
import threading
import logging
import os
from PIL import Image
from daily import EventHandler, CallClient, Daily
from datetime import datetime
from dotenv import load_dotenv
from auth import get_meeting_token, get_room_name
from pipeline import Pipeline
from device import device, torch_dtype
load_dotenv()
class DailyVision(EventHandler):
def __init__(
self,
room_url,
room_name,
expiration,
idle,
bot_name="Daily Bot"
):
self.__client = CallClient(event_handler=self)
self.__pipeline = Pipeline
self.__camera = None
self.__time = time.time()
self.__queue = queue.Queue()
self.__app_quit = False
self.__image_buffer = None
self.__bot_name = bot_name
self.__room_url = room_url
self.__room_name = room_name
self.__expiration = expiration
self.__idle = idle
# Create the pipeline (this might take a moment)
self.__pipeline = Pipeline(device, torch_dtype)
#print(self.__pipeline.InputParams.schema())
# 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}")
# Setup camera
self.setup_camera()
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"]
# Start thread
self.__thread = threading.Thread(target = self.process_frames)
self.__thread.start()
# 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, color_format="RGB")
# Say hello
self.wave()
def setup_camera(self):
if not self.__camera:
self.__camera = Daily.create_camera_device("camera",
width = 640,
height = 480,
color_format="RGB")
self.__client.update_inputs({
"camera": {
"isEnabled": True,
"settings": {
"deviceId": "camera"
}
}
})
def process_frames(self):
params = Pipeline.InputParams()
while not self.__app_quit:
# Is anyone watching?
if not self.__idle and len(self.__client.participants()) < 2:
self.logger.info(f"No partcipants in channel. Exiting...")
self.__app_quit = True
break
# Check expiry timer
if time.time() > self.__expiration:
self.logger.info(f"Expiration timer exceeded. Exiting...")
self.__app_quit = True
break
try:
#video_frame = self.__queue.get(timeout=5)
video_frame = self.__image_buffer
if not video_frame == None:
image = Image.frombytes("RGB", (video_frame.width, video_frame.height), video_frame.buffer)
result_image = self.__pipeline.predict(params, image)
self.__camera.write_frame(result_image.tobytes())
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 > float(os.getenv("FPS_CAP", 0.0333)):
self.__time = time.time()
self.__image_buffer = 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))
parser.add_argument("-i", "--idle", type=bool, help="Wait for participants to join", default=os.getenv("BOT_WILL_IDLE", False))
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.idle, args.bot_name)
try :
app.run(args.url, token)
except KeyboardInterrupt:
print("Ctrl-C detected. Exiting!")
finally:
app.leave()
# Let leave finish
time.sleep(2)
if __name__ == '__main__':
main() |