NeuralFalcon commited on
Commit
3403d4c
·
verified ·
1 Parent(s): 7771b1b

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +291 -429
index.html CHANGED
@@ -1,435 +1,297 @@
1
  <!DOCTYPE html>
2
- <html>
3
  <head>
4
- <meta charset="utf-8">
5
- <meta name="description"
6
- content="Deformable Neural Radiance Fields creates free-viewpoint portraits (nerfies) from casually captured videos.">
7
- <meta name="keywords" content="Nerfies, D-NeRF, NeRF">
8
- <meta name="viewport" content="width=device-width, initial-scale=1">
9
- <title>Nerfies: Deformable Neural Radiance Fields</title>
10
-
11
- <link href="https://fonts.googleapis.com/css?family=Google+Sans|Noto+Sans|Castoro"
12
- rel="stylesheet">
13
-
14
- <link rel="stylesheet" href="./static/css/bulma.min.css">
15
- <link rel="stylesheet" href="./static/css/bulma-carousel.min.css">
16
- <link rel="stylesheet" href="./static/css/bulma-slider.min.css">
17
- <link rel="stylesheet" href="./static/css/fontawesome.all.min.css">
18
- <link rel="stylesheet"
19
- href="https://cdn.jsdelivr.net/gh/jpswalsh/academicons@1/css/academicons.min.css">
20
- <link rel="stylesheet" href="./static/css/index.css">
21
- <link rel="icon" href="./static/images/favicon.svg">
22
-
23
- <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
24
- <script defer src="./static/js/fontawesome.all.min.js"></script>
25
- <script src="./static/js/bulma-carousel.min.js"></script>
26
- <script src="./static/js/bulma-slider.min.js"></script>
27
- <script src="./static/js/index.js"></script>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
28
  </head>
29
- <body>
30
-
31
- <section class="hero">
32
- <div class="hero-body">
33
- <div class="container is-max-desktop">
34
- <div class="columns is-centered">
35
- <div class="column has-text-centered">
36
- <h1 class="title is-1 publication-title">Nerfies: Deformable Neural Radiance Fields</h1>
37
- <div class="is-size-5 publication-authors">
38
- <span class="author-block">
39
- <a href="https://keunhong.com" target="_blank">Keunhong Park</a><sup>1</sup>,</span>
40
- <span class="author-block">
41
- <a href="https://utkarshsinha.com" target="_blank">Utkarsh Sinha</a><sup>2</sup>,</span>
42
- <span class="author-block">
43
- <a href="https://jonbarron.info" target="_blank">Jonathan T. Barron</a><sup>2</sup>,
44
- </span>
45
- <span class="author-block">
46
- <a href="http://sofienbouaziz.com" target="_blank">Sofien Bouaziz</a><sup>2</sup>,
47
- </span>
48
- <span class="author-block">
49
- <a href="https://www.danbgoldman.com" target="_blank">Dan B Goldman</a><sup>2</sup>,
50
- </span>
51
- <span class="author-block">
52
- <a href="https://homes.cs.washington.edu/~seitz/" target="_blank">Steven M. Seitz</a><sup>1,2</sup>,
53
- </span>
54
- <span class="author-block">
55
- <a href="http://www.ricardomartinbrualla.com" target="_blank">Ricardo Martin-Brualla</a><sup>2</sup>
56
- </span>
57
- </div>
58
-
59
- <div class="is-size-5 publication-authors">
60
- <span class="author-block"><sup>1</sup>University of Washington,</span>
61
- <span class="author-block"><sup>2</sup>Google Research</span>
62
- </div>
63
-
64
- <div class="column has-text-centered">
65
- <div class="publication-links">
66
- <!-- PDF Link. -->
67
- <span class="link-block">
68
- <a href="https://arxiv.org/pdf/2011.12948" target="_blank"
69
- class="external-link button is-normal is-rounded is-dark">
70
- <span class="icon">
71
- <i class="fas fa-file-pdf"></i>
72
- </span>
73
- <span>Paper</span>
74
- </a>
75
- </span>
76
- <span class="link-block">
77
- <a href="https://arxiv.org/abs/2011.12948" target="_blank"
78
- class="external-link button is-normal is-rounded is-dark">
79
- <span class="icon">
80
- <i class="ai ai-arxiv"></i>
81
- </span>
82
- <span>arXiv</span>
83
- </a>
84
- </span>
85
- <!-- Video Link. -->
86
- <span class="link-block">
87
- <a href="https://www.youtube.com/watch?v=MrKrnHhk8IA" target="_blank"
88
- class="external-link button is-normal is-rounded is-dark">
89
- <span class="icon">
90
- <i class="fab fa-youtube"></i>
91
- </span>
92
- <span>Video</span>
93
- </a>
94
- </span>
95
- <!-- Code Link. -->
96
- <span class="link-block">
97
- <a href="https://github.com/google/nerfies" target="_blank"
98
- class="external-link button is-normal is-rounded is-dark">
99
- <span class="icon">
100
- <i class="fab fa-github"></i>
101
- </span>
102
- <span>Code</span>
103
- </a>
104
- </span>
105
- <!-- Dataset Link. -->
106
- <span class="link-block">
107
- <a href="https://github.com/google/nerfies/releases/tag/0.1" target="_blank"
108
- class="external-link button is-normal is-rounded is-dark">
109
- <span class="icon">
110
- <i class="far fa-images"></i>
111
- </span>
112
- <span>Data</span>
113
- </a>
114
- </div>
115
-
116
- </div>
117
- </div>
118
- </div>
119
  </div>
