Youngsun Lim commited on
Commit
2f084b5
ยท
1 Parent(s): b7847f2

dataset update

Browse files
Files changed (1) hide show
  1. app.py +66 -242
app.py CHANGED
@@ -3,92 +3,6 @@ from datetime import datetime
3
  import gradio as gr
4
  from huggingface_hub import HfApi, hf_hub_download
5
 
6
-
7
- import hashlib, subprocess, tempfile, pathlib, urllib.parse
8
-
9
- # โ–ถ ๋™์˜์ƒ์ด ์žˆ๋Š” ํ—ˆ๋ธŒ ๋ฐ์ดํ„ฐ์…‹(repo id)
10
- VIDEO_DATASET_REPO = os.getenv("VIDEO_DATASET_REPO", "SGTLIM/ucf101_eval_unified")
11
-
12
- # โ–ถ ์บ์‹œ ํด๋” (์ถฉ๋ถ„ํ•œ ๊ณต๊ฐ„ ๊ฒฝ๋กœ ๊ถŒ์žฅ)
13
- LOCAL_CACHE_DIR = "/tmp/hf_video_cache"
14
- MUTED_CACHE_DIR = "/tmp/hf_video_cache_muted"
15
-
16
- pathlib.Path(LOCAL_CACHE_DIR).mkdir(parents=True, exist_ok=True)
17
- pathlib.Path(MUTED_CACHE_DIR).mkdir(parents=True, exist_ok=True)
18
-
19
- def _sha1_8(s: str) -> str:
20
- return hashlib.sha1(s.encode("utf-8")).hexdigest()[:8]
21
-
22
- def _download_local(v: dict) -> str:
23
- """
24
- v: {"url": ".../resolve/main/<id>.mp4", "id": "<id>.mp4", ...}
25
- - id๊ฐ€ ์žˆ์œผ๋ฉด VIDEO_DATASET_REPO์—์„œ hf_hub_download ์‚ฌ์šฉ
26
- - (๋น„์ƒ) id๊ฐ€ ์—†์œผ๋ฉด url์—์„œ repo/id๋ฅผ ํŒŒ์‹ฑํ•ด์„œ ์‚ฌ์šฉ ์‹œ๋„
27
- """
28
- vid = v.get("id")
29
- if vid:
30
- return hf_hub_download(
31
- repo_id=VIDEO_DATASET_REPO,
32
- filename=vid,
33
- repo_type="dataset",
34
- token=HF_TOKEN,
35
- local_dir=LOCAL_CACHE_DIR,
36
- local_dir_use_symlinks=False,
37
- )
38
- # fallback: url ํŒŒ์‹ฑ (datasets/{owner/repo}/resolve/main/{path})
39
- u = v.get("url", "")
40
- try:
41
- parts = urllib.parse.urlparse(u).path.strip("/").split("/")
42
- i = parts.index("datasets")
43
- repo_id = "/".join(parts[i+1:i+3]) # owner/repo
44
- file_path = "/".join(parts[i+5:]) # after resolve/main/
45
- return hf_hub_download(
46
- repo_id=repo_id, filename=file_path, repo_type="dataset",
47
- token=HF_TOKEN, local_dir=LOCAL_CACHE_DIR, local_dir_use_symlinks=False
48
- )
49
- except Exception:
50
- # ๋งˆ์ง€๋ง‰ ํด๋ฐฑ: ๊ทธ๋ƒฅ ์›๊ฒฉ URL ๊ทธ๋Œ€๋กœ(์†Œ๋ฆฌ ๋‚  ์ˆ˜ ์žˆ์Œ)
51
- return u
52
-
53
- def _ensure_muted(local_or_url: str, key_hint: str) -> str:
54
- """
55
- local_or_url์ด ๋กœ์ปฌ ํŒŒ์ผ์ด๋ฉด ๊ทธ๊ฑธ ๊ธฐ๋ฐ˜์œผ๋กœ ๋ฌด์Œ mp4 ์ƒ์„ฑ.
56
- -c:v copy -an โ†’ ์‹คํŒจ ์‹œ ์žฌ์ธ์ฝ”๋”ฉ์œผ๋กœ ํด๋ฐฑ.
57
- ์ด๋ฏธ ๋งŒ๋“ค์–ด์ง„ ์บ์‹œ๊ฐ€ ์žˆ์œผ๋ฉด ์žฌ์‚ฌ์šฉ.
58
- """
59
- # ์›๊ฒฉ์ด๋ฉด ๊ทธ๋Œ€๋กœ(๊ฐ€๋Šฅํ•˜๋ฉด _download_local๋กœ ๋กœ์ปฌ์„ ๋„˜๊ธฐ์„ธ์š”)
60
- if not os.path.isfile(local_or_url):
61
- return local_or_url
62
-
63
- h8 = _sha1_8(key_hint + "|" + os.path.abspath(local_or_url))
64
- out = os.path.join(MUTED_CACHE_DIR, f"muted_{h8}.mp4")
65
- if os.path.exists(out):
66
- return out
67
-
68
- # 1์ฐจ: ์ŠคํŠธ๋ฆผ ๋ณต์‚ฌ๋กœ ์˜ค๋””์˜ค๋งŒ ์ œ๊ฑฐ(๋น ๋ฅด๊ณ  ์†์ƒ ์—†์Œ)
69
- cmd = ["ffmpeg","-y","-i",local_or_url,"-c:v","copy","-an",out]
70
- try:
71
- subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
72
- return out
73
- except subprocess.CalledProcessError:
74
- pass
75
-
76
- # 2์ฐจ: ์žฌ์ธ์ฝ”๋”ฉ ํด๋ฐฑ (ํ™•์‹คํžˆ ๋ฌด์Œ)
77
- cmd = [
78
- "ffmpeg","-y","-i",local_or_url,
79
- "-vf","format=yuv420p","-movflags","+faststart",
80
- "-c:v","libx264","-crf","18","-preset","veryfast",
81
- "-an", out
82
- ]
83
- subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
84
- return out
85
-
86
- def _video_src_muted(v: dict) -> str:
87
- """ํ‰๊ฐ€ ํ™”๋ฉด์— ๋„ฃ์„ 'ํ™•์‹คํ•œ ๋ฌด์Œ' ์†Œ์Šค ๊ฒฝ๋กœ ๋ฐ˜ํ™˜"""
88
- local = _download_local(v)
89
- return _ensure_muted(local, v.get("id") or v.get("url",""))
90
-
91
-
92
  # -------------------- Config --------------------
