unnastyle commited on
Commit
c9b2086
ยท
verified ยท
1 Parent(s): b668284

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +99 -100
app.py CHANGED
@@ -1,10 +1,8 @@
1
- # app.py
2
-
3
  import gradio as gr
4
  from bs4 import BeautifulSoup
5
  import re
6
  import logging
7
- import requests # ์ถ”๊ฐ€์ฝ”๋“œ์—์„œ ์‚ฌ์šฉ
8
 
9
  # ๋””๋ฒ„๊น… ๋กœ๊น… ์„ค์ • (์ „์ฒด ํ†ตํ•ฉ์„ ์œ„ํ•ด ํฌ๋งท ํฌํ•จ)
10
  logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s")
@@ -207,26 +205,25 @@ def remove_timeline(script_text, lecture_number):
207
  stripped_line = line.strip()
208
  if stripped_line == "":
209
  continue
210
- # ๋ฒˆํ˜ธ๋งŒ ์žˆ๋Š” ์ค„ ์ œ๊ฑฐ
211
  if re.match(r'^\d+$', stripped_line):
212
  continue
213
- # ํƒ€์ž„๋ผ์ธ ํ˜•์‹ ์ œ๊ฑฐ (์˜ˆ: 00:00:00.000 --> 00:00:02.000)
214
  if re.match(r'^\d{1,2}:\d{2}(?::\d{2}(?:\.\d{3})?)?\s*-->\s*\d{1,2}:\d{2}(?::\d{2}(?:\.\d{3})?)?$', stripped_line):
215
  continue
216
  valid_lines.append(stripped_line)
217
  cleaned_text = "".join(valid_lines)
218
- # ๋งˆ์นจํ‘œ(.) ๋‹ค์Œ์— ์—ฌ๋ฐฑ์ด ์—†์œผ๋ฉด ์—ฌ๋ฐฑ ์ถ”๊ฐ€
219
  cleaned_text = re.sub(r'\.(\S)', r'. \1', cleaned_text)
220
- # ๊ธ€ ๊ฐ€์žฅ ์•ž์— ์žˆ๋Š” "WEBVTT" ์ œ๊ฑฐ
221
  cleaned_text = re.sub(r'^WEBVTT\s*', '', cleaned_text)
222
  return cleaned_text
223
 
 
 
 
224
  # ์ƒˆ๋กœ์šด ์ „์ฒด ์ฒ˜๋ฆฌ ํ•จ์ˆ˜: ๊ฐ•์˜ URL -> ์Šคํฌ๋ฆฝํŠธ URL ์ƒ์„ฑ -> ์Šคํฌ๋ฆฝํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ -> ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ
225
  def process_full(lecture_url):
226
  """
227
  ์ž…๋ ฅ๋œ ๊ฐ•์˜ URL๋กœ๋ถ€ํ„ฐ ์Šคํฌ๋ฆฝํŠธ URL์„ ์ƒ์„ฑํ•˜๊ณ ,
228
  ํ•ด๋‹น ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๊ฐ€์ ธ์˜จ ํ›„ ํƒ€์ž„๋ผ์ธ์„ ์ œ๊ฑฐํ•œ ์ตœ์ข… ๊ฐ•์˜ ๋‚ด์šฉ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜.
229
- ์ค‘๊ฐ„ ๋‹จ๊ณ„๋Š” ์ถœ๋ ฅํ•˜์ง€ ์•Š๊ณ  ์ตœ์ข… ๊ฒฐ๊ณผ๋งŒ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
230
  """
231
  script_url = create_script_url(lecture_url)
232
  if not script_url:
@@ -236,59 +233,39 @@ def process_full(lecture_url):
236
  if "์˜ค๋ฅ˜ ๋ฐœ์ƒ" in script_text:
237
  return script_text
238
 
239
- cleaned = remove_timeline(script_text, 1) # lecture_number๋Š” ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ 1 ์‚ฌ์šฉ
240
  return cleaned
241
 
 
242
  with gr.Blocks() as additional_demo:
243
- # ๋ชจ๋“ˆ2 ์ƒ๋‹จ ์•ˆ๋‚ด ๋ฌธ๊ตฌ
244
- gr.Markdown("โ€ป ์•„๋ž˜ ์ˆœ์„œ๋Œ€๋กœ ๊ฐ ๋‹จ๊ณ„๋ณ„ ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ์ง„ํ–‰ํ•˜์„ธ์š”.")
245
  with gr.Row():
