Jon Taylor commited on
Commit
b3de037
1 Parent(s): 71f583a
Dockerfile CHANGED
@@ -51,11 +51,11 @@ RUN cd frontend && npm install
51
 
52
  # Copy frontend app and build
53
  COPY --chown=user frontend/ frontend/
54
- #RUN cd frontend && npm run build
55
 
56
  # Copy everything else
57
  COPY --chown=user app/ app/
58
  COPY --chown=user server.py server.py
59
 
60
- #ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libtcmalloc.so.4
61
  CMD ["python3", "server.py"]
 
51
 
52
  # Copy frontend app and build
53
  COPY --chown=user frontend/ frontend/
54
+ RUN cd frontend && npm run build
55
 
56
  # Copy everything else
57
  COPY --chown=user app/ app/
58
  COPY --chown=user server.py server.py
59
 
60
+ ENV LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libtcmalloc.so.4
61
  CMD ["python3", "server.py"]
app/bot.py CHANGED
@@ -30,13 +30,14 @@ class DailyVision(EventHandler):
30
  self.__pipeline = Pipeline
31
  self.__camera = None
32
  self.__time = time.time()
33
- self.__queue = queue.Queue()
34
  self.__app_quit = False
35
  self.__image_buffer = None
36
  self.__bot_name = bot_name
37
  self.__room_url = room_url
38
  self.__room_name = room_name
39
  self.__expiration = expiration
 
40
  self.__idle = idle
41
 
42
  # Create the pipeline (this might take a moment)
@@ -101,7 +102,7 @@ class DailyVision(EventHandler):
101
  })
102
 
103
  def process_frames(self):
104
- params = Pipeline.InputParams()
105
 
106
  while not self.__app_quit:
107
  # Is anyone watching?
@@ -114,6 +115,7 @@ class DailyVision(EventHandler):
114
  self.logger.info(f"Expiration timer exceeded. Exiting...")
115
  self.__app_quit = True
116
  break
 
117
  try:
118
  #video_frame = self.__queue.get(timeout=5)
119
  video_frame = self.__image_buffer
@@ -124,7 +126,8 @@ class DailyVision(EventHandler):
124
  self.__camera.write_frame(result_image.tobytes())
125
  except queue.Empty:
126
  pass
127
-
 
128
  def on_video_frame(self, participant_id, video_frame):
129
  # Process ~15 frames per second (considering incoming frames at 30fps).
130
  if time.time() - self.__time > float(os.getenv("FPS_CAP", 0.0333)):
@@ -132,16 +135,18 @@ class DailyVision(EventHandler):
132
  self.__image_buffer = video_frame
133
  #self.__queue.put(video_frame)
134
 
135
- def wave(self, emoji="👋"):
 
 
 
 
 
 
 
 
136
  self.__client.send_app_message(
137
  {
138
- "event": "sync-emoji-reaction",
139
- "reaction": {
140
- "emoji": emoji,
141
- "room": "main-room",
142
- "sessionId": "bot",
143
- "id": time.time(),
144
- },
145
  }
146
  )
147
 
 
30
  self.__pipeline = Pipeline
31
  self.__camera = None
32
  self.__time = time.time()
33
+ #self.__queue = queue.Queue()
34
  self.__app_quit = False
35
  self.__image_buffer = None
36
  self.__bot_name = bot_name
37
  self.__room_url = room_url
38
  self.__room_name = room_name
39
  self.__expiration = expiration
40
+ self.__params = Pipeline.InputParams()
41
  self.__idle = idle
42
 
43
  # Create the pipeline (this might take a moment)
 
102
  })
103
 
104
  def process_frames(self):
105
+ params = self.__params
106
 
107
  while not self.__app_quit:
108
  # Is anyone watching?
 
115
  self.logger.info(f"Expiration timer exceeded. Exiting...")
116
  self.__app_quit = True
117
  break
118
+ """
119
  try:
120
  #video_frame = self.__queue.get(timeout=5)
121
  video_frame = self.__image_buffer
 
126
  self.__camera.write_frame(result_image.tobytes())
127
  except queue.Empty:
128
  pass
129
+ """
130
+
131
  def on_video_frame(self, participant_id, video_frame):
132
  # Process ~15 frames per second (considering incoming frames at 30fps).