93
  REPO_ID = os.getenv("RESULTS_REPO", "sgtlim/videoeval_results") # ์—…๋กœ๋“œํ•œ ๋ฆฌํฌ์™€ ์ผ์น˜
94
  HF_TOKEN = os.getenv("HF_TOKEN")
@@ -207,7 +121,7 @@ def push(participant_id, video_id, score, notes=""):
207
  token=HF_TOKEN,
208
  commit_message="append"
209
  )
210
- return gr.update(visible=True, value=f"โœ… Saved successfully.")
211
  except Exception as e:
212
  return gr.update(
213
  visible=True,
@@ -341,15 +255,7 @@ for cls, files in EXAMPLES.items():
341
  EX_CACHE[cls] = {"real": None, "bad": None}
342
  for kind, fname in files.items():
343
  try:
344
- # EX_CACHE[cls][kind] = hf_hub_download(
345
- # repo_id=REPO_ID,
346
- # filename=fname,
347
- # repo_type="dataset",
348
- # token=HF_TOKEN,
349
- # local_dir="/tmp",
350
- # local_dir_use_symlinks=False,
351
- # )
352
- p = hf_hub_download(
353
  repo_id=REPO_ID,
354
  filename=fname,
355
  repo_type="dataset",
@@ -357,101 +263,11 @@ for cls, files in EXAMPLES.items():
357
  local_dir="/tmp",
358
  local_dir_use_symlinks=False,
359
  )
360
- # โฌ‡๏ธ ๋ฐ›์€ ํŒŒ์ผ์„ ํ™•์‹คํ•œ ๋ฌด์Œ์œผ๋กœ ๋ณ€ํ™˜/์บ์‹œ
361
- EX_CACHE[cls][kind] = _ensure_muted(p, f"example::{cls}::{kind}")
362
  except Exception as e:
363
  print(f"[WARN] example missing: {cls} {kind} -> {fname}: {e}")
364
 
365
- # GLOBAL_CSS = """
366
- # /* ===== ๊ณตํ†ต ๋ณ€์ˆ˜ ํˆฌ๋ช…ํ™” (v3/v4 ๋‘˜๋‹ค) ===== */
367
- # :root, .gradio-container {
368
- # --body-background-fill: transparent !important;
369
- # --background-fill-primary: transparent !important;
370
- # --background-fill-secondary: transparent !important;
371
- # --block-background-fill: transparent !important;
372
- # --block-border-color: transparent !important;
373
- # --panel-background-fill: transparent !important;
374
- # --panel-border-color: transparent !important;
375
- # --section-header-background-fill: transparent !important;
376
- # --shadow-drop: 0 0 0 rgba(0,0,0,0) !important;
377
- # --shadow-spread: 0 0 0 rgba(0,0,0,0) !important;
378
- # }
379
-
380
- # /* ===== v4(Tailwind ๊ธฐ๋ฐ˜)์—์„œ ์ž์ฃผ ์“ฐ์ด๋Š” ๋ฐฐ๊ฒฝ/ํ…Œ๋‘๋ฆฌ/๊ทธ๋ฆผ์ž ์ œ๊ฑฐ ===== */
381
- # .gradio-container .bg-white,
382
- # .gradio-container .bg-gray-50,
383
- # .gradio-container .bg-gray-100,
384
- # .gradio-container .bg-slate-50,
385
- # .gradio-container .bg-neutral-50,
386
- # .gradio-container .bg-secondary,
387
- # .gradio-container .border,
388
- # .gradio-container .shadow,
389
- # .gradio-container .shadow-sm,
390
- # .gradio-container .shadow-md,
391
- # .gradio-container .ring-1,
392
- # .gradio-container .ring,
393
- # .gradio-container .gr-card,
394
- # .gradio-container .prose > *:where(hr) {
395
- # background: transparent !important;
396
- # box-shadow: none !important;
397
- # border-color: transparent !important;
398
- # }
399
-
400
- # /* ===== v3 ์ปดํฌ๋„ŒํŠธ ๊ณ„์—ด ===== */
401
- # .gradio-container .gr-panel,
402
- # .gradio-container .gr-group,
403
- # .gradio-container .gr-box,
404
- # .gradio-container .gr-row,
405
- # .gradio-container .gr-column,
406
- # .gradio-container .gr-accordion,
407
- # .gradio-container .gr-block,
408
- # .gradio-container .gr-form,
409
- # .gradio-container .gr-tabs,
410
- # .gradio-container .gr-tabitem,
411
- # .gradio-container .gr-section-header {
412
- # background: transparent !important;
413
- # box-shadow: none !important;
414
- # border: none !important;
415
- # }
416
-
417
- # /* ๊ตฌ๋ถ„์„ /ํ—ค๋” ๋ฐ” ์ œ๊ฑฐ */
418
- # .gradio-container hr,
419
- # .gradio-container .gr-divider,
420
- # .gradio-container .gr-accordion .label {
421
- # background: transparent !important;
422
- # border: none !important;
423
- # box-shadow: none !important;
424
- # }
425
-
426
- # /* ๋ฐ”๊นฅ์ชฝ ํŽ˜์ด์ง€ ๋ฐฐ๊ฒฝ๋„ ๊ฐ•์ œ๋กœ ํˆฌ๋ช…/ํฐ์ƒ‰์œผ๋กœ */
427
- # html, body, .gradio-container { background: transparent !important; }
428
-
429
- # /* ๊ธฐ์กด CSS ์•„๋ž˜์— ์ถ”๊ฐ€ */
430
- # #eval [class*="bg-"],
431
- # #eval [class*="border"],
432
- # #eval [class*="shadow"],
433
- # #eval .gr-panel, #eval .gr-group, #eval .gr-box, #eval .gr-row, #eval .gr-column,
434
- # #eval .gr-block, #eval .gr-form, #eval .gr-section-header, #eval .gr-accordion {
435
- # background: transparent !important;
436
- # border-color: transparent !important;
437
- # box-shadow: none !important;
438
- # }
439
- # #eval .gr-form, #eval .gr-panel { background: transparent !important; box-shadow:none !important; border:none !important; }
440
-
441
- # """
442
-
443
  GLOBAL_CSS = """
444
- /* ===== ์Šคํฌ๋กค ๊ฐ•์ œ ํ—ˆ์šฉ ===== */
445
- html, body, #root, .gradio-container {
446
- height: auto !important;
447
- min-height: 100% !important;
448
- overflow: auto !important;
449
- }
450
- .gradio-container *[class*="overflow-hidden"] {
451
- overflow: visible !important;
452
- }
453
-
454
- /* ===== ๋ฐฐ๊ฒฝ/ํ…Œ๋‘๋ฆฌ ์ œ๊ฑฐ(๊ธฐ์กด ๋‚ด์šฉ) ===== */
455
  :root, .gradio-container {
456
  --body-background-fill: transparent !important;
457
  --background-fill-primary: transparent !important;
@@ -465,6 +281,7 @@ html, body, #root, .gradio-container {
465
  --shadow-spread: 0 0 0 rgba(0,0,0,0) !important;
466
  }
467
 
 
468
  .gradio-container .bg-white,
469
  .gradio-container .bg-gray-50,
470
  .gradio-container .bg-gray-100,
@@ -484,6 +301,7 @@ html, body, #root, .gradio-container {
484
  border-color: transparent !important;
485
  }
486
 
 
487
  .gradio-container .gr-panel,
488
  .gradio-container .gr-group,
489
  .gradio-container .gr-box,
@@ -500,6 +318,7 @@ html, body, #root, .gradio-container {
500
  border: none !important;
501
  }
502
 
 
503
  .gradio-container hr,
504
  .gradio-container .gr-divider,
505
  .gradio-container .gr-accordion .label {
@@ -508,6 +327,10 @@ html, body, #root, .gradio-container {
508
  box-shadow: none !important;
509
  }
510
 
 
 
 
 
511
  #eval [class*="bg-"],
512
  #eval [class*="border"],
513
  #eval [class*="shadow"],
@@ -518,68 +341,70 @@ html, body, #root, .gradio-container {
518
  box-shadow: none !important;
519
  }
520
  #eval .gr-form, #eval .gr-panel { background: transparent !important; box-shadow:none !important; border:none !important; }
521
- .gradio-container .h-screen,
522
- .gradio-container .min-h-screen { height: auto !important; min-height: auto !important; }
523
- .gradio-container .overflow-hidden { overflow: visible !important; }
524
- html, body { position: static !important; }
525
- """
526
 
 
527
 
528
  # -------------------- UI --------------------
529
- with gr.Blocks(css=GLOBAL_CSS) as demo:
 
530
  gr.HTML("""
531
  <script>
532
  (function(){
533
- function allowScroll(){
534
- // ์ตœ์ƒ์œ„๋“ค ๊ฐ•์ œ ์˜ค๋ฒ„๋ผ์ด๋“œ
535
- [document.documentElement, document.body].forEach(el=>{
536
- if (!el) return;
537
- el.style.overflow = 'auto';
538
- el.style.height = 'auto';
539
- el.style.minHeight = '100%';
540
- el.style.position = 'static';
541
- });
542
- const root = document.getElementById('root') || document.querySelector('#root,.gradio-container');
543
- if (root){
544
- root.style.overflow = 'auto';
545
- root.style.height = 'auto';
546
- root.style.minHeight = '100%';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
547
  }
548
- // ๊ณ ์ • ๋ ˆ์ด์•„์›ƒ/์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ์ฐจ๋‹จ ํด๋ž˜์Šค ๋ฌด๋ ฅํ™”
549
- document.querySelectorAll('.overflow-hidden, .h-screen, .min-h-screen')
550
- .forEach(el=>{
551
- el.classList.remove('overflow-hidden','h-screen','min-h-screen');
552
- el.style.overflow = 'auto';
553
- if (getComputedStyle(el).height === '100vh') el.style.height = 'auto';
554
- if (getComputedStyle(el).minHeight === '100vh') el.style.minHeight = 'auto';
555
- });
556
- }
557
-
558
- const apply = () => requestAnimationFrame(allowScroll);
559
-
560
- // ์ดˆ๊ธฐ 1ํšŒ
561
- apply();
562
-
563
- // ๋ ˆ์ด์•„์›ƒ/ํด๋ž˜์Šค๊ฐ€ ๋ฐ”๋€” ๋•Œ๋งˆ๋‹ค ์žฌ์ ์šฉ
564
- const mo = new MutationObserver(apply);
565
- mo.observe(document.documentElement, {
566
- subtree: true,
567
- childList: true,
568
- attributes: true,
569
- attributeFilter: ['class','style']
570
- });
571
-
572
- // ๊ฐ€๋” ๋†“์น˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์œ„ํ•ด ์ฃผ๊ธฐ์  ๋ฐฑ์—… ์ ์šฉ
573
- const interval = setInterval(apply, 1500);
574
-
575
- // ํŽ˜์ด์ง€ ์ด๋ฒคํŠธ์—๋„ ํ›…
576
- window.addEventListener('load', apply, { once:false });
577
- document.addEventListener('visibilitychange', apply);
578
- window.addEventListener('resize', apply);
579
  })();
580
  </script>
581
  """)
582
- # Blocks ์•ˆ, ์–ด๋””์„œ๋“  ํ•œ ๋ฒˆ๋งŒ ์ถ”๊ฐ€(๊ถŒ์žฅ ์œ„์น˜: Blocks ์‹œ์ž‘ ์งํ›„)
583
 
584
  order_state = gr.State(value=[]) # v4์—์„œ๋Š” value= ๊ถŒ์žฅ
585
  ptr_state = gr.State(value=0)
@@ -796,7 +621,7 @@ with gr.Blocks(css=GLOBAL_CSS) as demo:
796
  _progress_html(TOTAL_PER_PARTICIPANT, TOTAL_PER_PARTICIPANT),
797
  5.0, # score ๋ฆฌ์…‹
798
  ptr,
799
- cur_video_id
800
  )