120
- </div>
121
- </section>
122
-
123
- <section class="hero teaser">
124
- <div class="container is-max-desktop">
125
- <div class="hero-body">
126
- <video id="teaser" autoplay muted loop playsinline height="100%">
127
- <source src="./static/videos/teaser.mp4"
128
- type="video/mp4">
129
- </video>
130
- <h2 class="subtitle has-text-centered">
131
- <span class="dnerf">Nerfies</span> turns selfie videos from your phone into
132
- free-viewpoint
133
- portraits.
134
- </h2>
135
- </div>
136
- </div>
137
- </section>
138
-
139
-
140
- <section class="hero is-light is-small">
141
- <div class="hero-body">
142
- <div class="container">
143
- <div id="results-carousel" class="carousel results-carousel">
144
- <div class="item item-steve">
145
- <video poster="" id="steve" autoplay controls muted loop playsinline height="100%">
146
- <source src="./static/videos/steve.mp4"
147
- type="video/mp4">
148
- </video>
149
- </div>
150
- <div class="item item-chair-tp">
151
- <video poster="" id="chair-tp" autoplay controls muted loop playsinline height="100%">
152
- <source src="./static/videos/chair-tp.mp4"
153
- type="video/mp4">
154
- </video>
155
- </div>
156
- <div class="item item-shiba">
157
- <video poster="" id="shiba" autoplay controls muted loop playsinline height="100%">
158
- <source src="./static/videos/shiba.mp4"
159
- type="video/mp4">
160
- </video>
161
- </div>
162
- <div class="item item-fullbody">
163
- <video poster="" id="fullbody" autoplay controls muted loop playsinline height="100%">
164
- <source src="./static/videos/fullbody.mp4"
165
- type="video/mp4">
166
- </video>
167
- </div>
168
- <div class="item item-blueshirt">
169
- <video poster="" id="blueshirt" autoplay controls muted loop playsinline height="100%">
170
- <source src="./static/videos/blueshirt.mp4"
171
- type="video/mp4">
172
- </video>
173
- </div>
174
- <div class="item item-mask">
175
- <video poster="" id="mask" autoplay controls muted loop playsinline height="100%">
176
- <source src="./static/videos/mask.mp4"
177
- type="video/mp4">
178
- </video>
179
- </div>
180
- <div class="item item-coffee">
181
- <video poster="" id="coffee" autoplay controls muted loop playsinline height="100%">
182
- <source src="./static/videos/coffee.mp4"
183
- type="video/mp4">
184
- </video>
185
- </div>
186
- <div class="item item-toby">
187
- <video poster="" id="toby" autoplay controls muted loop playsinline height="100%">
188
- <source src="./static/videos/toby2.mp4"
189
- type="video/mp4">
190
- </video>
191
- </div>
192
- </div>
193
- </div>
194
- </div>
195
- </section>
196
-
197
-
198
- <section class="section">
199
- <div class="container is-max-desktop">
200
- <!-- Abstract. -->
201
- <div class="columns is-centered has-text-centered">
202
- <div class="column is-four-fifths">
203
- <h2 class="title is-3">Abstract</h2>
204
- <div class="content has-text-justified">
205
- <p>
206
- We present the first method capable of photorealistically reconstructing a non-rigidly
207
- deforming scene using photos/videos captured casually from mobile phones.
208
- </p>
209
- <p>
210
- Our approach augments neural radiance fields
211
- (NeRF) by optimizing an
212
- additional continuous volumetric deformation field that warps each observed point into a
213
- canonical 5D NeRF.
214
- We observe that these NeRF-like deformation fields are prone to local minima, and
215
- propose a coarse-to-fine optimization method for coordinate-based models that allows for
216
- more robust optimization.
217
- By adapting principles from geometry processing and physical simulation to NeRF-like
218
- models, we propose an elastic regularization of the deformation field that further
219
- improves robustness.
220
- </p>
221
- <p>
222
- We show that <span class="dnerf">Nerfies</span> can turn casually captured selfie
223
- photos/videos into deformable NeRF
224
- models that allow for photorealistic renderings of the subject from arbitrary
225
- viewpoints, which we dub <i>"nerfies"</i>. We evaluate our method by collecting data
226
- using a
227
- rig with two mobile phones that take time-synchronized photos, yielding train/validation
228
- images of the same pose at different viewpoints. We show that our method faithfully
229
- reconstructs non-rigidly deforming scenes and reproduces unseen views with high
230
- fidelity.
231
- </p>
232
- </div>
233
- </div>
234
- </div>
235
- <!--/ Abstract. -->
236
-
237
- <!-- Paper video. -->
238
- <div class="columns is-centered has-text-centered">
239
- <div class="column is-four-fifths">
240
- <h2 class="title is-3">Video</h2>
241
- <div class="publication-video">
242
- <iframe src="https://www.youtube.com/embed/MrKrnHhk8IA?rel=0&amp;showinfo=0"
243
- frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>
244
- </div>
245
- </div>
246
- </div>
247
- <!--/ Paper video. -->
248
- </div>
249
- </section>
250
-
251
-
252
- <section class="section">
253
- <div class="container is-max-desktop">
254
-
255
- <div class="columns is-centered">
256
-
257
- <!-- Visual Effects. -->
258
- <div class="column">
259
- <div class="content">
260
- <h2 class="title is-3">Visual Effects</h2>
261
- <p>
262
- Using <i>nerfies</i> you can create fun visual effects. This Dolly zoom effect
263
- would be impossible without nerfies since it would require going through a wall.
264
- </p>
265
- <video id="dollyzoom" autoplay controls muted loop playsinline height="100%">
266
- <source src="./static/videos/dollyzoom-stacked.mp4"
267
- type="video/mp4">
268
- </video>
269
- </div>
270
- </div>
271
- <!--/ Visual Effects. -->
272
-
273
- <!-- Matting. -->
274
- <div class="column">
275
- <h2 class="title is-3">Matting</h2>
276
- <div class="columns is-centered">
277
- <div class="column content">
278
- <p>
279
- As a byproduct of our method, we can also solve the matting problem by ignoring
280
- samples that fall outside of a bounding box during rendering.
281
- </p>
282
- <video id="matting-video" controls playsinline height="100%">
283
- <source src="./static/videos/matting.mp4"
284
- type="video/mp4">
285
- </video>
286
- </div>
287
-
288
- </div>
289
- </div>
290
- </div>
291
- <!--/ Matting. -->
292
-
293
- <!-- Animation. -->
294
- <div class="columns is-centered">
295
- <div class="column is-full-width">
296
- <h2 class="title is-3">Animation</h2>
297
-
298
- <!-- Interpolating. -->
299
- <h3 class="title is-4">Interpolating states</h3>
300
- <div class="content has-text-justified">
301
- <p>
302
- We can also animate the scene by interpolating the deformation latent codes of two input
303
- frames. Use the slider here to linearly interpolate between the left frame and the right
304
- frame.
305
- </p>
306
- </div>
307
- <div class="columns is-vcentered interpolation-panel">
308
- <div class="column is-3 has-text-centered">
309
- <img src="./static/images/interpolate_start.jpg"
310
- class="interpolation-image"
311
- alt="Interpolate start reference image."/>
312
- <p>Start Frame</p>
313
- </div>
314
- <div class="column interpolation-video-column">
315
- <div id="interpolation-image-wrapper">
316
- Loading...
317
- </div>
318
- <input class="slider is-fullwidth is-large is-info"
319
- id="interpolation-slider"
320
- step="1" min="0" max="100" value="0" type="range">
321
- </div>
322
- <div class="column is-3 has-text-centered">
323
- <img src="./static/images/interpolate_end.jpg"
324
- class="interpolation-image"
325
- alt="Interpolation end reference image."/>
326
- <p class="is-bold">End Frame</p>
327
- </div>
328
- </div>
329
- <br/>
330
- <!--/ Interpolating. -->
331
-
332
- <!-- Re-rendering. -->
333
- <h3 class="title is-4">Re-rendering the input video</h3>
334
- <div class="content has-text-justified">
335
- <p>
336
- Using <span class="dnerf">Nerfies</span>, you can re-render a video from a novel
337
- viewpoint such as a stabilized camera by playing back the training deformations.
338
- </p>
339
- </div>
340
- <div class="content has-text-centered">
341
- <video id="replay-video"
342
- controls
343
- muted
344
- preload
345
- playsinline
346
- width="75%">
347
- <source src="./static/videos/replay.mp4"
348
- type="video/mp4">
349
- </video>
350
- </div>
351
- <!--/ Re-rendering. -->
352
-
353
- </div>
354
- </div>
355
- <!--/ Animation. -->
356
-
357
-
358
- <!-- Concurrent Work. -->
359
- <div class="columns is-centered">
360
- <div class="column is-full-width">
361
- <h2 class="title is-3">Related Links</h2>
362
-
363
- <div class="content has-text-justified">
364
- <p>
365
- There's a lot of excellent work that was introduced around the same time as ours.
366
- </p>
367
- <p>
368
- <a href="https://arxiv.org/abs/2104.09125" target="_blank">Progressive Encoding for Neural Optimization</a> introduces an idea similar to our windowed position encoding for coarse-to-fine optimization.
369
- </p>
370
- <p>
371
- <a href="https://www.albertpumarola.com/research/D-NeRF/index.html" target="_blank">D-NeRF</a> and <a href="https://gvv.mpi-inf.mpg.de/projects/nonrigid_nerf/" target="_blank">NR-NeRF</a>
372
- both use deformation fields to model non-rigid scenes.
373
- </p>
374
- <p>
375
- Some works model videos with a NeRF by directly modulating the density, such as <a href="https://video-nerf.github.io/" target="_blank">Video-NeRF</a>, <a href="https://www.cs.cornell.edu/~zl548/NSFF/" target="_blank">NSFF</a>, and <a href="https://neural-3d-video.github.io/" target="_blank">DyNeRF</a>
376
- </p>
377
- <p>
378
- There are probably many more by the time you are reading this. Check out <a href="https://dellaert.github.io/NeRF/" target="_blank">Frank Dellart's survey on recent NeRF papers</a>, and <a href="https://github.com/yenchenlin/awesome-NeRF" target="_blank">Yen-Chen Lin's curated list of NeRF papers</a>.
379
- </p>
380
- </div>
381
- </div>
382
- </div>
383
- <!--/ Concurrent Work. -->
384
-
385
- </div>
386
- </section>
387
-
388
-
389
- <section class="section" id="BibTeX">
390
- <div class="container is-max-desktop content">
391
- <h2 class="title">BibTeX</h2>
392
- <pre><code>@article{park2021nerfies,
393
- author = {Park, Keunhong and Sinha, Utkarsh and Barron, Jonathan T. and Bouaziz, Sofien and Goldman, Dan B and Seitz, Steven M. and Martin-Brualla, Ricardo},
394
- title = {Nerfies: Deformable Neural Radiance Fields},
395
- journal = {ICCV},
396
- year = {2021},
397
- }</code></pre>
398
- </div>
399
- </section>
400
-
401
-
402
- <footer class="footer">
403
- <div class="container">
404
- <div class="content has-text-centered">
405
- <a class="icon-link" target="_blank"
406
- href="./static/videos/nerfies_paper.pdf">
407
- <i class="fas fa-file-pdf"></i>
408
- </a>
409
- <a class="icon-link" href="https://github.com/keunhong" target="_blank" class="external-link" disabled>
410
- <i class="fab fa-github"></i>
411
- </a>
412
- </div>
413
- <div class="columns is-centered">
414
- <div class="column is-8">
415
- <div class="content">
416
- <p>
417
- This website is licensed under a <a rel="license" target="_blank"
418
- href="http://creativecommons.org/licenses/by-sa/4.0/">Creative
419
- Commons Attribution-ShareAlike 4.0 International License</a>.
420
- </p>
421
- <p>
422
- This means you are free to borrow the <a target="_blank"
423
- href="https://github.com/nerfies/nerfies.github.io">source code</a> of this website,
424
- we just ask that you link back to this page in the footer.
425
- Please remember to remove the analytics code included in the header of the website which
426
- you do not want on your website.
427
- </p>
428
- </div>
429
- </div>
430
- </div>
431
- </div>
432
- </footer>
433
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
434
  </body>