133
  if time.time() - self.__time > float(os.getenv("FPS_CAP", 0.0333)):
 
135
  self.__image_buffer = video_frame
136
  #self.__queue.put(video_frame)
137
 
138
+ def on_app_message(self, message, sender):
139
+ # Update pipeline settings based on message data
140
+ print(message)
141
+ self.__params = self.__pipeline.InputParams(**message)
142
+ print(self.__params)
143
+ #print(self.__pipeline.Info())
144
+ return
145
+
146
+ def wave(self):
147
  self.__client.send_app_message(
148
  {
149
+ "prompt": self.__params.prompt,
 
 
 
 
 
 
150
  }
151
  )
152
 
frontend/app/components/Call.js CHANGED
@@ -1,17 +1,18 @@
1
  "use client";
2
 
3
- import { useCallback, useEffect, useState } from "react";
4
- import Card from "../components/Card";
5
- import { VideoCameraIcon, PaintBrushIcon } from "@heroicons/react/24/outline";
6
- import Avatar from "../components/Avatar";
7
- import CreateRoom from "../components/CreateRoom";
8
- import { apiUrl } from "../utils";
9
- import Join from "../components/Joining";
10
  import {
11
  DailyVideo,
 
12
  useLocalSessionId,
13
  useParticipantIds,
14
  } from "@daily-co/daily-react";
 
 
 
 
 
 
 
15
 
16
  const STATE_IDLE = "idle";
17
  const STATE_JOINING = "joining";