246
  url1 = gr.Textbox(label="๊ฐ•์˜1 URL", elem_id="url1")
247
  url2 = gr.Textbox(label="๊ฐ•์˜2 URL", elem_id="url2")
248
  url3 = gr.Textbox(label="๊ฐ•์˜3 URL", elem_id="url3")
249
  with gr.Row():
250
- gen_url_btn1 = gr.Button("์Šคํฌ๋ฆฝํŠธ URL ๋งŒ๋“ค๊ธฐ", elem_id="gen_url_btn1")
251
- gen_url_btn2 = gr.Button("์Šคํฌ๋ฆฝํŠธ URL ๋งŒ๋“ค๊ธฐ", elem_id="gen_url_btn2")
252
- gen_url_btn3 = gr.Button("์Šคํฌ๋ฆฝํŠธ URL ๋งŒ๋“ค๊ธฐ", elem_id="gen_url_btn3")
253
- with gr.Row():
254
- script_url1 = gr.Textbox(label="๊ฐ•์˜1 ์Šคํฌ๋ฆฝํŠธ URL", interactive=False, elem_id="script_url1")
255
- script_url2 = gr.Textbox(label="๊ฐ•์˜2 ์Šคํฌ๋ฆฝํŠธ URL", interactive=False, elem_id="script_url2")
256
- script_url3 = gr.Textbox(label="๊ฐ•์˜3 ์Šคํฌ๋ฆฝํŠธ URL", interactive=False, elem_id="script_url3")
257
- with gr.Row():
258
- fetch_btn1 = gr.Button("์Šคํฌ๋ฆฝํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ", elem_id="fetch_btn1")
259
- fetch_btn2 = gr.Button("์Šคํฌ๋ฆฝํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ", elem_id="fetch_btn2")
260
- fetch_btn3 = gr.Button("์Šคํฌ๋ฆฝํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ", elem_id="fetch_btn3")
261
  with gr.Row():
262
- script1 = gr.Textbox(label="๊ฐ•์˜1 ์Šคํฌ๋ฆฝํŠธ", lines=10, elem_id="script1")
263
- script2 = gr.Textbox(label="๊ฐ•์˜2 ์Šคํฌ๋ฆฝํŠธ", lines=10, elem_id="script2")
264
- script3 = gr.Textbox(label="๊ฐ•์˜3 ์Šคํฌ๋ฆฝํŠธ", lines=10, elem_id="script3")
265
  with gr.Row():
266
- remove_btn1 = gr.Button("ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ", elem_id="remove_btn1")
267
- remove_btn2 = gr.Button("ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ", elem_id="remove_btn2")
268
- remove_btn3 = gr.Button("ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ", elem_id="remove_btn3")
269
  with gr.Row():