435
- </html>
 
1
  <!DOCTYPE html>
2
+ <html lang="en">
3
  <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Italian Brinarot</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
9
+ <style>
10
+ @import url('https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap');
11
+
12
+ body {
13
+ font-family: 'Poppins', sans-serif;
14
+ background: linear-gradient(135deg, #f5f7fa 0%, #e4e8f0 100%);
15
+ }
16
+
17
+ .character-card {
18
+ transition: all 0.3s cubic-bezier(0.25, 0.8, 0.25, 1);
19
+ perspective: 1000px;
20
+ }
21
+
22
+ .character-card:hover {
23
+ transform: translateY(-8px);
24
+ box-shadow: 0 15px 30px rgba(0,0,0,0.12);
25
+ }
26
+
27
+ .image-container {
28
+ /* REMOVED clip-path: circle(50% at 50% 50%); */
29
+ background: linear-gradient(145deg, #ffffff, #e6e6e6);
30
+ box-shadow: 0 4px 15px rgba(0,0,0,0.1);
31
+ /* Tailwind classes will handle rounding and overflow */
32
+ }
33
+
34
+ .play-btn {
35
+ transition: all 0.2s ease;
36
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
37
+ }
38
+
39
+ .play-btn:hover {
40
+ transform: translateY(-2px);
41
+ box-shadow: 0 5px 15px rgba(118, 75, 162, 0.4);
42
+ }
43
+
44
+ .play-btn:active {
45
+ transform: translateY(0);
46
+ }
47
+
48
+ .gradient-text {
49
+ background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
50
+ -webkit-background-clip: text;
51
+ background-clip: text;
52
+ color: transparent;
53
+ }
54
+
55
+ .header-divider {
56
+ height: 4px;
57
+ background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
58
+ }
59
+
60
+ @media (max-width: 640px) {
61
+ .character-name {
62
+ font-size: 1rem;
63
+ }
64
+ }
65
+ </style>
66
  </head>
67
+ <body class="min-h-screen">
68
+ <div class="container mx-auto px-4 py-8">
69
+ <!-- Header -->
70
+ <header class="text-center mb-12">
71
+ <h1 class="text-4xl md:text-5xl font-bold gradient-text mb-2">Italian Brinarot</h1>
72
+ <div class="header-divider w-32 mx-auto rounded-full mb-6"></div>
73
+ <p class="text-gray-600 max-w-2xl mx-auto">Discover the magical sounds of Italian Brinarot characters</p>
74
+ </header>
75
+
76
+ <!-- Character Grid -->
77
+ <div id="characterGrid" class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-8"></div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
79
 
80
+ <!-- Embedded Character Data -->
81
+ <script>
82
+ const characterData = {
83
+ "Bombardiro Crocodilo": {
84
+ "image_path": "./assets/Bombardiro_Crocodilo.png",
85
+ "audio_path": "./assets/Bombardiro_Crocodilo.wav"
86
+ },
87
+ "Tralalero Tralala": {
88
+ "image_path": "./assets/Tralalero_Tralala.png",
89
+ "audio_path": "./assets/Tralalero_Tralala.wav"
90
+ },
91
+ "Bombombini Gusini": {
92
+ "image_path": "./assets/Bombombini_Gusini.png",
93
+ "audio_path": "./assets/Bombombini_Gusini.wav"
94
+ },
95
+ "Tung Tung Tung Tung Tung Tung Tung Tung Tung Sahur": {
96
+ "image_path": "./assets/Tung_Tung_Tung_Tung_Tung_Tung_Tung_Tung_Tung_Sahur.png",
97
+ "audio_path": "./assets/Tung_Tung_Tung_Tung_Tung_Tung_Tung_Tung_Tung_Sahur.wav"
98
+ },
99
+ "Brr Brr Patapim": {
100
+ "image_path": "./assets/Brr_Brr_Patapim.png",
101
+ "audio_path": "./assets/Brr_Brr_Patapim.wav"
102
+ },
103
+ "Cappuccino Assassino": {
104
+ "image_path": "./assets/Cappuccino_Assassino.png",
105
+ "audio_path": "./assets/Cappuccino_Assassino.wav"
106
+ },
107
+ "Lirili Larila": {
108
+ "image_path": "./assets/Lirili_Larila.png",
109
+ "audio_path": "./assets/Lirili_Larila.wav"
110
+ },
111
+ "Trulimero Trulichina": {
112
+ "image_path": "./assets/Trulimero_Trulichina.png",
113
+ "audio_path": "./assets/Trulimero_Trulichina.wav"
114
+ },
115
+ "Boneca Ambalabu": {
116
+ "image_path": "./assets/Boneca_Ambalabu.png",
117
+ "audio_path": "./assets/Boneca_Ambalabu.wav"
118
+ },
119
+ "Chimpanzini Bananini": {
120
+ "image_path": "./assets/Chimpanzini_Bananini.png",
121
+ "audio_path": "./assets/Chimpanzini_Bananini.wav"
122
+ },
123
+ "Bananita Dolfinita": {
124
+ "image_path": "./assets/Bananita_Dolfinita.png",
125
+ "audio_path": "./assets/Bananita_Dolfinita.wav"
126
+ },
127
+ "Bluberini Octopusini": {
128
+ "image_path": "./assets/Bluberini_Octopusini.png",
129
+ "audio_path": "./assets/Bluberini_Octopusini.wav"
130
+ },
131
+ "Bobrito Bandito": {
132
+ "image_path": "./assets/Bobrito_Bandito.png",
133
+ "audio_path": "./assets/Bobrito_Bandito.wav"
134
+ },
135
+ "Brri Brri Bicus Dicus": {
136
+ "image_path": "./assets/Brri_Brri_Bicus_Dicus.png",
137
+ "audio_path": "./assets/Brri_Brri_Bicus_Dicus.wav"
138
+ },
139
+ "Burbaloni Luliloli": {
140
+ "image_path": "./assets/Burbaloni_Luliloli.png",
141
+ "audio_path": "./assets/Burbaloni_Luliloli.wav"
142
+ },
143
+ "Chimpanzini Annasini": {
144
+ "image_path": "./assets/Chimpanzini_Annasini.png",
145
+ "audio_path": "./assets/Chimpanzini_Annasini.wav"
146
+ },
147
+ "Chimpanzini Cocosini": {
148
+ "image_path": "./assets/Chimpanzini_Cocosini.png",
149
+ "audio_path": "./assets/Chimpanzini_Cocosini.wav"
150
+ },
151
+ "Cocofanto Elefanto": {
152
+ "image_path": "./assets/Cocofanto_Elefanto.png",
153
+ "audio_path": "./assets/Cocofanto_Elefanto.wav"
154
+ },
155
+ "Frigo Camelo Buffardello": {
156
+ "image_path": "./assets/frigo_camelo_buffardello.png",
157
+ "audio_path": "./assets/frigo_camelo_buffardello.wav"
158
+ },
159
+ "Giraffe Celeste": {
160
+ "image_path": "./assets/Giraffe_Celeste.png",
161
+ "audio_path": "./assets/Giraffe_Celeste.wav"
162
+ },
163
+ "Glorbo Fruttodrillo": {
164
+ "image_path": "./assets/Glorbo_Fruttodrillo.png",
165
+ "audio_path": "./assets/Glorbo_Fruttodrillo.wav"
166
+ },
167
+ "Il Cacto Hipopotoma": {
168
+ "image_path": "./assets/il_cacto_hipopotoma.png",
169
+ "audio_path": "./assets/il_cacto_hipopotoma.wav"
170
+ },
171
+ "Trippi Troppi Troppa Trippa": {
172
+ "image_path": "./assets/Trippi_Troppi_Troppa_Trippa.png",
173
+ "audio_path": "./assets/Trippi_Troppi_Troppa_Trippa.wav"
174
+ }
175
+ };
176
+
177
+ // Function to load and display characters
178
+ function loadCharacters() {
179
+ const characterGrid = document.getElementById('characterGrid');
180
+
181
+ // Clear any existing content
182
+ characterGrid.innerHTML = '';
183
+
184
+ // Create cards for each character
185
+ Object.entries(characterData).forEach(([name, data]) => {
186
+ const card = document.createElement('div');
187
+ card.className = 'character-card bg-white rounded-2xl overflow-hidden shadow-md flex flex-col items-center p-6';
188
+
189
+ // Image container - **MODIFIED** for square with rounded corners
190
+ const imageContainer = document.createElement('div');
191
+ // Added rounded-xl (you can change this) and overflow-hidden
192
+ imageContainer.className = 'image-container mb-4 w-40 h-40 flex items-center justify-center rounded-2xl overflow-hidden'; // <-- MODIFIED LINE
193
+
194
+ const image = document.createElement('img');
195
+ image.src = data.image_path.replace(/\\/g, '/');
196
+ image.alt = name;
197
+ image.className = 'w-full h-full object-cover'; // object-cover ensures the image fills the square container
198
+ imageContainer.appendChild(image);
199
+
200
+ // Character name
201
+ const nameElement = document.createElement('h3');
202
+ nameElement.className = 'character-name text-lg md:text-xl font-semibold text-gray-800 mb-3 text-center';
203
+ nameElement.textContent = name;
204
+
205
+ // Play/Pause button
206
+ const playButton = document.createElement('button');
207
+ // **MODIFIED** - Adjusted button gradient for better contrast/look (Optional)
208
+ playButton.className = 'play-btn text-white font-medium py-2 px-6 rounded-full flex items-center';
209
+
210
+ const playIcon = document.createElement('i');
211
+ playIcon.className = 'fas fa-play mr-2';
212
+
213
+ playButton.appendChild(playIcon);
214
+ playButton.appendChild(document.createTextNode('Play'));
215
+
216
+ // Audio element
217
+ const audio = new Audio(data.audio_path.replace(/\\/g, '/'));
218
+ let isPlaying = false;
219
+
220
+ // Keep track of all audios and buttons to manage pause state
221
+ let currentAudio = null;
222
+ let currentButton = null;
223
+
224
+ // Play/Pause button click handler - **REVISED** for better pause handling
225
+ playButton.addEventListener('click', () => {
226
+ // Stop any other audio that might be playing
227
+ document.querySelectorAll('audio').forEach(a => {
228
+ if (a !== audio && !a.paused) {
229
+ a.pause();
230
+ // Reset the button associated with that audio
231
+ const relatedButton = a.nextElementSibling; // Assuming button is the next sibling
232
+ if (relatedButton && relatedButton.classList.contains('play-btn')) {
233
+ relatedButton.innerHTML = '<i class="fas fa-play mr-2"></i>Play';
234
+ relatedButton.style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'; // Reset background
235
+ // Find the 'isPlaying' state for that audio (more complex, simplified here)
236
+ }
237
+ }
238
+ });
239
+ // Find *all* buttons and reset their state visually if they aren't the current one
240
+ document.querySelectorAll('.play-btn').forEach(btn => {
241
+ if (btn !== playButton && !btn.previousElementSibling.paused) { // Check if audio associated with *other* button is playing
242
+ // This part is tricky without a direct link; the logic below handles the active one better.
243
+ } else if (btn !== playButton) {
244
+ btn.innerHTML = '<i class="fas fa-play mr-2"></i>Play';
245
+ btn.style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)';
246
+ }
247
+ });
248
+
249
+
250
+ if (isPlaying) {
251
+ audio.pause();
252
+ playButton.innerHTML = '<i class="fas fa-play mr-2"></i>Play';
253
+ playButton.style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'; // Reset background
254
+ isPlaying = false;
255
+ currentAudio = null;
256
+ currentButton = null;
257
+ } else {
258
+ audio.currentTime = 0;
259
+ audio.play();
260
+ playButton.innerHTML = '<i class="fas fa-pause mr-2"></i>Pause';
261
+ playButton.style.background = '#ef4444'; // Example: Red background for pause state
262
+ isPlaying = true;
263
+ currentAudio = audio;
264
+ currentButton = playButton;
265
+ }
266
+ });
267
+
268
+ // When audio ends, reset button
269
+ audio.addEventListener('ended', () => {
270
+ playButton.innerHTML = '<i class="fas fa-play mr-2"></i>Play';
271
+ playButton.style.background = 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)'; // Reset background
272
+ isPlaying = false;
273
+ currentAudio = null;
274
+ currentButton = null;
275
+ });
276
+
277
+ // Assemble the card
278
+ card.appendChild(imageContainer);
279
+ card.appendChild(nameElement);
280
+ card.appendChild(audio); // Keep audio in DOM for easier access if needed, hide it
281
+ audio.style.display = 'none';
282
+ card.appendChild(playButton);
283
+
284
+
285
+ // Add card to the grid
286
+ characterGrid.appendChild(card);
287
+ });
288
+
289
+ // Improved pause handling: Add a global listener if needed, or rely on the button click logic above.
290
+ // The revised click handler above should now pause other audios when a new one is played.
291
+ }
292
+
293
+ // Load characters when the page loads
294
+ window.addEventListener('DOMContentLoaded', loadCharacters);
295
+ </script>
296
  </body>
297
+ </html>