kerojohan commited on
Commit
6c4bb6f
·
1 Parent(s): aed2053

Add example thumbnails and version label to Space UI

Browse files
Files changed (1) hide show
  1. app.py +132 -22
app.py CHANGED
@@ -13,7 +13,8 @@ import yaml
13
  from bat_tracker.pipeline import run_pipeline
14
 
15
 
16
- APP_TITLE = "Bat Tracker"
 
17
  APP_DESCRIPTION = (
18
  "Sube un video IR monocromo para ejecutar el pipeline, revisar la region valida "
19
  "detectada y consultar `events.csv` en forma de tabla."
@@ -44,20 +45,69 @@ def _format_duration_hms(seconds: float) -> str:
44
 
45
 
46
  # Pesos según la ficha del bucket HF; duraciones comprobadas con ffprobe sobre la URL resolve.
47
- EXAMPLE_VIDEO_ROWS: list[tuple[str, str, str]] = [
48
- (
49
- EXAMPLE_VIDEO_RABELLA,
50
- "39,3 MB",
51
- _format_duration_hms(60.095667),
52
- ),
53
- (
54
- EXAMPLE_VIDEO_PROVAGRAN2,
55
- "862 MB",
56
- _format_duration_hms(600.0),
57
- ),
 
 
58
  ]
59
 
60
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
61
  def _prepare_config(config_file: str | None, work_dir: Path) -> Path:
62
  source_path = Path(config_file) if config_file else DEFAULT_CONFIG_PATH
63
  if not source_path.exists():
@@ -284,6 +334,60 @@ APP_CSS = """
284
  max-width: 220px;
285
  }
286
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
287
  .config-note,
288
  .config-note * {
289
  color: #4a4238 !important;
@@ -303,9 +407,9 @@ APP_CSS = """
303
  with gr.Blocks(title=APP_TITLE) as demo:
304
  with gr.Column(elem_classes=["app-shell"]):
305
  gr.HTML(
306
- """
307
  <section class="hero">
308
- <h1>Bat Tracker Space</h1>
309
  <p>
310
  Interfaz minima para ejecutar el tracker sobre un video, inspeccionar la
311
  region valida detectada y revisar los eventos agregados en forma de tabla.
@@ -382,17 +486,23 @@ with gr.Blocks(title=APP_TITLE) as demo:
382
  with gr.Column(elem_classes=["examples-footer"]):
383
  gr.Markdown(
384
  "### Ejemplos de vídeo\n"
385
- "Pulsa una fila de la tabla para cargar ese vídeo en **Video de entrada** (arriba). "
386
  "**Peso** y **duración** corresponden al archivo original en el bucket. "
387
  "El segundo ejemplo es muy grande y puede tardar en descargarse."
388
  )
389
- gr.Examples(
390
- examples=[list(row) for row in EXAMPLE_VIDEO_ROWS],
391
- inputs=[video_input, example_file_size, example_duration],
392
- label="Vídeos de ejemplo",
393
- cache_examples=False,
394
- examples_per_page=6,
395
- )
 
 
 
 
 
 
396
 
397
  run_button.click(
398
  fn=process_video,
 
13
  from bat_tracker.pipeline import run_pipeline
14
 
15
 
16
+ APP_VERSION = "v1.1.4"
17
+ APP_TITLE = f"Bat Tracker {APP_VERSION}"
18
  APP_DESCRIPTION = (
19
  "Sube un video IR monocromo para ejecutar el pipeline, revisar la region valida "
20
  "detectada y consultar `events.csv` en forma de tabla."
 
45
 
46
 
47
  # Pesos según la ficha del bucket HF; duraciones comprobadas con ffprobe sobre la URL resolve.
48
+ EXAMPLE_VIDEOS = [
49
+ {
50
+ "name": "Rabella",
51
+ "url": EXAMPLE_VIDEO_RABELLA,
52
+ "size": "39,3 MB",
53
+ "duration": _format_duration_hms(60.095667),
54
+ },
55
+ {
56
+ "name": "Provagran2",
57
+ "url": EXAMPLE_VIDEO_PROVAGRAN2,
58
+ "size": "862 MB",
59
+ "duration": _format_duration_hms(600.0),
60
+ },
61
  ]
62
 
63
 
64
+ def _build_examples_table_html() -> str:
65
+ rows: list[str] = []
66
+ for idx, example in enumerate(EXAMPLE_VIDEOS, start=1):
67
+ rows.append(
68
+ f"""
69
+ <tr>
70
+ <td>{idx}</td>
71
+ <td>
72
+ <div class="example-thumb-wrap">
73
+ <video class="example-thumb" src="{example["url"]}" preload="metadata" muted playsinline></video>
74
+ </div>
75
+ </td>
76
+ <td>{example["name"]}</td>
77
+ <td>{example["size"]}</td>
78
+ <td>{example["duration"]}</td>
79
+ </tr>
80
+ """
81
+ )
82
+ return (
83
+ """
84
+ <div class="examples-table-shell">
85
+ <table class="examples-table">
86
+ <thead>
87
+ <tr>
88
+ <th>#</th>
89
+ <th>Miniatura</th>
90
+ <th>Vídeo</th>
91
+ <th>Peso</th>
92
+ <th>Duración</th>
93
+ </tr>
94
+ </thead>
95
+ <tbody>
96
+ """
97
+ + "".join(rows)
98
+ + """
99
+ </tbody>
100
+ </table>
101
+ </div>
102
+ """
103
+ )
104
+
105
+
106
+ def load_example(example_idx: int) -> tuple[str, str, str]:
107
+ example = EXAMPLE_VIDEOS[example_idx]
108
+ return example["url"], example["size"], example["duration"]
109
+
110
+
111
  def _prepare_config(config_file: str | None, work_dir: Path) -> Path:
112
  source_path = Path(config_file) if config_file else DEFAULT_CONFIG_PATH
113
  if not source_path.exists():
 
334
  max-width: 220px;
335
  }
336
 
337
+ .examples-table-shell {
338
+ overflow-x: auto;
339
+ border: 1px solid #d7d0c3;
340
+ border-radius: 12px;
341
+ background: #fffdf8;
342
+ margin: 10px 0 14px;
343
+ }
344
+
345
+ .examples-table {
346
+ width: 100%;
347
+ border-collapse: collapse;
348
+ font-size: 0.95rem;
349
+ color: #2a231c;
350
+ }
351
+
352
+ .examples-table th,
353
+ .examples-table td {
354
+ text-align: left;
355
+ padding: 10px 12px;
356
+ border-bottom: 1px solid #e2d8c9;
357
+ vertical-align: middle;
358
+ }
359
+
360
+ .examples-table th {
361
+ background: #ebe3d4;
362
+ color: #3d352b;
363
+ font-weight: 700;
364
+ }
365
+
366
+ .examples-table tr:last-child td {
367
+ border-bottom: none;
368
+ }
369
+
370
+ .example-thumb-wrap {
371
+ width: 112px;
372
+ height: 64px;
373
+ overflow: hidden;
374
+ border-radius: 10px;
375
+ background: #1b1510;
376
+ border: 1px solid #c5bcab;
377
+ }
378
+
379
+ .example-thumb {
380
+ width: 100%;
381
+ height: 100%;
382
+ object-fit: cover;
383
+ display: block;
384
+ background: #1b1510;
385
+ }
386
+
387
+ .example-buttons {
388
+ gap: 10px;
389
+ }
390
+
391
  .config-note,
392
  .config-note * {
393
  color: #4a4238 !important;
 
407
  with gr.Blocks(title=APP_TITLE) as demo:
408
  with gr.Column(elem_classes=["app-shell"]):
409
  gr.HTML(
410
+ f"""
411
  <section class="hero">
412
+ <h1>Bat Tracker Space {APP_VERSION}</h1>
413
  <p>
414
  Interfaz minima para ejecutar el tracker sobre un video, inspeccionar la
415
  region valida detectada y revisar los eventos agregados en forma de tabla.
 
486
  with gr.Column(elem_classes=["examples-footer"]):
487
  gr.Markdown(
488
  "### Ejemplos de vídeo\n"
489
+ "Consulta la tabla con miniaturas y usa un botón para cargar ese vídeo en **Video de entrada**. "
490
  "**Peso** y **duración** corresponden al archivo original en el bucket. "
491
  "El segundo ejemplo es muy grande y puede tardar en descargarse."
492
  )
493
+ gr.HTML(_build_examples_table_html())
494
+ with gr.Row(elem_classes=["example-buttons"]):
495
+ example_rabella_button = gr.Button("Cargar Rabella")
496
+ example_provagran2_button = gr.Button("Cargar Provagran2")
497
+
498
+ example_rabella_button.click(
499
+ fn=lambda: load_example(0),
500
+ outputs=[video_input, example_file_size, example_duration],
501
+ )
502
+ example_provagran2_button.click(
503
+ fn=lambda: load_example(1),
504
+ outputs=[video_input, example_file_size, example_duration],
505
+ )
506
 
507
  run_button.click(
508
  fn=process_video,