270
- cleaned1 = gr.Textbox(label="๊ฐ•์˜1 ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ", lines=10, interactive=False, elem_id="cleaned1")
271
- cleaned2 = gr.Textbox(label="๊ฐ•์˜2 ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ", lines=10, interactive=False, elem_id="cleaned2")
272
- cleaned3 = gr.Textbox(label="๊ฐ•์˜3 ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ", lines=10, interactive=False, elem_id="cleaned3")
273
- with gr.Row():
274
- copy_btn1 = gr.Button("๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌ", elem_id="copy_btn1")
275
- copy_btn2 = gr.Button("๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌ", elem_id="copy_btn2")
276
- copy_btn3 = gr.Button("๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌ", elem_id="copy_btn3")
277
- with gr.Row():
278
- copy_result1 = gr.Textbox(label="๊ฐ•์˜ ๋ณต์‚ฌ ๊ฒฐ๊ณผ", interactive=False, elem_id="copy_result1")
279
- copy_result2 = gr.Textbox(label="๊ฐ•์˜ ๋ณต์‚ฌ ๊ฒฐ๊ณผ", interactive=False, elem_id="copy_result2")
280
- copy_result3 = gr.Textbox(label="๊ฐ•์˜ ๋ณต์‚ฌ ๊ฒฐ๊ณผ", interactive=False, elem_id="copy_result3")
281
-
282
- gen_url_btn1.click(fn=lambda url: create_script_url(url), inputs=url1, outputs=script_url1)
283
- gen_url_btn2.click(fn=lambda url: create_script_url(url), inputs=url2, outputs=script_url2)
284
- gen_url_btn3.click(fn=lambda url: create_script_url(url), inputs=url3, outputs=script_url3)
285
- fetch_btn1.click(fn=lambda url: fetch_script(url), inputs=script_url1, outputs=script1)
286
- fetch_btn2.click(fn=lambda url: fetch_script(url), inputs=script_url2, outputs=script2)
287
- fetch_btn3.click(fn=lambda url: fetch_script(url), inputs=script_url3, outputs=script3)
288
- remove_btn1.click(fn=lambda script: remove_timeline(script, 1), inputs=script1, outputs=cleaned1)
289
- remove_btn2.click(fn=lambda script: remove_timeline(script, 2), inputs=script2, outputs=cleaned2)
290
- remove_btn3.click(fn=lambda script: remove_timeline(script, 3), inputs=script3, outputs=cleaned3)
291
-
292
  custom_script = """
293
  <script>
294
  function setupCopy(copyBtnId, textBoxId, resultBoxId) {
@@ -319,9 +296,9 @@ with gr.Blocks() as additional_demo:
319
  });
320
  }
321
  document.addEventListener("DOMContentLoaded", function(){
322
- setupCopy("copy_btn1", "cleaned1", "copy_result1");
323
- setupCopy("copy_btn2", "cleaned2", "copy_result2");
324
- setupCopy("copy_btn3", "cleaned3", "copy_result3");
325
  });
326
  </script>
327
  """
@@ -329,14 +306,6 @@ with gr.Blocks() as additional_demo:
329
  gr.Markdown("๋””๋ฒ„๊น… ๋ชจ๋“œ ํ™œ์„ฑํ™”๋จ: ๋กœ๊ทธ๊ฐ€ ์ฝ˜์†”์— ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.")
330
  # ---------- [๋ชจ๋“ˆ2: ์ถ”๊ฐ€์ฝ”๋“œ] ๋ ----------
331
 
332
- # ์ƒˆ๋กœ์šด ์ „์ฒด ์ฒ˜๋ฆฌ ์ธํ„ฐํŽ˜์ด์Šค: ๊ฐ•์˜ URL -> ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ ๊ฒฐ๊ณผ๋งŒ ๋ฐ˜ํ™˜
333
- full_interface = gr.Interface(
334
- fn=process_full,
335
- inputs=gr.Textbox(label="๊ฐ•์˜ URL", placeholder="๊ฐ•์˜ URL์„ ์ž…๋ ฅํ•˜์„ธ์š”..."),
336
- outputs=gr.Textbox(label="ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ ๊ฒฐ๊ณผ", lines=10),
337
- description="๊ฐ•์˜ URL์„ ์ž…๋ ฅํ•˜๋ฉด ์Šคํฌ๋ฆฝํŠธ URL ์ƒ์„ฑ, ์Šคํฌ๋ฆฝํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ, ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ๊นŒ์ง€ ํ•œ ๋ฒˆ์— ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค."
338
- )
339
-
340
  # ---------- ํ†ตํ•ฉ Gradio ์•ฑ ๊ตฌ์„ฑ (ํ•œ ํŽ˜์ด์ง€์— ๋ชจ๋‘ ํ‘œ์‹œ) ----------
341
  with gr.Blocks() as app:
342
  gr.Markdown("# ์บ๋กค๋ผ์ธ๋Œ€ํ•™ ๊ฐ•์˜ ์ถ”์ถœ๊ธฐ")
@@ -347,56 +316,86 @@ with gr.Blocks() as app:
347
  <strong>์‚ฌ์šฉ๋ฐฉ๋ฒ•</strong>
348
  <ol>
349
  <li>์ถ”์ถœ์„ ์›ํ•˜๋Š” ๊ฐ•์˜ ํŽ˜์ด์ง€์—์„œ "Ctrl + U"๋ฅผ ๋ˆ„๋ฅด๊ณ  "ํŽ˜์ด์ง€ ์†Œ์Šค ๋ณด๊ธฐ" ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
