arcacolab commited on
Commit
3d77c68
ยท
verified ยท
1 Parent(s): 213d4d7

Upload 2 files

Browse files
Files changed (2) hide show
  1. newmain.py +253 -0
  2. newmain_gd.py +253 -0
newmain.py ADDED
@@ -0,0 +1,253 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import atexit
2
+ import os
3
+ import platform
4
+ import re
5
+ import stat
6
+ import subprocess
7
+ import sys
8
+ import time
9
+ import threading
10
+ from pathlib import Path
11
+ from typing import List, Optional
12
+
13
+ import requests
14
+
15
+ VERSION = "0.2"
16
+ CURRENT_TUNNELS: List["Tunnel"] = []
17
+
18
+ machine = platform.machine()
19
+ if machine == "x86_64":
20
+ machine = "amd64"
21
+
22
+ BINARY_REMOTE_NAME = f"frpc_{platform.system().lower()}_{machine.lower()}"
23
+ EXTENSION = ".exe" if os.name == "nt" else ""
24
+ BINARY_URL = f"https://cdn-media.huggingface.co/frpc-gradio-{VERSION}/{BINARY_REMOTE_NAME}{EXTENSION}"
25
+
26
+ BINARY_FILENAME = f"{BINARY_REMOTE_NAME}_v{VERSION}"
27
+ BINARY_FOLDER = Path(__file__).parent.absolute()
28
+ BINARY_PATH = f"{BINARY_FOLDER / BINARY_FILENAME}"
29
+
30
+ TUNNEL_TIMEOUT_SECONDS = 30
31
+ TUNNEL_ERROR_MESSAGE = (
32
+ "Could not create share URL. "
33
+ "Please check the appended log from frpc for more information:"
34
+ )
35
+
36
+ GRADIO_API_SERVER = "https://api.gradio.app/v2/tunnel-request"
37
+ GRADIO_SHARE_SERVER_ADDRESS = None
38
+
39
+
40
+ class Tunnel:
41
+ def __init__(self, remote_host, remote_port, local_host, local_port, share_token):
42
+ self.proc = None
43
+ self.url = None
44
+ self.remote_host = remote_host
45
+ self.remote_port = remote_port
46
+ self.local_host = local_host
47
+ self.local_port = local_port
48
+ self.share_token = share_token
49
+
50
+ @staticmethod
51
+ def download_binary():
52
+ if not Path(BINARY_PATH).exists():
53
+ resp = requests.get(BINARY_URL)
54
+
55
+ if resp.status_code == 403:
56
+ raise OSError(
57
+ f"Cannot set up a share link as this platform is incompatible. Please "
58
+ f"create a GitHub issue with information about your platform: {platform.uname()}"
59
+ )
60
+
61
+ resp.raise_for_status()
62
+
63
+ # Save file data to local copy
64
+ with open(BINARY_PATH, "wb") as file:
65
+ file.write(resp.content)
66
+ st = os.stat(BINARY_PATH)
67
+ os.chmod(BINARY_PATH, st.st_mode | stat.S_IEXEC)
68
+
69
+ def start_tunnel(self) -> str:
70
+ self.download_binary()
71
+ self.url = self._start_tunnel(BINARY_PATH)
72
+ return self.url
73
+
74
+ def kill(self):
75
+ if self.proc is not None:
76
+ print(f"Killing tunnel {self.local_host}:{self.local_port} <> {self.url}")
77
+ self.proc.terminate()
78
+ self.proc = None
79
+
80
+ def _start_tunnel(self, binary: str) -> str:
81
+ CURRENT_TUNNELS.append(self)
82
+ command = [
83
+ binary,
84
+ "http",
85
+ "-n",
86
+ self.share_token,
87
+ "-l",
88
+ str(self.local_port),
89
+ "-i",
90
+ self.local_host,
91
+ "--uc",
92
+ "--sd",
93
+ "random",
94
+ "--ue",
95
+ "--server_addr",
96
+ f"{self.remote_host}:{self.remote_port}",
97
+ "--disable_log_color",
98
+ ]
99
+ self.proc = subprocess.Popen(
100
+ command, stdout=subprocess.PIPE, stderr=subprocess.PIPE
101
+ )
102
+ atexit.register(self.kill)
103
+ return self._read_url_from_tunnel_stream()
104
+
105
+ def _read_url_from_tunnel_stream(self) -> str:
106
+ start_timestamp = time.time()
107
+
108
+ log = []
109
+ url = ""
110
+
111
+ def _raise_tunnel_error():
112
+ log_text = "\n".join(log)
113
+ print(log_text, file=sys.stderr)
114
+ raise ValueError(f"{TUNNEL_ERROR_MESSAGE}\n{log_text}")
115
+
116
+ while url == "":
117
+ # check for timeout and log
118
+ if time.time() - start_timestamp >= TUNNEL_TIMEOUT_SECONDS:
119
+ _raise_tunnel_error()
120
+
121
+ assert self.proc is not None
122
+ if self.proc.stdout is None:
123
+ continue
124
+
125
+ line = self.proc.stdout.readline()
126
+ line = line.decode("utf-8")
127
+
128
+ if line == "":
129
+ continue
130
+
131
+ log.append(line.strip())
132
+
133
+ if "start proxy success" in line:
134
+ result = re.search("start proxy success: (.+)\n", line)
135
+ if result is None:
136
+ _raise_tunnel_error()
137
+ else:
138
+ url = result.group(1)
139
+ elif "login to server failed" in line:
140
+ _raise_tunnel_error()
141
+
142
+ return url
143
+
144
+
145
+ def setup_tunnel(
146
+ local_host: str,
147
+ local_port: int,
148
+ share_token: str,
149
+ share_server_address: Optional[str],
150
+ ) -> str:
151
+ share_server_address = (
152
+ GRADIO_SHARE_SERVER_ADDRESS
153
+ if share_server_address is None
154
+ else share_server_address
155
+ )
156
+ if share_server_address is None:
157
+ response = requests.get(GRADIO_API_SERVER)
158
+ if not (response and response.status_code == 200):
159
+ raise RuntimeError("Could not get share link from Gradio API Server.")
160
+ payload = response.json()[0]
161
+ remote_host, remote_port = payload["host"], int(payload["port"])
162
+ else:
163
+ remote_host, remote_port = share_server_address.split(":")
164
+ remote_port = int(remote_port)
165
+ try:
166
+ tunnel = Tunnel(remote_host, remote_port, local_host, local_port, share_token)
167
+ address = tunnel.start_tunnel()
168
+ return address
169
+ except Exception as e:
170
+ raise RuntimeError(str(e)) from e
171
+
172
+
173
+ # Cloudflared ํ„ฐ๋„ URL๊ณผ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ €์žฅํ•  ์ „์—ญ ๋ณ€์ˆ˜
174
+ cloudflared_url = None
175
+ cloudflared_proc = None
176
+
177
+ def start_cloudflared_tunnel(port):
178
+ global cloudflared_url, cloudflared_proc
179
+ cloudflared_proc = subprocess.Popen(
180
+ ["cloudflared", "tunnel", "--url", f"http://127.0.0.1:{port}"],
181
+ stdout=subprocess.PIPE,
182
+ stderr=subprocess.PIPE
183
+ )
184
+ for line in cloudflared_proc.stderr:
185
+ l = line.decode()
186
+ if "trycloudflare.com " in l:
187
+ cloudflared_url = l[l.find("http"):].strip()
188
+ break
189
+
190
+
191
+ if __name__ == "__main__":
192
+ import secrets
193
+
194
+ print("๐Ÿš€ ComfyUI + ํ„ฐ๋„ ์‹œ์ž‘\n")
195
+
196
+ # 1. Gradio ํ„ฐ๋„ ์ƒ์„ฑ
197
+ gradio_url = setup_tunnel(
198
+ "127.0.0.1",
199
+ 8188,
200
+ secrets.token_urlsafe(32),
201
+ None,
202
+ )
203
+
204
+ # 2. Cloudflared ํ„ฐ๋„์„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ๋กœ ์‹œ์ž‘
205
+ cloudflared_thread = threading.Thread(
206
+ target=start_cloudflared_tunnel,
207
+ args=(8188,),
208
+ daemon=True
209
+ )
210
+ cloudflared_thread.start()
211
+
212
+ # Cloudflared URL์ด ์ƒ์„ฑ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ
213
+ for _ in range(20):
214
+ if cloudflared_url:
215
+ break
216
+ time.sleep(0.5)
217
+
218
+ # URL ์ถœ๋ ฅ
219
+ print(f"๐ŸŒ ComfyUI ์ ‘์† URL:")
220
+ print(f" Gradio: {gradio_url}")
221
+ if cloudflared_url:
222
+ print(f" Cloudflare: {cloudflared_url}")
223
+ print()
224
+ print("๐Ÿ’ก ํŒ:")
225
+ print(" โ€ข ์œ„ URL์„ ํด๋ฆญํ•˜์—ฌ ComfyUI์— ์ ‘์†ํ•˜์„ธ์š”")
226
+ print(" โ€ข ์ด ์…€์„ ์ค‘๋‹จ(โ– )ํ•˜๋ฉด ComfyUI์™€ ํ„ฐ๋„์ด ๋ชจ๋‘ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค")
227
+ print(" โ€ข ์•„๋ž˜ ComfyUI ๋กœ๊ทธ์—์„œ ์ง„ํ–‰ ์ƒํ™ฉ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค\n")
228
+ print("=" * 60 + "\n")
229
+
230
+ # 3. ComfyUI ์‹คํ–‰ (ํ„ฐ๋„ ์Šค๋ ˆ๋“œ์— ์ž…๋ ฅ๋œ ์ธ์ž๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์‹คํ–‰)
231
+ # sys.argv[1:]๋ฅผ ํ†ตํ•ด tunnel.py ๋’ค์— ๋ถ™๋Š” ๋ชจ๋“  ์ธ์ž๋ฅผ main.py์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
232
+ comfyui_command = [
233
+ "python",
234
+ "/content/ComfyUI/main.py",
235
+ "--listen", "127.0.0.1",
236
+ "--port", "8188"
237
+ ] + sys.argv[1:]
238
+
239
+ comfyui_proc = subprocess.Popen(comfyui_command)
240
+
241
+ try:
242
+ comfyui_proc.wait()
243
+ except KeyboardInterrupt:
244
+ print("\n๐Ÿ›‘ ComfyUI์™€ ํ„ฐ๋„์„ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค...")
245
+
246
+ # Cloudflared ํ„ฐ๋„ ์ข…๋ฃŒ
247
+ if cloudflared_proc:
248
+ cloudflared_proc.terminate()
249
+ if cloudflared_url:
250
+ print(f"Killing cloudflare tunnel 127.0.0.1:8188 <> {cloudflared_url}")
251
+
252
+ # ComfyUI ์ข…๋ฃŒ
253
+ comfyui_proc.terminate()
newmain_gd.py ADDED
@@ -0,0 +1,253 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import atexit
2
+ import os
3
+ import platform
4
+ import re
5
+ import stat
6
+ import subprocess
7
+ import sys
8
+ import time
9
+ import threading
10
+ from pathlib import Path
11
+ from typing import List, Optional
12
+
13
+ import requests
14
+
15
+ VERSION = "0.2"
16
+ CURRENT_TUNNELS: List["Tunnel"] = []
17
+
18
+ machine = platform.machine()
19
+ if machine == "x86_64":
20
+ machine = "amd64"
21
+
22
+ BINARY_REMOTE_NAME = f"frpc_{platform.system().lower()}_{machine.lower()}"
23
+ EXTENSION = ".exe" if os.name == "nt" else ""
24
+ BINARY_URL = f"https://cdn-media.huggingface.co/frpc-gradio-{VERSION}/{BINARY_REMOTE_NAME}{EXTENSION}"
25
+
26
+ BINARY_FILENAME = f"{BINARY_REMOTE_NAME}_v{VERSION}"
27
+ BINARY_FOLDER = Path(__file__).parent.absolute()
28
+ BINARY_PATH = f"{BINARY_FOLDER / BINARY_FILENAME}"
29
+
30
+ TUNNEL_TIMEOUT_SECONDS = 30
31
+ TUNNEL_ERROR_MESSAGE = (
32
+ "Could not create share URL. "
33
+ "Please check the appended log from frpc for more information:"
34
+ )
35
+
36
+ GRADIO_API_SERVER = "https://api.gradio.app/v2/tunnel-request"
37
+ GRADIO_SHARE_SERVER_ADDRESS = None
38
+
39
+
40
+ class Tunnel:
41
+ def __init__(self, remote_host, remote_port, local_host, local_port, share_token):
42
+ self.proc = None
43
+ self.url = None
44
+ self.remote_host = remote_host
45
+ self.remote_port = remote_port
46
+ self.local_host = local_host
47
+ self.local_port = local_port
48
+ self.share_token = share_token
49
+
50
+ @staticmethod
51
+ def download_binary():
52
+ if not Path(BINARY_PATH).exists():
53
+ resp = requests.get(BINARY_URL)
54
+
55
+ if resp.status_code == 403:
56
+ raise OSError(
57
+ f"Cannot set up a share link as this platform is incompatible. Please "
58
+ f"create a GitHub issue with information about your platform: {platform.uname()}"
59
+ )
60
+
61
+ resp.raise_for_status()
62
+
63
+ # Save file data to local copy
64
+ with open(BINARY_PATH, "wb") as file:
65
+ file.write(resp.content)
66
+ st = os.stat(BINARY_PATH)
67
+ os.chmod(BINARY_PATH, st.st_mode | stat.S_IEXEC)
68
+
69
+ def start_tunnel(self) -> str:
70
+ self.download_binary()
71
+ self.url = self._start_tunnel(BINARY_PATH)
72
+ return self.url
73
+
74
+ def kill(self):
75
+ if self.proc is not None:
76
+ print(f"Killing tunnel {self.local_host}:{self.local_port} <> {self.url}")
77
+ self.proc.terminate()
78
+ self.proc = None
79
+
80
+ def _start_tunnel(self, binary: str) -> str:
81
+ CURRENT_TUNNELS.append(self)
82
+ command = [
83
+ binary,
84
+ "http",
85
+ "-n",
86
+ self.share_token,
87
+ "-l",
88
+ str(self.local_port),
89
+ "-i",
90
+ self.local_host,
91
+ "--uc",
92
+ "--sd",
93
+ "random",
94
+ "--ue",
95
+ "--server_addr",
96
+ f"{self.remote_host}:{self.remote_port}",
97
+ "--disable_log_color",
98
+ ]
99
+ self.proc = subprocess.Popen(
100
+ command, stdout=subprocess.PIPE, stderr=subprocess.PIPE
101
+ )
102
+ atexit.register(self.kill)
103
+ return self._read_url_from_tunnel_stream()
104
+
105
+ def _read_url_from_tunnel_stream(self) -> str:
106
+ start_timestamp = time.time()
107
+
108
+ log = []
109
+ url = ""
110
+
111
+ def _raise_tunnel_error():
112
+ log_text = "\n".join(log)
113
+ print(log_text, file=sys.stderr)
114
+ raise ValueError(f"{TUNNEL_ERROR_MESSAGE}\n{log_text}")
115
+
116
+ while url == "":
117
+ # check for timeout and log
118
+ if time.time() - start_timestamp >= TUNNEL_TIMEOUT_SECONDS:
119
+ _raise_tunnel_error()
120
+
121
+ assert self.proc is not None
122
+ if self.proc.stdout is None:
123
+ continue
124
+
125
+ line = self.proc.stdout.readline()
126
+ line = line.decode("utf-8")
127
+
128
+ if line == "":
129
+ continue
130
+
131
+ log.append(line.strip())
132
+
133
+ if "start proxy success" in line:
134
+ result = re.search("start proxy success: (.+)\n", line)
135
+ if result is None:
136
+ _raise_tunnel_error()
137
+ else:
138
+ url = result.group(1)
139
+ elif "login to server failed" in line:
140
+ _raise_tunnel_error()
141
+
142
+ return url
143
+
144
+
145
+ def setup_tunnel(
146
+ local_host: str,
147
+ local_port: int,
148
+ share_token: str,
149
+ share_server_address: Optional[str],
150
+ ) -> str:
151
+ share_server_address = (
152
+ GRADIO_SHARE_SERVER_ADDRESS
153
+ if share_server_address is None
154
+ else share_server_address
155
+ )
156
+ if share_server_address is None:
157
+ response = requests.get(GRADIO_API_SERVER)
158
+ if not (response and response.status_code == 200):
159
+ raise RuntimeError("Could not get share link from Gradio API Server.")
160
+ payload = response.json()[0]
161
+ remote_host, remote_port = payload["host"], int(payload["port"])
162
+ else:
163
+ remote_host, remote_port = share_server_address.split(":")
164
+ remote_port = int(remote_port)
165
+ try:
166
+ tunnel = Tunnel(remote_host, remote_port, local_host, local_port, share_token)
167
+ address = tunnel.start_tunnel()
168
+ return address
169
+ except Exception as e:
170
+ raise RuntimeError(str(e)) from e
171
+
172
+
173
+ # Cloudflared ํ„ฐ๋„ URL๊ณผ ํ”„๋กœ์„ธ์Šค๋ฅผ ์ €์žฅํ•  ์ „์—ญ ๋ณ€์ˆ˜
174
+ cloudflared_url = None
175
+ cloudflared_proc = None
176
+
177
+ def start_cloudflared_tunnel(port):
178
+ global cloudflared_url, cloudflared_proc
179
+ cloudflared_proc = subprocess.Popen(
180
+ ["cloudflared", "tunnel", "--url", f"http://127.0.0.1:{port}"],
181
+ stdout=subprocess.PIPE,
182
+ stderr=subprocess.PIPE
183
+ )
184
+ for line in cloudflared_proc.stderr:
185
+ l = line.decode()
186
+ if "trycloudflare.com " in l:
187
+ cloudflared_url = l[l.find("http"):].strip()
188
+ break
189
+
190
+
191
+ if __name__ == "__main__":
192
+ import secrets
193
+
194
+ print("๐Ÿš€ ComfyUI + ํ„ฐ๋„ ์‹œ์ž‘\n")
195
+
196
+ # 1. Gradio ํ„ฐ๋„ ์ƒ์„ฑ
197
+ gradio_url = setup_tunnel(
198
+ "127.0.0.1",
199
+ 8188,
200
+ secrets.token_urlsafe(32),
201
+ None,
202
+ )
203
+
204
+ # 2. Cloudflared ํ„ฐ๋„์„ ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์Šค๋ ˆ๋“œ๋กœ ์‹œ์ž‘
205
+ cloudflared_thread = threading.Thread(
206
+ target=start_cloudflared_tunnel,
207
+ args=(8188,),
208
+ daemon=True
209
+ )
210
+ cloudflared_thread.start()
211
+
212
+ # Cloudflared URL์ด ์ƒ์„ฑ๋  ๋•Œ๊นŒ์ง€ ๋Œ€๊ธฐ
213
+ for _ in range(20):
214
+ if cloudflared_url:
215
+ break
216
+ time.sleep(0.5)
217
+
218
+ # URL ์ถœ๋ ฅ
219
+ print(f"๐ŸŒ ComfyUI ์ ‘์† URL:")
220
+ print(f" Gradio: {gradio_url}")
221
+ if cloudflared_url:
222
+ print(f" Cloudflare: {cloudflared_url}")
223
+ print()
224
+ print("๐Ÿ’ก ํŒ:")
225
+ print(" โ€ข ์œ„ URL์„ ํด๋ฆญํ•˜์—ฌ ComfyUI์— ์ ‘์†ํ•˜์„ธ์š”")
226
+ print(" โ€ข ์ด ์…€์„ ์ค‘๋‹จ(โ– )ํ•˜๋ฉด ComfyUI์™€ ํ„ฐ๋„์ด ๋ชจ๋‘ ์ข…๋ฃŒ๋ฉ๋‹ˆ๋‹ค")
227
+ print(" โ€ข ์•„๋ž˜ ComfyUI ๋กœ๊ทธ์—์„œ ์ง„ํ–‰ ์ƒํ™ฉ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค\n")
228
+ print("=" * 60 + "\n")
229
+
230
+ # 3. ComfyUI ์‹คํ–‰ (ํ„ฐ๋„ ์Šค๋ ˆ๋“œ์— ์ž…๋ ฅ๋œ ์ธ์ž๋ฅผ ์ถ”๊ฐ€ํ•˜์—ฌ ์‹คํ–‰)
231
+ # sys.argv[1:]๋ฅผ ํ†ตํ•ด tunnel.py ๋’ค์— ๋ถ™๋Š” ๋ชจ๋“  ์ธ์ž๋ฅผ main.py์— ์ „๋‹ฌํ•ฉ๋‹ˆ๋‹ค.
232
+ comfyui_command = [
233
+ "python",
234
+ "/content/drive/MyDrive/ONECLICK/ComfyUI/main.py",
235
+ "--listen", "127.0.0.1",
236
+ "--port", "8188"
237
+ ] + sys.argv[1:]
238
+
239
+ comfyui_proc = subprocess.Popen(comfyui_command)
240
+
241
+ try:
242
+ comfyui_proc.wait()
243
+ except KeyboardInterrupt:
244
+ print("\n๐Ÿ›‘ ComfyUI์™€ ํ„ฐ๋„์„ ์ข…๋ฃŒํ•ฉ๋‹ˆ๋‹ค...")
245
+
246
+ # Cloudflared ํ„ฐ๋„ ์ข…๋ฃŒ
247
+ if cloudflared_proc:
248
+ cloudflared_proc.terminate()
249
+ if cloudflared_url:
250
+ print(f"Killing cloudflare tunnel 127.0.0.1:8188 <> {cloudflared_url}")
251
+
252
+ # ComfyUI ์ข…๋ฃŒ
253
+ comfyui_proc.terminate()