801
 
802
  # ๋‹ค์Œ ์˜์ƒ ๋กœ๋“œ
@@ -804,8 +629,7 @@ with gr.Blocks(css=GLOBAL_CSS) as demo:
804
  v = V[next_idx]
805
  return (
806
  status_msg,
807
- # v["url"],
808
- _video_src_muted(v),
809
  _extract_action(v),
810
  new_done,
811
  _progress_html(new_done, TOTAL_PER_PARTICIPANT),
 
3
  import gradio as gr
4
  from huggingface_hub import HfApi, hf_hub_download
5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  # -------------------- Config --------------------
7
  REPO_ID = os.getenv("RESULTS_REPO", "sgtlim/videoeval_results") # ์—…๋กœ๋“œํ•œ ๋ฆฌํฌ์™€ ์ผ์น˜
8
  HF_TOKEN = os.getenv("HF_TOKEN")
 
121
  token=HF_TOKEN,
122
  commit_message="append"
123
  )
124
+ return gr.update(visible=True, value=f"โœ… Saved for {video_id}.")
125
  except Exception as e:
126
  return gr.update(
127
  visible=True,
 
255
  EX_CACHE[cls] = {"real": None, "bad": None}
256
  for kind, fname in files.items():
257
  try:
258
+ EX_CACHE[cls][kind] = hf_hub_download(
 
 
 
 
 
 
 
 
259
  repo_id=REPO_ID,
260
  filename=fname,
261
  repo_type="dataset",
 
263
  local_dir="/tmp",
264
  local_dir_use_symlinks=False,
265
  )
 
 
266
  except Exception as e:
267
  print(f"[WARN] example missing: {cls} {kind} -> {fname}: {e}")
268
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
269
  GLOBAL_CSS = """
270
+ /* ===== ๊ณตํ†ต ๋ณ€์ˆ˜ ํˆฌ๋ช…ํ™” (v3/v4 ๋‘˜๋‹ค) ===== */
 
 
 
 
 
 
 
 
 
 
271
  :root, .gradio-container {
272
  --body-background-fill: transparent !important;
273
  --background-fill-primary: transparent !important;
 
281
  --shadow-spread: 0 0 0 rgba(0,0,0,0) !important;
282
  }
283
 
284
+ /* ===== v4(Tailwind ๊ธฐ๋ฐ˜)์—์„œ ์ž์ฃผ ์“ฐ์ด๋Š” ๋ฐฐ๊ฒฝ/ํ…Œ๋‘๋ฆฌ/๊ทธ๋ฆผ์ž ์ œ๊ฑฐ ===== */
285
  .gradio-container .bg-white,
286
  .gradio-container .bg-gray-50,
287
  .gradio-container .bg-gray-100,
 
301
  border-color: transparent !important;
302
  }
303
 
304
+ /* ===== v3 ์ปดํฌ๋„ŒํŠธ ๊ณ„์—ด ===== */
305
  .gradio-container .gr-panel,
306
  .gradio-container .gr-group,
307
  .gradio-container .gr-box,
 
318
  border: none !important;
319
  }
320
 
321
+ /* ๊ตฌ๋ถ„์„ /ํ—ค๋” ๋ฐ” ์ œ๊ฑฐ */
322
  .gradio-container hr,
323
  .gradio-container .gr-divider,
324
  .gradio-container .gr-accordion .label {
 
327
  box-shadow: none !important;
328
  }
329
 
330
+ /* ๋ฐ”๊นฅ์ชฝ ํŽ˜์ด์ง€ ๋ฐฐ๊ฒฝ๋„ ๊ฐ•์ œ๋กœ ํˆฌ๋ช…/ํฐ์ƒ‰์œผ๋กœ */
331
+ html, body, .gradio-container { background: transparent !important; }
332
+
333
+ /* ๊ธฐ์กด CSS ์•„๋ž˜์— ์ถ”๊ฐ€ */
334
  #eval [class*="bg-"],
335
  #eval [class*="border"],
336
  #eval [class*="shadow"],
 
341
  box-shadow: none !important;
342
  }
343
  #eval .gr-form, #eval .gr-panel { background: transparent !important; box-shadow:none !important; border:none !important; }
 
 
 
 
 
344
 
345
+ """
346
 
347
  # -------------------- UI --------------------
348
+ with gr.Blocks(fill_height=True, css=GLOBAL_CSS) as demo:
349
+ # Blocks ์•ˆ, ์–ด๋””์„œ๋“  ํ•œ ๋ฒˆ๋งŒ ์ถ”๊ฐ€(๊ถŒ์žฅ ์œ„์น˜: Blocks ์‹œ์ž‘ ์งํ›„)
350
  gr.HTML("""
351
  <script>
352
  (function(){
353
+ // ๋ชจ๋“  ์ผ๋ฐ˜ DOM + Shadow DOM ์•ˆ์˜ <video>๊นŒ์ง€ ์ฐพ์•„ ์Œ์†Œ๊ฑฐ
354
+ function eachNodeWithShadow(root, fn){
355
+ const walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT);
356
+ fn(root);
357
+ while (walker.nextNode()){
358
+ const el = walker.currentNode;
359
+ fn(el);
360
+ if (el.shadowRoot){
361
+ eachNodeWithShadow(el.shadowRoot, fn);
362
+ }
363
+ }
364
+ }
365
+
366
+ function muteVideoEl(v){
367
+ try{
368
+ // ์žฌ์ƒ ์ „์— ๋ฐ˜๋“œ์‹œ muted ์†์„ฑ์ด ์žˆ์–ด์•ผ ๋ธŒ๋ผ์šฐ์ €๊ฐ€ ์†Œ๋ฆฌ ์ฐจ๋‹จ
369
+ v.muted = true;
370
+ v.volume = 0.0;
371
+ v.setAttribute('muted','');
372
+ v.setAttribute('playsinline','');
373
+ v.setAttribute('preload','metadata');
374
+
375
+ // ์‚ฌ์šฉ์ž๊ฐ€ ๋ณผ๋ฅจ/์Œ์†Œ๊ฑฐ๋ฅผ ๋ฐ”๊ฟ”๋„ ๋‹ค์‹œ 0์œผ๋กœ
376
+ if (!v._muteHooked){
377
+ v.addEventListener('volumechange', () => {
378
+ if (!v.muted || v.volume > 0) { v.muted = true; v.volume = 0.0; }
379
+ });
380
+ v.addEventListener('play', () => {
381
+ v.muted = true; v.volume = 0.0;
382
+ });
383
+ v._muteHooked = true;
384
  }
385
+ }catch(e){}
386
+ }
387
+
388
+ function muteAll(root){
389
+ eachNodeWithShadow(root || document, (el)=>{
390
+ if (el.tagName && el.tagName.toLowerCase() === 'video'){
391
+ muteVideoEl(el);
392
+ }else if (el.querySelectorAll){
393
+ el.querySelectorAll('video').forEach(muteVideoEl);
394
+ }
395
+ });
396
+ }
397
+
398
+ // ์ดˆ๊ธฐ ๋ Œ๋”์—์„œ
399
+ muteAll(document);
400
+
401
+ // ์ดํ›„ DOM ๋ณ€ํ™” ๊ฐ์‹œ(Shadow DOM ๋‚ด๋ถ€ ๋ณ€ํ™”๋„ ํฌ์ฐฉ)
402
+ const obs = new MutationObserver(() => muteAll(document));
403
+ obs.observe(document, {subtree:true, childList:true, attributes:false});
 
 
 
 
 
 
 
 
 
 
 
 
404
  })();
405
  </script>
406
  """)
407
+
408
 
409
  order_state = gr.State(value=[]) # v4์—์„œ๋Š” value= ๊ถŒ์žฅ
410
  ptr_state = gr.State(value=0)
 
621
  _progress_html(TOTAL_PER_PARTICIPANT, TOTAL_PER_PARTICIPANT),
622
  5.0, # score ๋ฆฌ์…‹
623
  ptr,
624
+ video_id
625
  )
626
 
627
  # ๋‹ค์Œ ์˜์ƒ ๋กœ๋“œ
 
629
  v = V[next_idx]
630
  return (
631
  status_msg,
632
+ v["url"],
 
633
  _extract_action(v),
634
  new_done,
635
  _progress_html(new_done, TOTAL_PER_PARTICIPANT),