350
- ๋˜๋Š” ํ•ด๋‹นํŽ˜์ด์ง€์—์„œ ๋งˆ์šฐ์Šค ์šฐํด๋ฆญ ํ›„ "ํŽ˜์ด์ง€ ์†Œ์Šค ๋ณด๊ธฐ" ํด๋ฆญ (์—ฃ์ง€์˜ ๊ฒฝ์šฐ "ํŽ˜์ด์ง€ ์›๋ณธ ๋ณด๊ธฐ")</li>
351
- <li>"ํŽ˜์ด์ง€ ์†Œ์Šค ๋ณด๊ธฐ" ํŽ˜์ด์ง€์—์„œ ์ „์ฒด ๋ณต์‚ฌ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค. "Ctrl+A" ๋‹ค์Œ "Ctrl + C"</li>
352
- <li>"์ „์ฒด ํŽ˜์ด์ง€ HTML ์ž…๋ ฅ"์ฐฝ์— ๋ณต์‚ฌํ•œ ๋‚ด์šฉ์„ ๋ถ™ํ˜€๋„ฃ๊ธฐ ํ•ฉ๋‹ˆ๋‹ค. "Ctrl + V"</li>
353
  <li>"Submit" ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ๋™์˜์ƒ ๊ฐ•์˜ ๋ชฉ๋ก๏ฟฝ๏ฟฝ๏ฟฝ ๋‚˜์˜ต๋‹ˆ๋‹ค.</li>
354
- <li>๋‚ด์šฉ ์ถ”์ถœ์„ ์›ํ•˜๋Š” ๊ฐ•์˜ URL์„ ๋ณต์‚ฌํ•ด์„œ ์•„๋ž˜ "๊ฐ•์˜ URL" ์ฐฝ์— ๋ถ™ํ˜€๋„ฃ๊ธฐ ํ•ฉ๋‹ˆ๋‹ค.</li>
355
- <li>์ˆœ์„œ๋Œ€๋กœ ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ํ•ด๋‹น ์˜์ƒ์˜ ๊ฐ•์˜ ๋‚ด์šฉ์„ ์ถ”์ถœ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.</li>
356
- <li>๊ฐ๊ฐ ์ถ”์ถœ๋œ ๊ฐ•์˜ ๋‚ด์šฉ์„ "ChatGPT"์— ์ „์ฒด ๋ถ™ํ˜€๋„ฃ๊ณ  ๊ฐ•์˜ ์š”์•ฝ์„ ์ง€์‹œํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.</li>
357
  </ol>
358
  </div>
359
  """
360
  )
361
  iface.render()
362
- # Module1์˜ Submit ๋ฒ„ํŠผ ํด๋ฆญ ์‹œ Module2 ๋‚ด์šฉ ์ง€์šฐ๊ธฐ ์œ„ํ•œ JavaScript
363
- gr.HTML(
364
- """
365
- <script>
366
- function clearModule2Fields() {
367
- var ids = ["url1", "url2", "url3", "script_url1", "script_url2", "script_url3", "script1", "script2", "script3", "cleaned1", "cleaned2", "cleaned3", "copy_result1", "copy_result2", "copy_result3"];
368
- ids.forEach(function(id) {
369
- var elem = document.getElementById(id);
370
- if (elem) {
371
- var textarea = elem.querySelector("textarea");
372
- if (textarea) {
373
- textarea.value = "";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
374
  } else {
375
- elem.value = "";
 
 
 
 
376
  }
377
  }
378
- });
379
- }
380
- document.addEventListener("DOMContentLoaded", function(){
381
- var buttons = document.getElementsByTagName("button");
382
- for (var i = 0; i < buttons.length; i++) {
383
- if (buttons[i].textContent.trim() === "Submit") {
384
- buttons[i].addEventListener("click", function(){
385
- clearModule2Fields();
386
- });
387
- }
388
  }
389
  });
