arcacolab commited on
Commit
a531340
ยท
verified ยท
1 Parent(s): e71af1d

Upload runcomfy_gd.py

Browse files
Files changed (1) hide show
  1. runcomfy_gd.py +398 -0
runcomfy_gd.py ADDED
@@ -0,0 +1,398 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import os
3
+ import subprocess
4
+ import time
5
+ import atexit
6
+ import sys
7
+ import re
8
+ import argparse
9
+ import shlex
10
+ import io
11
+ import select
12
+
13
+ # --- ์„ค์ • ๋ณ€์ˆ˜ ---
14
+ COMFYUI_PORT = 8188
15
+ # ํ„ฐ๋„ ์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ ๊ฒฝ๋กœ (ComfyUI ๋””๋ ‰ํ† ๋ฆฌ ๋ฐ–, ์ฆ‰ ๋ถ€๋ชจ ๋””๋ ‰ํ† ๋ฆฌ)
16
+ TUNNEL_SCRIPT_PATH = "../gradio-tunnel.py"
17
+
18
+ # Gradio Tunnel Script ๋‚ด์šฉ (์ด์ „ ๋‹จ๊ณ„์—์„œ ์‚ฌ์šฉํ–ˆ๋˜ ๋‚ด์šฉ ๊ทธ๋Œ€๋กœ)
19
+ GRADIO_TUNNEL_SCRIPT_CONTENT = r"""
20
+ import atexit
21
+ import os
22
+ import platform
23
+ import re
24
+ import stat
25
+ import subprocess
26
+ import sys
27
+ import time
28
+ import secrets
29
+ from pathlib import Path
30
+ from typing import List, Optional
31
+
32
+ import requests
33
+
34
+ VERSION = "0.2"
35
+ CURRENT_TUNNELS: List["Tunnel"] = []
36
+
37
+ machine = platform.machine()
38
+ if machine == "x86_64":
39
+ machine = "amd64"
40
+
41
+ BINARY_REMOTE_NAME = f"frpc_{platform.system().lower()}_{machine.lower()}"
42
+ EXTENSION = ".exe" if os.name == "nt" else ""
43
+ BINARY_URL = f"https://cdn-media.huggingface.co/frpc-gradio-{VERSION}/{BINARY_REMOTE_NAME}{EXTENSION}"
44
+
45
+ BINARY_FILENAME = f"{BINARY_REMOTE_NAME}_v{VERSION}"
46
+ BINARY_FOLDER = Path(__file__).parent.absolute()
47
+ BINARY_PATH = f"{BINARY_FOLDER / BINARY_FILENAME}"
48
+
49
+ TUNNEL_TIMEOUT_SECONDS = 30
50
+ TUNNEL_ERROR_MESSAGE = (
51
+ "Could not create share URL. "
52
+ "Please check the appended log from frpc for more information:"
53
+ )
54
+
55
+ GRADIO_API_SERVER = "https://api.gradio.app/v2/tunnel-request"
56
+ GRADIO_SHARE_SERVER_ADDRESS = None
57
+
58
+
59
+ class Tunnel:
60
+ def __init__(self, remote_host, remote_port, local_host, local_port, share_token):
61
+ self.proc = None
62
+ self.url = None
63
+ self.remote_host = remote_host
64
+ self.remote_port = remote_port
65
+ self.local_host = local_host
66
+ self.local_port = local_port
67
+ self.share_token = share_token
68
+
69
+ @staticmethod
70
+ def download_binary():
71
+ if not Path(BINARY_PATH).exists():
72
+ resp = requests.get(BINARY_URL)
73
+
74
+ if resp.status_code == 403:
75
+ raise OSError(
76
+ f"Cannot set up a share link as this platform is incompatible. Please "
77
+ f"create a GitHub issue with information about your platform: {platform.uname()}"
78
+ )
79
+
80
+ resp.raise_for_status()
81
+
82
+ # Save file data to local copy
83
+ with open(BINARY_PATH, "wb") as file:
84
+ file.write(resp.content)
85
+ st = os.stat(BINARY_PATH)
86
+ os.chmod(BINARY_PATH, st.st_mode | stat.S_IEXEC)
87
+
88
+ def start_tunnel(self) -> str:
89
+ self.download_binary()
90
+ self.url = self._start_tunnel(BINARY_PATH)
91
+ return self.url
92
+
93
+ def kill(self):
94
+ if self.proc is not None:
95
+ print(f"ํ„ฐ๋„ ์ข…๋ฃŒ ์ค‘: {self.local_host}:{self.local_port} <> {self.url}")
96
+ self.proc.terminate()
97
+ self.proc = None
98
+
99
+ def _start_tunnel(self, binary: str) -> str:
100
+ CURRENT_TUNNELS.append(self)
101
+ command = [
102
+ binary,
103
+ "http",
104
+ "-n",
105
+ self.share_token,
106
+ "-l",
107
+ str(self.local_port),
108
+ "-i",
109
+ self.local_host,
110
+ "--uc",
111
+ "--sd",
112
+ "random",
113
+ "--ue",
114
+ "--server_addr",
115
+ f"{self.remote_host}:{self.remote_port}",
116
+ "--disable_log_color",
117
+ ]
118
+ self.proc = subprocess.Popen(
119
+ command, stdout=subprocess.PIPE, stderr=subprocess.PIPE
120
+ )
121
+ atexit.register(self.kill)
122
+ return self._read_url_from_tunnel_stream()
123
+
124
+ def _read_url_from_tunnel_stream(self) -> str:
125
+ start_timestamp = time.time()
126
+
127
+ log = []
128
+ url = ""
129
+
130
+ def _raise_tunnel_error():
131
+ log_text = "\\n".join(log)
132
+ print(log_text, file=sys.stderr)
133
+ raise ValueError(f"{TUNNEL_ERROR_MESSAGE}\\n{log_text}")
134
+
135
+ while url == "":
136
+ if time.time() - start_timestamp >= TUNNEL_TIMEOUT_SECONDS:
137
+ _raise_tunnel_error()
138
+
139
+ assert self.proc is not None
140
+ if self.proc.stdout is None:
141
+ continue
142
+
143
+ line = self.proc.stdout.readline()
144
+ try:
145
+ line = line.decode("utf-8")
146
+ except UnicodeDecodeError:
147
+ continue
148
+
149
+ if line == "":
150
+ time.sleep(0.01)
151
+ continue
152
+
153
+ log.append(line.strip())
154
+
155
+ if "start proxy success" in line:
156
+ result = re.search("start proxy success: (.+)\\n", line)
157
+ if result is None:
158
+ _raise_tunnel_error()
159
+ else:
160
+ url = result.group(1)
161
+ elif "login to server failed" in line:
162
+ _raise_tunnel_error()
163
+
164
+ if self.proc.poll() is not None and url == "":
165
+ _raise_tunnel_error()
166
+
167
+ return url
168
+
169
+
170
+ def setup_tunnel(
171
+ local_host: str,
172
+ local_port: int,
173
+ share_token: str,
174
+ share_server_address: Optional[str],
175
+ ) -> str:
176
+ share_server_address = (
177
+ GRADIO_SHARE_SERVER_ADDRESS
178
+ if share_server_address is None
179
+ else share_server_address
180
+ )
181
+ if share_server_address is None:
182
+ response = requests.get(GRADIO_API_SERVER)
183
+ if not (response and response.status_code == 200):
184
+ raise RuntimeError("Could not get share link from Gradio API Server.")
185
+ payload = response.json()[0]
186
+ remote_host, remote_port = payload["host"], int(payload["port"])
187
+ else:
188
+ remote_host, remote_port = share_server_address.split(":")
189
+ remote_port = int(remote_port)
190
+ try:
191
+ tunnel = Tunnel(remote_host, remote_port, local_host, local_port, share_token)
192
+ address = tunnel.start_tunnel()
193
+ return address
194
+ except Exception as e:
195
+ raise RuntimeError(str(e)) from e
196
+
197
+ # ์ด ์Šคํฌ๋ฆฝํŠธ๋Š” ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ์ธ์ž๋กœ ๋ฐ›์•„ Gradio ํ„ฐ๋„๋ง์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
198
+ if __name__ == "__main__":
199
+ if len(sys.argv) < 2:
200
+ print("์‚ฌ์šฉ๋ฒ•: python gradio-tunnel.py <port_number>", file=sys.stderr)
201
+ sys.exit(1)
202
+
203
+ try:
204
+ port = int(sys.argv[1])
205
+ except ValueError:
206
+ print("์˜ค๋ฅ˜: ํฌํŠธ ๋ฒˆํ˜ธ๋Š” ์ •์ˆ˜์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.", file=sys.stderr)
207
+ sys.exit(1)
208
+
209
+ try:
210
+ address = setup_tunnel(
211
+ "127.0.0.1",
212
+ port,
213
+ secrets.token_urlsafe(32),
214
+ None,
215
+ )
216
+ print(address, flush=True)
217
+ # ํ„ฐ๋„ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋˜์ง€ ์•Š๋„๋ก ๋Œ€๊ธฐ
218
+ time.sleep(3600 * 24 * 3)
219
+ except Exception as e:
220
+ print(f"ํ„ฐ๋„ ์‹คํ–‰ ์ค‘ ์น˜๋ช…์ ์ธ ์˜ค๋ฅ˜ ๋ฐœ์ƒ: {{e}}", file=sys.stderr)
221
+ sys.exit(1)
222
+
223
+ """
224
+
225
+ # --- 1. main ํ•จ์ˆ˜ (์ธ์ž ์ฒ˜๋ฆฌ ๊ฐ„์†Œํ™”) ---
226
+ def main():
227
+ # requests ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜๋ฅผ ๋ณด์žฅํ•ฉ๋‹ˆ๋‹ค.
228
+ try:
229
+ import requests
230
+ except ImportError:
231
+ print("ํ•„์ˆ˜ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ 'requests'๊ฐ€ ์„ค์น˜๋˜์–ด ์žˆ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์„ค์น˜๋ฅผ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค.")
232
+ try:
233
+ subprocess.check_call([sys.executable, "-m", "pip", "install", "requests"])
234
+ # import requests # ์žฌ์„ค์น˜ ํ›„ ์žฌ์ž„ํฌํŠธ๊ฐ€ ํ•„์š”ํ•˜์ง€๋งŒ, main ํ•จ์ˆ˜ ๋ฐ–์—์„œ ์ด๋ฏธ ์ž„ํฌํŠธ ์‹œ๋„๋˜์—ˆ์œผ๋ฏ€๋กœ ์ƒ๋žต
235
+ except Exception as e:
236
+ print(f"๊ฒฝ๊ณ : 'requests' ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์„ค์น˜ ์‹คํŒจ. ํ„ฐ๋„๋ง ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ค๋ฅ˜: {e}")
237
+
238
+ # runcomfy.py์— ์ „๋‹ฌ๋œ ๋ชจ๋“  ์ธ์ž(์Šคํฌ๋ฆฝํŠธ ์ด๋ฆ„ ์ œ์™ธ)๋ฅผ ComfyUI์— ์ „๋‹ฌํ•  ์ธ์ž๋กœ ์‚ฌ์šฉ
239
+ comfyui_args = sys.argv[1:]
240
+
241
+ # --- ํ•„์ˆ˜ ๊ฒฝ๋กœ ์„ค์ • ๋ฐ ์ด๋™ ---
242
+ comfyui_dir = "/content/drive/MyDrive/ONECLICK/ComfyUI"
243
+ # ๋˜๋Š” f-string ์‚ฌ์šฉ: comfyui_dir = f"{WS}/ComfyUI"
244
+
245
+ print(f"ComfyUI ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์ด๋™ ์ค‘: {comfyui_dir}")
246
+ try:
247
+ os.chdir(comfyui_dir)
248
+ except FileNotFoundError:
249
+ print(f"์˜ค๋ฅ˜: ๋””๋ ‰ํ† ๋ฆฌ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค: {comfyui_dir}. ๊ฒฝ๋กœ๋ฅผ ํ™•์ธํ•ด ์ฃผ์„ธ์š”.")
250
+
251
+ # ํ„ฐ๋„ ์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์„ ์ €์žฅ
252
+ print("ํ„ฐ๋„ ์Šคํฌ๋ฆฝํŠธ ์ €์žฅ ์ค‘...")
253
+ try:
254
+ # TUNNEL_SCRIPT_PATH๋Š” '../gradio-tunnel.py'์ด๋ฏ€๋กœ, CWD์˜ ๋ถ€๋ชจ์— ์ €์žฅ๋จ
255
+ with open(TUNNEL_SCRIPT_PATH, "w") as f:
256
+ f.write(GRADIO_TUNNEL_SCRIPT_CONTENT)
257
+ except Exception as e:
258
+ print(f"์˜ค๋ฅ˜: ํ„ฐ๋„ ์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ ์ €์žฅ ์‹คํŒจ: {e}")
259
+ sys.exit(1)
260
+
261
+ # --- 2. ComfyUI ์„œ๋ฒ„ ์‹คํ–‰ (๋ฐฑ๊ทธ๋ผ์šด๋“œ) ---
262
+ print("\nComfyUI ์„œ๋ฒ„๋ฅผ ๋ฐฑ๊ทธ๋ผ์šด๋“œ๋กœ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค...")
263
+ comfyui_base_args = [
264
+ "./main.py",
265
+ "--listen", "127.0.0.1",
266
+ "--port", str(COMFYUI_PORT),
267
+ ]
268
+ comfyui_command = ["python"] + comfyui_base_args + comfyui_args
269
+
270
+ comfyui_proc = subprocess.Popen(
271
+ comfyui_command,
272
+ stdout=subprocess.PIPE,
273
+ stderr=subprocess.STDOUT,
274
+ text=True
275
+ )
276
+ atexit.register(comfyui_proc.terminate)
277
+
278
+ # --- 3. Gradio ํ„ฐ๋„๋ง ์Šคํฌ๋ฆฝํŠธ ์‹คํ–‰ (๋ฐฑ๊ทธ๋ผ์šด๋“œ) ---
279
+ print(f"์„œ๋ฒ„๊ฐ€ ํฌํŠธ {COMFYUI_PORT}๋ฅผ ์—ด ๋•Œ๊นŒ์ง€ 15์ดˆ ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค...")
280
+ time.sleep(15)
281
+
282
+ print(f"\nGradio ํ„ฐ๋„ ํด๋ผ์ด์–ธํŠธ ์‹œ์ž‘ ์ค‘ (ํฌํŠธ {COMFYUI_PORT})...")
283
+ tunnel_command = ["python", TUNNEL_SCRIPT_PATH, str(COMFYUI_PORT)]
284
+
285
+ tunnel_proc = subprocess.Popen(
286
+ tunnel_command,
287
+ stdout=subprocess.PIPE,
288
+ stderr=subprocess.STDOUT,
289
+ text=True
290
+ )
291
+ atexit.register(tunnel_proc.terminate)
292
+
293
+ # --- 4. ํ„ฐ๋„ ์ฃผ์†Œ ์ถœ๋ ฅ ๋ฐ ํ”„๋กœ์„ธ์Šค ์œ ์ง€ ---
294
+ share_url = None
295
+ start_time = time.time()
296
+ print("\n[ํ„ฐ๋„ ์ถœ๋ ฅ - Gradio ๋กœ๊ทธ]")
297
+
298
+ # ํ„ฐ๋„ URL์„ ์ฐพ๋Š” ๋ฃจํ”„
299
+ while time.time() - start_time < 60 and tunnel_proc.poll() is None:
300
+ line = tunnel_proc.stdout.readline()
301
+
302
+ if line:
303
+ line_stripped = line.strip()
304
+ print(f"[TUNNEL] {line_stripped}")
305
+
306
+ # URL ํŒจํ„ด ์ฐพ๊ธฐ
307
+ if line_stripped.startswith(("https://", "http://")):
308
+ share_url = line_stripped
309
+ break
310
+
311
+ time.sleep(0.01)
312
+
313
+ if share_url:
314
+ print("\n" + "="*50)
315
+ print(f"๐ŸŽ‰ **ComfyUI ๊ณต์œ  URL์ด ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค:** {share_url}")
316
+ print("์ด ์ฃผ์†Œ๋กœ ์ ‘์†ํ•˜์„ธ์š”.")
317
+ print("="*50)
318
+
319
+ else:
320
+ # --- ํ„ฐ๋„๋ง ์‹คํŒจ ์‹œ ์˜ค๋ฅ˜ ์ง„๋‹จ ๋กœ์ง (communicate() ์ œ๊ฑฐ) ---
321
+ print("\n" + "="*50)
322
+ print("๐Ÿšจ **ํ„ฐ๋„๋ง ํด๋ผ์ด์–ธํŠธ ์‹คํ–‰์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค!**")
323
+ print("์•„๋ž˜ ๋กœ๊ทธ์—์„œ ์˜ค๋ฅ˜ ์›์ธ์„ ํ™•์ธํ•˜์„ธ์š”.")
324
+ print("="*50)
325
+
326
+ # 1. ํ„ฐ๋„ ํ”„๋กœ์„ธ์Šค ์ข…๋ฃŒ ์‹œ ๋‚จ์€ ๋กœ๊ทธ ํ™•์ธ ๋ฐ ์ถœ๋ ฅ
327
+ print("\n--- ํ„ฐ๋„ ํด๋ผ์ด์–ธํŠธ ์ตœ์ข… ๋กœ๊ทธ ---")
328
+ tunnel_proc.stdout.seek(0) # ํ„ฐ๋„ stdout์˜ ์ฒ˜์Œ์œผ๋กœ ์ด๋™
329
+ tunnel_logs = tunnel_proc.stdout.read()
330
+ if tunnel_logs:
331
+ print(tunnel_logs.strip())
332
+ else:
333
+ print("ํ„ฐ๋„ ๋กœ๊ทธ๊ฐ€ ๋ฐœ๊ฒฌ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ์ฆ‰์‹œ ์ข…๋ฃŒ๋œ ๊ฒƒ์œผ๋กœ ๋ณด์ž…๋‹ˆ๋‹ค.")
334
+
335
+ # 2. ComfyUI ํ”„๋กœ์„ธ์Šค ๋กœ๊ทธ ํ™•์ธ (communicate ๋Œ€์‹  read())
336
+ # ComfyUI์˜ stdout์ด ๋‹ซํžˆ์ง€ ์•Š๋„๋ก, ๋น„์ฐจ๋‹จ ๋ฐฉ์‹์œผ๋กœ ํ˜„์žฌ๊นŒ์ง€์˜ ๋กœ๊ทธ๋ฅผ ์ฝ์Šต๋‹ˆ๋‹ค.
337
+ print("\n--- ComfyUI ์ดˆ๊ธฐ ๋กœ๊ทธ ํ™•์ธ (ComfyUI๊ฐ€ ํฌํŠธ๋ฅผ ์—ด์—ˆ๋Š”์ง€ ํ™•์ธ) ---")
338
+ # subprocess.PIPE๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ์ฐจ๋‹จ ๋ชจ๋“œ์ด๋ฏ€๋กœ, read()๋ฅผ ์“ฐ๊ธฐ ์ „์—
339
+ # ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด, ํ˜„์žฌ๊นŒ์ง€ ๋ฒ„ํผ์— ์Œ“์ธ ๋กœ๊ทธ๋ฅผ ์ตœ๋Œ€ํ•œ ์ถœ๋ ฅํ•ด ๋ด…๋‹ˆ๋‹ค.
340
+ # ์ด ์‹œ์ ์—์„œ๋Š” 15์ดˆ ๋™์•ˆ ๋Œ€๊ธฐํ–ˆ์œผ๋ฏ€๋กœ, ComfyUI๊ฐ€ ์‹œ์ž‘ ์‹œ ์ถœ๋ ฅํ•˜๋Š” ๋กœ๊ทธ๊ฐ€ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
341
+ try:
342
+ # select๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋น„์ฐจ๋‹จ ๋ฐฉ์‹์œผ๋กœ ์ฝ์„ ์ˆ˜ ์žˆ๋„๋ก ์‹œ๋„ (Colab ํ™˜๊ฒฝ์—์„œ ํ•ญ์ƒ ์ž‘๋™ํ•˜์ง€๋Š” ์•Š์„ ์ˆ˜ ์žˆ์Œ)
343
+ if comfyui_proc.stdout is not None:
344
+ ready_to_read, _, _ = select.select([comfyui_proc.stdout], [], [], 0.5)
345
+ if ready_to_read:
346
+ comfy_logs = comfyui_proc.stdout.read()
347
+ print(comfy_logs.strip() if comfy_logs else "ComfyUI ๋กœ๊ทธ ๋ฒ„ํผ์— ๋‚ด์šฉ ์—†์Œ.")
348
+ else:
349
+ print("ComfyUI ๋กœ๊ทธ ๋ฒ„ํผ์— ๋‚ด์šฉ ์—†์Œ (500ms ๋Œ€๊ธฐ ํ›„).")
350
+ else:
351
+ print("ComfyUI stdout์ด None์ž…๋‹ˆ๋‹ค.")
352
+ except Exception as e:
353
+ print(f"ComfyUI ๋กœ๊ทธ ์ฝ๊ธฐ ์ค‘ ์˜ˆ์™ธ ๋ฐœ์ƒ: {e}")
354
+
355
+ raise RuntimeError("Gradio ํ„ฐ๋„๋ง์— ์‹คํŒจํ–ˆ์Šต๋‹ˆ๋‹ค. ์œ„์˜ ์ƒ์„ธ ๋กœ๊ทธ๋ฅผ ํ™•์ธํ•ด ์ฃผ์‹ญ์‹œ์˜ค.")
356
+
357
+
358
+ # ํ”„๋กœ์„ธ์Šค ์œ ์ง€๋ฅผ ์œ„ํ•œ ๋ฉ”์ธ ๋ฃจํ”„ (์ถฉ๋Œ ๋กœ๊ทธ ์ถœ๋ ฅ ๊ฐ•ํ™”)
359
+ try:
360
+ print("\n**ํ”„๋กœ์„ธ์Šค๋ฅผ ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค. Colab ์„ธ์…˜์ด ์—ฐ๊ฒฐ๋œ ๋™์•ˆ ํ„ฐ๋„์ด ์œ ์ง€๋ฉ๋‹ˆ๋‹ค.**")
361
+ print("์ค‘์ง€ํ•˜๋ ค๋ฉด ์ด ์…€์˜ ์‹คํ–‰์„ ๋ฉˆ์ถ”์„ธ์š”.")
362
+ while True:
363
+ # ComfyUI ๋กœ๊ทธ๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๋ชจ๋‘ ์ถœ๋ ฅ
364
+ comfy_line = comfyui_proc.stdout.readline()
365
+ if comfy_line:
366
+ print(comfy_line.strip())
367
+
368
+ if comfyui_proc.poll() is not None:
369
+ print("\n[์˜ค๋ฅ˜] ComfyUI ํ”„๋กœ์„ธ์Šค๊ฐ€ ์˜ˆ๊ธฐ์น˜ ์•Š๊ฒŒ ์ค‘์ง€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์„ธ์…˜์„ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.")
370
+ # ์ข…๋ฃŒ ์‹œ ๋‚จ์•„์žˆ๋Š” ๋ชจ๋“  ๋กœ๊ทธ๋ฅผ ์ถœ๋ ฅํ•˜์—ฌ ์›์ธ ํŒŒ์•…
371
+ print("\n--- ComfyUI ์ถฉ๋Œ ๋กœ๊ทธ (์›์ธ ๋ถ„์„์šฉ) ---")
372
+ print(comfyui_proc.stdout.read())
373
+ break
374
+
375
+ if tunnel_proc.poll() is not None:
376
+ print("\n[์˜ค๋ฅ˜] ํ„ฐ๋„ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์˜ˆ๊ธฐ์น˜ ์•Š๊ฒŒ ์ค‘์ง€๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์„ธ์…˜์„ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค.")
377
+ # ํ„ฐ๋„ ํ”„๋กœ์„ธ์Šค ์ข…๋ฃŒ ์‹œ ๋‚จ์€ ๋กœ๊ทธ ํ™•์ธ ๋ฐ ์ถœ๋ ฅ
378
+ print("\n--- ํ„ฐ๋„ ์ถฉ๋Œ ๋กœ๊ทธ (์›์ธ ๋ถ„์„์šฉ) ---")
379
+ print(tunnel_proc.stdout.read())
380
+ break
381
+
382
+ time.sleep(0.01)
383
+
384
+ except KeyboardInterrupt:
385
+ print("\n์‚ฌ์šฉ์ž๊ฐ€ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ค‘์ง€ํ–ˆ์Šต๋‹ˆ๋‹ค. (KeyboardInterrupt)")
386
+
387
+ finally:
388
+ print("\n๋ฐฑ๊ทธ๋ผ์šด๋“œ ํ”„๋กœ์„ธ์Šค ์ข…๋ฃŒ๋ฅผ ์‹œ๋„ํ•ฉ๋‹ˆ๋‹ค...")
389
+
390
+ if comfyui_proc.poll() is None:
391
+ comfyui_proc.terminate()
392
+ if tunnel_proc.poll() is None:
393
+ tunnel_proc.terminate()
394
+
395
+ print("๋ฐฑ๊ทธ๋ผ์šด๋“œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.")
396
+
397
+ if __name__ == '__main__':
398
+ main()