@@ -24,8 +25,13 @@ export default function Call() {
24
  const [callState, setCallState] = useState(STATE_IDLE);
25
  const [roomUrl, setRoomUrl] = useState();
26
  const [botState, setBotState] = useState(BOT_STATE_STARTING);
 
 
27
  const localSessionId = useLocalSessionId();
28
  const participantIds = useParticipantIds({ filter: "remote" });
 
 
 
29
 
30
  const start = useCallback(async () => {
31
  const resp = await fetch(`${apiUrl}/start`, {
@@ -62,11 +68,11 @@ export default function Call() {
62
  return <Join roomUrl={roomUrl} onJoin={() => setCallState(STATE_JOINED)} />;
63
  }
64
 
 
65
  // Main call loop
66
  return (
67
- <main className="container py-24">
68
- {roomUrl}
69
- <div className="grid grid-cols-2 grid-flow-col gap-4">
70
  <div>
71
  <Card headerText="Local Webcam" HeaderIcon={VideoCameraIcon}>
72
  <div className="overflow-hidden bg-gray-50 sm:rounded-lg">
@@ -75,7 +81,31 @@ export default function Call() {
75
  </div>
76
  </div>
77
  </Card>
78
- <div className="relative">Config - Resolution, Mbps, FPS</div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
  </div>
80
  <div>
81
  <Card headerText="Inference" HeaderIcon={PaintBrushIcon}>
 
1
  "use client";
2
 
 
 
 
 
 
 
 
3
  import {
4
  DailyVideo,
5
+ useAppMessage,
6
  useLocalSessionId,
7
  useParticipantIds,
8
  } from "@daily-co/daily-react";
9
+ import { PaintBrushIcon, VideoCameraIcon } from "@heroicons/react/24/outline";
10
+ import { useCallback, useEffect, useState } from "react";
11
+ import Avatar from "../components/Avatar";
12
+ import Card from "../components/Card";
13
+ import CreateRoom from "../components/CreateRoom";
14
+ import Join from "../components/Joining";
15
+ import { apiUrl } from "../utils";
16
 
17
  const STATE_IDLE = "idle";
18
  const STATE_JOINING = "joining";
 
25
  const [callState, setCallState] = useState(STATE_IDLE);
26
  const [roomUrl, setRoomUrl] = useState();
27
  const [botState, setBotState] = useState(BOT_STATE_STARTING);
28
+ const [params, setParams] = useState({});
29
+
30
  const localSessionId = useLocalSessionId();
31
  const participantIds = useParticipantIds({ filter: "remote" });
32
+ const sendAppMessage = useAppMessage({
33
+ onAppMessage: useCallback((ev) => setParams(ev.data), []),
34
+ });
35
 
36
  const start = useCallback(async () => {
37
  const resp = await fetch(`${apiUrl}/start`, {
 
68
  return <Join roomUrl={roomUrl} onJoin={() => setCallState(STATE_JOINED)} />;
69
  }
70
 
71
+ console.log(params);
72
  // Main call loop
73
  return (
74
+ <main className="container py-12">
75
+ <div className="grid grid-cols-2 grid-flow-col gap-12">
 
76
  <div>
77
  <Card headerText="Local Webcam" HeaderIcon={VideoCameraIcon}>
78
  <div className="overflow-hidden bg-gray-50 sm:rounded-lg">
 
81
  </div>
82
  </div>
83
  </Card>
84
+ <div className="relative">
85
+ <div>
86
+ <label
87
+ htmlFor="comment"
88
+ className="block text-sm font-medium leading-6 text-gray-900"
89
+ >
90
+ Add your comment
91
+ </label>
92
+ <div className="mt-2">
93
+ <textarea
94
+ rows={4}
95
+ name="comment"
96
+ id="comment"
97
+ className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
98
+ defaultValue={params.prompt || ""}
99
+ />
100
+ </div>
101
+ </div>
102
+ Config - Resolution, Mbps, FPS
103
+ <button
104
+ onClick={() => sendAppMessage({ prompt: "Big ol' car" }, "*")}
105
+ >
106
+ Send test app message
107
+ </button>
108
+ </div>
109
  </div>
110
  <div>
111
  <Card headerText="Inference" HeaderIcon={PaintBrushIcon}>
frontend/app/components/CreateRoom.js CHANGED
@@ -1,9 +1,11 @@
1
- import { ArrowRightIcon } from "@heroicons/react/20/solid";
2
  import { useState } from "react";
3
  import { apiUrl } from "../utils";
4
 
5
  export default function CreateRoom({ onCreateRoom }) {
6
  const [fetching, setFetching] = useState(false);
 
 
7
 
8
  async function create() {
9
  setFetching(true);
@@ -48,6 +50,45 @@ export default function CreateRoom({ onCreateRoom }) {
48
  <ArrowRightIcon className="-h-5 w-5" aria-hidden="true" />
49
  </button>
50
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  </div>
52
  </div>
53
  );
 
1
+ import { ArrowRightIcon, ChevronRightIcon } from "@heroicons/react/20/solid";
2
  import { useState } from "react";
3
  import { apiUrl } from "../utils";
4
 
5
  export default function CreateRoom({ onCreateRoom }) {
6
  const [fetching, setFetching] = useState(false);
7
+ const [roomUrl, setRoomUrl] = useState();
8
+ const [showManual, setShowManual] = useState(false);
9
 
10
  async function create() {
11
  setFetching(true);
 
50
  <ArrowRightIcon className="-h-5 w-5" aria-hidden="true" />
51
  </button>
52
  </div>
53
+
54
+ <hr className="my-6" />
55
+
56
+ <div
57
+ className="inline-flex text-sm text-gray-500 cursor-pointer"
58
+ onClick={() => setShowManual(!showManual)}
59
+ >
60
+ Join an existing room
61
+ <ChevronRightIcon
62
+ className={`w-5 h-5 text-gray-300 transition-transform ${
63
+ showManual && "rotate-90"
64
+ }`}
65
+ />
66
+ </div>
67
+
68
+ {showManual && (
69
+ <div className="mt-5 sm:flex sm:items-center">
70
+ <div className="w-full">
71
+ <label htmlFor="room" className="sr-only">
72
+ Daily Room URL
73
+ </label>
74
+ <input
75
+ type="text"
76
+ name="room"
77
+ id="room"
78
+ className="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
79
+ placeholder="https://..."
80
+ onChange={(e) => setRoomUrl(e.target.value)}
81
+ />
82
+ </div>
83
+ <button
84
+ type="submit"
85
+ onClick={() => onCreateRoom(roomUrl)}
86
+ className="mt-3 inline-flex w-full items-center justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600 sm:ml-3 sm:mt-0 sm:w-auto"
87
+ >
88
+ Join
89
+ </button>
90
+ </div>
91
+ )}
92
  </div>
93
  </div>
94
  );
frontend/package.json CHANGED
@@ -14,11 +14,13 @@
14
  "@headlessui/react": "^1.7.17",
15
  "@heroicons/react": "^2.0.18",
16
  "next": "14.0.3",
 
17
  "react": "^18",
18
  "react-dom": "^18",
19
  "recoil": "^0.7.7"
20
  },
21
  "devDependencies": {
 
22
  "autoprefixer": "^10.0.1",
23
  "eslint": "^8",
24
  "eslint-config-next": "14.0.3",
 
14
  "@headlessui/react": "^1.7.17",
15
  "@heroicons/react": "^2.0.18",
16
  "next": "14.0.3",
17
+ "nextjs": "^0.0.3",
18
  "react": "^18",
19
  "react-dom": "^18",
20
  "recoil": "^0.7.7"
21
  },
22
  "devDependencies": {
23
+ "@tailwindcss/forms": "^0.5.7",
24
  "autoprefixer": "^10.0.1",
25
  "eslint": "^8",
26
  "eslint-config-next": "14.0.3",
frontend/tailwind.config.js CHANGED
@@ -24,5 +24,5 @@ module.exports = {
24
  },
25
  },
26
  },
27
- plugins: [],
28
  };
 
24
  },
25
  },
26
  },
27
+ plugins: [require("@tailwindcss/forms")],
28
  };
frontend/yarn.lock CHANGED
@@ -285,6 +285,13 @@
285
  dependencies:
286
  tslib "^2.4.0"
287
 
 
 
 
 
 
 
 
288
  "@types/json5@^0.0.29":
289
  version "0.0.29"
290
  resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
@@ -1721,6 +1728,11 @@ micromatch@^4.0.4, micromatch@^4.0.5:
1721
  braces "^3.0.2"
1722
  picomatch "^2.3.1"
1723
 
 
 
 
 
 
1724
  minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
1725
  version "3.1.2"
1726
  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
@@ -1785,6 +1797,11 @@ [email protected]:
1785
  "@next/swc-win32-ia32-msvc" "14.0.3"
1786
  "@next/swc-win32-x64-msvc" "14.0.3"
1787
 
 
 
 
 
 
1788
  node-releases@^2.0.14:
1789
  version "2.0.14"
1790
  resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b"
 
285
  dependencies:
286
  tslib "^2.4.0"
287
 
288
+ "@tailwindcss/forms@^0.5.7":
289
+ version "0.5.7"
290
+ resolved "https://registry.yarnpkg.com/@tailwindcss/forms/-/forms-0.5.7.tgz#db5421f062a757b5f828bc9286ba626c6685e821"
291
+ integrity sha512-QE7X69iQI+ZXwldE+rzasvbJiyV/ju1FGHH0Qn2W3FKbuYtqp8LKcy6iSw79fVUT5/Vvf+0XgLCeYVG+UV6hOw==
292
+ dependencies:
293
+ mini-svg-data-uri "^1.2.3"
294
+
295
  "@types/json5@^0.0.29":
296
  version "0.0.29"
297
  resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
 
1728
  braces "^3.0.2"
1729
  picomatch "^2.3.1"
1730
 
1731
+ mini-svg-data-uri@^1.2.3:
1732
+ version "1.4.4"
1733
+ resolved "https://registry.yarnpkg.com/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz#8ab0aabcdf8c29ad5693ca595af19dd2ead09939"
1734
+ integrity sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==
1735
+
1736
  minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
1737
  version "3.1.2"
1738
  resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
 
1797
  "@next/swc-win32-ia32-msvc" "14.0.3"
1798
  "@next/swc-win32-x64-msvc" "14.0.3"
1799
 
1800
+ nextjs@^0.0.3:
1801
+ version "0.0.3"
1802
+ resolved "https://registry.yarnpkg.com/nextjs/-/nextjs-0.0.3.tgz#4f4d1d6a257be920d9b9649d4d9522c724a4e543"
1803
+ integrity sha512-mYbDUo4/sRAZ8TqK63PCpYnFiLg7BICG/ot9+guOrUKd4/Fo71ZmEQ41IZbH6nqbQvG7SXTBuofJXAIWfNho0w==
1804
+
1805
  node-releases@^2.0.14:
1806
  version "2.0.14"
1807
  resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b"