390
- </script>
391
- """
392
- )
393
- gr.Markdown("---")
394
- gr.Markdown("๋™์˜์ƒ ๊ฐ•์˜ ๋ชฉ๋ก์—์„œ ํ•„์š”ํ•œ ๊ฐ•์˜์˜ URL์„ ๋ณต์‚ฌํ•ด์„œ ๋„ฃ์–ด์ฃผ์„ธ์š”")
395
- additional_demo.render()
396
- gr.Markdown("---")
397
- gr.Markdown("### ์ „์ฒด ์ฒ˜๋ฆฌ (๊ฐ•์˜ URL -> ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ)")
398
- full_interface.render()
399
-
400
  if __name__ == "__main__":
401
  logging.debug("ํ†ตํ•ฉ Gradio ์•ฑ ์‹คํ–‰ ์ค‘")
402
  app.launch(debug=True)
 
 
 
1
  import gradio as gr
2
  from bs4 import BeautifulSoup
3
  import re
4
  import logging
5
+ import requests
6
 
7
  # ๋””๋ฒ„๊น… ๋กœ๊น… ์„ค์ • (์ „์ฒด ํ†ตํ•ฉ์„ ์œ„ํ•ด ํฌ๋งท ํฌํ•จ)
8
  logging.basicConfig(level=logging.DEBUG, format="%(asctime)s - %(levelname)s - %(message)s")
 
205
  stripped_line = line.strip()
206
  if stripped_line == "":
207
  continue
 
208
  if re.match(r'^\d+$', stripped_line):
209
  continue
 
210
  if re.match(r'^\d{1,2}:\d{2}(?::\d{2}(?:\.\d{3})?)?\s*-->\s*\d{1,2}:\d{2}(?::\d{2}(?:\.\d{3})?)?$', stripped_line):
211
  continue
212
  valid_lines.append(stripped_line)
213
  cleaned_text = "".join(valid_lines)
 
214
  cleaned_text = re.sub(r'\.(\S)', r'. \1', cleaned_text)
 
215
  cleaned_text = re.sub(r'^WEBVTT\s*', '', cleaned_text)
216
  return cleaned_text
217
 
218
+ # ๊ธฐ์กด์˜ "์Šคํฌ๋ฆฝํŠธ URL ๋งŒ๋“ค๊ธฐ", "์Šคํฌ๋ฆฝํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ", "ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ" ๊ด€๋ จ ์ปดํฌ๋„ŒํŠธ๋Š” ์ œ๊ฑฐํ•˜๊ณ ,
219
+ # ์•„๋ž˜ [๋ชจ๋“ˆ2 ๊ตฌ์กฐ]์— ๋งž๊ฒŒ ์ƒˆ๋กญ๊ฒŒ ๊ตฌ์„ฑํ•ฉ๋‹ˆ๋‹ค.
220
+
221
  # ์ƒˆ๋กœ์šด ์ „์ฒด ์ฒ˜๋ฆฌ ํ•จ์ˆ˜: ๊ฐ•์˜ URL -> ์Šคํฌ๋ฆฝํŠธ URL ์ƒ์„ฑ -> ์Šคํฌ๋ฆฝํŠธ ๊ฐ€์ ธ์˜ค๊ธฐ -> ํƒ€์ž„๋ผ์ธ ์ œ๊ฑฐ
222
  def process_full(lecture_url):
223
  """
224
  ์ž…๋ ฅ๋œ ๊ฐ•์˜ URL๋กœ๋ถ€ํ„ฐ ์Šคํฌ๋ฆฝํŠธ URL์„ ์ƒ์„ฑํ•˜๊ณ ,
225
  ํ•ด๋‹น ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๊ฐ€์ ธ์˜จ ํ›„ ํƒ€์ž„๋ผ์ธ์„ ์ œ๊ฑฐํ•œ ์ตœ์ข… ๊ฐ•์˜ ๋‚ด์šฉ์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ํ•จ์ˆ˜.
226
+ (์ค‘๊ฐ„ ๋‹จ๊ณ„๋Š” ์ถœ๋ ฅํ•˜์ง€ ์•Š๊ณ  ์ตœ์ข… ๊ฒฐ๊ณผ๋งŒ ๋ฐ˜ํ™˜)
227
  """
228
  script_url = create_script_url(lecture_url)
229
  if not script_url:
 
233
  if "์˜ค๋ฅ˜ ๋ฐœ์ƒ" in script_text:
234
  return script_text
235
 
236
+ cleaned = remove_timeline(script_text, 1)
237
  return cleaned
238
 
239
+ # [๋ชจ๋“ˆ2 ๊ตฌ์กฐ]
240
  with gr.Blocks() as additional_demo:
241
+ # ์•ˆ๋‚ด ๋ฌธ๊ตฌ ์ˆ˜์ •
242
+ gr.Markdown("โ€ป '๊ฐ•์˜ ๋‚ด์šฉ ๊ฐ€์ ธ์˜ค๊ธฐ' ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ํ•ด๋‹น ์˜์ƒ์˜ ๊ฐ•์˜ ๋‚ด์šฉ์„ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.")
243
  with gr.Row():
244
  url1 = gr.Textbox(label="๊ฐ•์˜1 URL", elem_id="url1")
245
  url2 = gr.Textbox(label="๊ฐ•์˜2 URL", elem_id="url2")
246
  url3 = gr.Textbox(label="๊ฐ•์˜3 URL", elem_id="url3")
247
  with gr.Row():
248
+ get_btn1 = gr.Button("๊ฐ•์˜ ๋‚ด์šฉ ๊ฐ€์ ธ์˜ค๊ธฐ", elem_id="get_btn1")
249
+ get_btn2 = gr.Button("๊ฐ•์˜ ๋‚ด์šฉ ๊ฐ€์ ธ์˜ค๊ธฐ", elem_id="get_btn2")
250
+ get_btn3 = gr.Button("๊ฐ•์˜ ๋‚ด์šฉ ๊ฐ€์ ธ์˜ค๊ธฐ", elem_id="get_btn3")
 
 
 
 
 
 
 
 
251
  with gr.Row():
252
+ lecture_content1 = gr.Textbox(label="๊ฐ•์˜ ๋‚ด์šฉ", lines=10, elem_id="lecture_content1")
253
+ lecture_content2 = gr.Textbox(label="๊ฐ•์˜ ๋‚ด์šฉ", lines=10, elem_id="lecture_content2")
254
+ lecture_content3 = gr.Textbox(label="๊ฐ•์˜ ๋‚ด์šฉ", lines=10, elem_id="lecture_content3")
255
  with gr.Row():
256
+ copy_btn1 = gr.Button("๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌํ•˜๊ธฐ", elem_id="copy_btn1")
257
+ copy_btn2 = gr.Button("๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌํ•˜๊ธฐ", elem_id="copy_btn2")
258
+ copy_btn3 = gr.Button("๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌํ•˜๊ธฐ", elem_id="copy_btn3")
259
  with gr.Row():
260
+ copy_result1 = gr.Textbox(label="๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌํ•˜๊ธฐ ๊ฒฐ๊ณผ", interactive=False, elem_id="copy_result1")
261
+ copy_result2 = gr.Textbox(label="๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌํ•˜๊ธฐ ๊ฒฐ๊ณผ", interactive=False, elem_id="copy_result2")
262
+ copy_result3 = gr.Textbox(label="๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌํ•˜๊ธฐ ๊ฒฐ๊ณผ", interactive=False, elem_id="copy_result3")
263
+
264
+ get_btn1.click(fn=lambda url: process_full(url), inputs=url1, outputs=lecture_content1)
265
+ get_btn2.click(fn=lambda url: process_full(url), inputs=url2, outputs=lecture_content2)
266
+ get_btn3.click(fn=lambda url: process_full(url), inputs=url3, outputs=lecture_content3)
267
+
268
+ # ๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌ ๊ธฐ๋Šฅ์€ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ JavaScript๋กœ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  custom_script = """
270
  <script>
271
  function setupCopy(copyBtnId, textBoxId, resultBoxId) {
 
296
  });
297
  }
298
  document.addEventListener("DOMContentLoaded", function(){
299
+ setupCopy("copy_btn1", "lecture_content1", "copy_result1");
300
+ setupCopy("copy_btn2", "lecture_content2", "copy_result2");
301
+ setupCopy("copy_btn3", "lecture_content3", "copy_result3");
302
  });
303
  </script>
304
  """
 
306
  gr.Markdown("๋””๋ฒ„๊น… ๋ชจ๋“œ ํ™œ์„ฑํ™”๋จ: ๋กœ๊ทธ๊ฐ€ ์ฝ˜์†”์— ์ถœ๋ ฅ๋ฉ๋‹ˆ๋‹ค.")
307
  # ---------- [๋ชจ๋“ˆ2: ์ถ”๊ฐ€์ฝ”๋“œ] ๋ ----------
308
 
 
 
 
 
 
 
 
 
309
  # ---------- ํ†ตํ•ฉ Gradio ์•ฑ ๊ตฌ์„ฑ (ํ•œ ํŽ˜์ด์ง€์— ๋ชจ๋‘ ํ‘œ์‹œ) ----------
310
  with gr.Blocks() as app:
311
  gr.Markdown("# ์บ๋กค๋ผ์ธ๋Œ€ํ•™ ๊ฐ•์˜ ์ถ”์ถœ๊ธฐ")
 
316
  <strong>์‚ฌ์šฉ๋ฐฉ๋ฒ•</strong>
317
  <ol>
318
  <li>์ถ”์ถœ์„ ์›ํ•˜๋Š” ๊ฐ•์˜ ํŽ˜์ด์ง€์—์„œ "Ctrl + U"๋ฅผ ๋ˆ„๋ฅด๊ณ  "ํŽ˜์ด์ง€ ์†Œ์Šค ๋ณด๊ธฐ" ํŽ˜์ด์ง€๋กœ ์ด๋™ํ•ฉ๋‹ˆ๋‹ค.
319
+ ๋˜๋Š” ํ•ด๋‹น ํŽ˜์ด์ง€์—์„œ ๋งˆ์šฐ์Šค ์šฐํด๋ฆญ ํ›„ "ํŽ˜์ด์ง€ ์†Œ์Šค ๋ณด๊ธฐ" ํด๋ฆญ (์—ฃ์ง€์˜ ๊ฒฝ์šฐ "ํŽ˜์ด์ง€ ์›๋ณธ ๋ณด๊ธฐ")</li>
320
+ <li>"ํŽ˜์ด์ง€ ์†Œ์Šค ๋ณด๊ธฐ" ํŽ˜์ด์ง€์—์„œ ์ „์ฒด ๋ณต์‚ฌ๋ฅผ ํ•ฉ๋‹ˆ๋‹ค. ("Ctrl+A" ํ›„ "Ctrl+C")</li>
321
+ <li>"์ „์ฒด ํŽ˜์ด์ง€ HTML ์ž…๋ ฅ"์ฐฝ์— ๋ณต์‚ฌํ•œ ๋‚ด์šฉ์„ ๋ถ™์—ฌ๋„ฃ๊ธฐ ํ•ฉ๋‹ˆ๋‹ค. ("Ctrl+V")</li>
322
  <li>"Submit" ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ๋™์˜์ƒ ๊ฐ•์˜ ๋ชฉ๋ก๏ฟฝ๏ฟฝ๏ฟฝ ๋‚˜์˜ต๋‹ˆ๋‹ค.</li>
323
+ <li>๋‚ด์šฉ ์ถ”์ถœ์„ ์›ํ•˜๋Š” ๊ฐ•์˜ URL์„ ๋ณต์‚ฌํ•ด์„œ ์•„๋ž˜ "๊ฐ•์˜ URL" ์ฐฝ์— ๋ถ™์—ฌ๋„ฃ๊ธฐ ํ•ฉ๋‹ˆ๋‹ค.</li>
324
+ <li>"๊ฐ•์˜๋‚ด์šฉ ๊ฐ€์ ธ์˜ค๊ธฐ" ๋ฒ„ํŠผ์„ ํด๋ฆญํ•˜๋ฉด ํ•ด๋‹น ์˜์ƒ์˜ ๊ฐ•์˜ ๋‚ด์šฉ์„ ์ถ”์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.</li>
325
+ <li>๊ฐ๊ฐ ์ถ”์ถœ๋œ ๊ฐ•์˜ ๋‚ด์šฉ์„ "ChatGPT"์— ๋ถ™์—ฌ๋„ฃ๊ณ  ๊ฐ•์˜ ์š”์•ฝ์„ ์š”์ฒญํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.</li>
326
  </ol>
327
  </div>
328
  """
329
  )
330
  iface.render()
331
+ gr.Markdown("---")
332
+ gr.Markdown("๋™์˜์ƒ ๊ฐ•์˜ ๋ชฉ๋ก์—์„œ ํ•„์š”ํ•œ ๊ฐ•์˜์˜ URL์„ ๋ณต์‚ฌํ•ด์„œ ๋„ฃ์–ด์ฃผ์„ธ์š”")
333
+ additional_demo.render()
334
+
335
+ # ---------- [๋ชจ๋“ˆ3: ๊ฐ•์˜๋‚ด์šฉ ํ•ฉ์น˜๊ธฐ ์ถ”๊ฐ€์ฝ”๋“œ] ์‹œ์ž‘ ----------
336
+ gr.Markdown("## ๊ฐ•์˜๋‚ด์šฉ ํ•ฉ์น˜๊ธฐ")
337
+ with gr.Row():
338
+ merge_btn = gr.Button("๊ฐ•์˜๋‚ด์šฉ ํ•ฉ์น˜๊ธฐ", elem_id="merge_btn")
339
+ merged_content = gr.Textbox(label="์ „์ฒด ๊ฐ•์˜ ๋‚ด์šฉ", lines=10, elem_id="merged_content")
340
+ with gr.Row():
341
+ merge_copy_btn = gr.Button("์ „์ฒด ๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌํ•˜๊ธฐ", elem_id="merge_copy_btn")
342
+ merge_copy_result = gr.Textbox(label="์ „์ฒด ๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌ ๊ฒฐ๊ณผ", interactive=False, elem_id="merge_copy_result")
343
+
344
+ def merge_contents(l1, l2, l3):
345
+ merged = ""
346
+ if l1.strip():
347
+ merged += "[๊ฐ•์˜1]\n" + l1.strip()
348
+ if l2.strip():
349
+ if merged:
350
+ merged += "\n\n"
351
+ merged += "[๊ฐ•์˜2]\n" + l2.strip()
352
+ if l3.strip():
353
+ if merged:
354
+ merged += "\n\n"
355
+ merged += "[๊ฐ•์˜3]\n" + l3.strip()
356
+ return merged
357
+
358
+ merge_btn.click(fn=merge_contents, inputs=[lecture_content1, lecture_content2, lecture_content3], outputs=merged_content)
359
+
360
+ # ์ „์ฒด ๊ฐ•์˜ ๋‚ด์šฉ ๋ณต์‚ฌ ๊ธฐ๋Šฅ์„ ์œ„ํ•œ ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ JavaScript ์ถ”๊ฐ€
361
+ merge_copy_script = """
362
+ <script>
363
+ function setupMergeCopy(copyBtnId, textBoxId, resultBoxId) {
364
+ const copyBtn = document.getElementById(copyBtnId);
365
+ if (!copyBtn) {
366
+ console.error("๋ฒ„ํŠผ " + copyBtnId + "๋ฅผ ์ฐพ์„ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
367
+ return;
368
+ }
369
+ copyBtn.addEventListener("click", function(){
370
+ const textBoxElem = document.getElementById(textBoxId);
371
+ const resultBoxElem = document.getElementById(resultBoxId);
372
+ if(textBoxElem && resultBoxElem) {
373
+ const textarea = textBoxElem.querySelector("textarea");
374
+ const resultTextarea = resultBoxElem.querySelector("textarea");
375
+ if(textarea && resultTextarea) {
376
+ var text = textarea.value;
377
+ if(text.trim() === ""){
378
+ resultTextarea.value = "๋ณต์‚ฌํ•  ๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค.";
379
  } else {
380
+ navigator.clipboard.writeText(text).then(function(){
381
+ resultTextarea.value = "๋ณต์‚ฌ์™„๋ฃŒ";
382
+ }, function(err){
383
+ resultTextarea.value = "๋ณต์‚ฌ ์‹คํŒจ";
384
+ });
385
  }
386
  }
 
 
 
 
 
 
 
 
 
 
387
  }
388
  });
389
+ }
390
+ document.addEventListener("DOMContentLoaded", function(){
391
+ setupMergeCopy("merge_copy_btn", "merged_content", "merge_copy_result");
392
+ });
393
+ </script>
394
+ """
395
+ gr.HTML(merge_copy_script)
396
+ # ---------- [๋ชจ๋“ˆ3: ๊ฐ•์˜๋‚ด์šฉ ํ•ฉ์น˜๊ธฐ ์ถ”๊ฐ€์ฝ”๋“œ] ๋ ----------
397
+
398
+ # ---------- ํ†ตํ•ฉ Gradio ์•ฑ ๊ตฌ์„ฑ ๋ ----------
399
  if __name__ == "__main__":
400
  logging.debug("ํ†ตํ•ฉ Gradio ์•ฑ ์‹คํ–‰ ์ค‘")
401
  app.launch(debug=True)