Denizfe commited on
Commit
d121696
·
verified ·
1 Parent(s): 89b58f2

bildirim gönderilmedi - Initial Deployment

Browse files
Files changed (2) hide show
  1. README.md +7 -5
  2. index.html +527 -19
README.md CHANGED
@@ -1,10 +1,12 @@
1
  ---
2
- title: Machinelearning
3
- emoji:
4
- colorFrom: indigo
5
- colorTo: yellow
6
  sdk: static
7
  pinned: false
 
 
8
  ---
9
 
10
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
1
  ---
2
+ title: machinelearning
3
+ emoji: 🐳
4
+ colorFrom: red
5
+ colorTo: red
6
  sdk: static
7
  pinned: false
8
+ tags:
9
+ - deepsite
10
  ---
11
 
12
+ Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
index.html CHANGED
@@ -1,19 +1,527 @@
1
- <!doctype html>
2
- <html>
3
- <head>
4
- <meta charset="utf-8" />
5
- <meta name="viewport" content="width=device-width" />
6
- <title>My static Space</title>
7
- <link rel="stylesheet" href="style.css" />
8
- </head>
9
- <body>
10
- <div class="card">
11
- <h1>Welcome to your static Space!</h1>
12
- <p>You can modify this app directly by editing <i>index.html</i> in the Files and versions tab.</p>
13
- <p>
14
- Also don't forget to check the
15
- <a href="https://huggingface.co/docs/hub/spaces" target="_blank">Spaces documentation</a>.
16
- </p>
17
- </div>
18
- </body>
19
- </html>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="tr">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Teachable Machine Görüntü Modeli</title>
7
+ <style>
8
+ .notification {
9
+ position: fixed;
10
+ top: 50%;
11
+ left: 50%;
12
+ transform: translate(-50%, -50%);
13
+ background-color: #3498db;
14
+ color: white;
15
+ padding: 25px 35px;
16
+ border-radius: 16px;
17
+ box-shadow: 0 15px 30px rgba(0,0,0,0.3);
18
+ z-index: 1000;
19
+ font-size: 1.5em;
20
+ text-align: center;
21
+ min-width: 300px;
22
+ animation: fadeIn 0.3s;
23
+ font-weight: bold;
24
+ display: flex;
25
+ align-items: center;
26
+ justify-content: space-between;
27
+ }
28
+ .notification-close {
29
+ background: none;
30
+ border: none;
31
+ color: white;
32
+ font-size: 1.2em;
33
+ cursor: pointer;
34
+ margin-left: 20px;
35
+ padding: 5px;
36
+ }
37
+
38
+ @keyframes fadeIn {
39
+ from { opacity: 0; transform: translate(-50%, -70%); }
40
+ to { opacity: 1; transform: translate(-50%, -50%); }
41
+ }
42
+
43
+ @keyframes fadeOut {
44
+ from { opacity: 1; }
45
+ to { opacity: 0; }
46
+ }
47
+
48
+ body {
49
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
50
+ display: flex;
51
+ flex-direction: column;
52
+ align-items: center;
53
+ margin: 0;
54
+ padding: 20px;
55
+ background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
56
+ min-height: 100vh;
57
+ color: #333;
58
+ }
59
+ .container {
60
+ background-color: white;
61
+ border-radius: 16px;
62
+ box-shadow: 0 10px 30px rgba(0,0,0,0.1);
63
+ padding: 40px;
64
+ max-width: 900px;
65
+ width: 100%;
66
+ margin: 20px auto;
67
+ transition: all 0.3s ease;
68
+ }
69
+ .container:hover {
70
+ box-shadow: 0 15px 35px rgba(0,0,0,0.15);
71
+ }
72
+ h1 {
73
+ color: #2c3e50;
74
+ margin-bottom: 15px;
75
+ font-size: 2.2rem;
76
+ text-align: center;
77
+ position: relative;
78
+ padding-bottom: 15px;
79
+ }
80
+ h1:after {
81
+ content: '';
82
+ position: absolute;
83
+ bottom: 0;
84
+ left: 50%;
85
+ transform: translateX(-50%);
86
+ width: 80px;
87
+ height: 3px;
88
+ background: linear-gradient(to right, #3498db, #9b59b6);
89
+ border-radius: 3px;
90
+ }
91
+ p {
92
+ color: #7f8c8d;
93
+ margin-bottom: 20px;
94
+ }
95
+ #webcam-container {
96
+ margin: 25px 0;
97
+ border: 3px solid #3498db;
98
+ border-radius: 12px;
99
+ overflow: hidden;
100
+ display: flex;
101
+ justify-content: center;
102
+ align-items: center;
103
+ min-height: 300px;
104
+ background: linear-gradient(45deg, #f8f9fa, #e9ecef);
105
+ box-shadow: 0 8px 20px rgba(0,0,0,0.1);
106
+ position: relative;
107
+ transition: all 0.3s;
108
+ }
109
+ #webcam-container:hover {
110
+ box-shadow: 0 12px 25px rgba(0,0,0,0.15);
111
+ }
112
+ #webcam-container:before {
113
+ content: "Kamera yükleniyor...";
114
+ position: absolute;
115
+ color: #7f8c8d;
116
+ font-size: 1em;
117
+ font-weight: 500;
118
+ }
119
+ #webcam-container video,
120
+ #webcam-container canvas {
121
+ display: block;
122
+ max-width: 100%;
123
+ max-height: 100%;
124
+ object-fit: contain;
125
+ }
126
+ #label-container {
127
+ margin: 25px 0;
128
+ font-size: 1.2em;
129
+ font-weight: bold;
130
+ background: linear-gradient(45deg, #f8f9fa, #e9ecef);
131
+ padding: 20px;
132
+ border-radius: 12px;
133
+ width: 100%;
134
+ box-shadow: 0 5px 15px rgba(0,0,0,0.05);
135
+ }
136
+ #label-container div {
137
+ transition: all 0.3s;
138
+ }
139
+ #label-container div:hover {
140
+ transform: translateX(5px);
141
+ background-color: rgba(52, 152, 219, 0.2) !important;
142
+ }
143
+ .button-group {
144
+ display: flex;
145
+ gap: 10px;
146
+ margin: 15px 0;
147
+ flex-wrap: wrap;
148
+ justify-content: center;
149
+ }
150
+ button {
151
+ padding: 14px 28px;
152
+ font-size: 1em;
153
+ cursor: pointer;
154
+ background: linear-gradient(to right, #3498db, #2980b9);
155
+ color: white;
156
+ border: none;
157
+ border-radius: 50px;
158
+ transition: all 0.3s;
159
+ font-weight: 600;
160
+ box-shadow: 0 4px 6px rgba(0,0,0,0.1);
161
+ position: relative;
162
+ overflow: hidden;
163
+ }
164
+ button:hover {
165
+ transform: translateY(-3px);
166
+ box-shadow: 0 6px 10px rgba(0,0,0,0.15);
167
+ }
168
+ button:active {
169
+ transform: translateY(1px);
170
+ }
171
+ button:before {
172
+ content: '';
173
+ position: absolute;
174
+ top: 0;
175
+ left: -100%;
176
+ width: 100%;
177
+ height: 100%;
178
+ background: linear-gradient(90deg, transparent, rgba(255,255,255,0.2), transparent);
179
+ transition: 0.5s;
180
+ }
181
+ button:hover:before {
182
+ left: 100%;
183
+ }
184
+ button.secondary {
185
+ background: linear-gradient(to right, #95a5a6, #7f8c8d);
186
+ }
187
+ #imagePreview {
188
+ display: flex;
189
+ justify-content: center;
190
+ align-items: center;
191
+ min-height: 200px;
192
+ border: 2px dashed #bdc3c7;
193
+ border-radius: 12px;
194
+ padding: 20px;
195
+ margin: 20px 0;
196
+ background-color: white;
197
+ transition: all 0.3s;
198
+ position: relative;
199
+ overflow: hidden;
200
+ }
201
+ #imagePreview:hover {
202
+ border-color: #3498db;
203
+ box-shadow: 0 5px 15px rgba(0,0,0,0.05);
204
+ }
205
+ .upload-section {
206
+ margin: 30px 0;
207
+ padding: 25px;
208
+ background: linear-gradient(45deg, #f8f9fa, #e9ecef);
209
+ border-radius: 12px;
210
+ box-shadow: 0 5px 15px rgba(0,0,0,0.05);
211
+ transition: all 0.3s;
212
+ }
213
+ .upload-section:hover {
214
+ box-shadow: 0 8px 20px rgba(0,0,0,0.1);
215
+ }
216
+ #fileError {
217
+ color: #e74c3c;
218
+ margin-top: 10px;
219
+ font-size: 0.9em;
220
+ }
221
+ </style>
222
+ </head>
223
+ <body>
224
+
225
+ <div class="container">
226
+ <h1>Teachable Machine Görüntü Modeli</h1>
227
+ <p>Modeli ve kamerayı başlatmak için butona tıklayın.</p>
228
+
229
+ <div class="button-group">
230
+ <button type="button" onclick="toggleCamera()" id="cameraBtn">Kamerayı Aç</button>
231
+ </div>
232
+
233
+ <div id="webcam-container"></div>
234
+ <div class="button-group" style="margin-top: 20px;">
235
+ <button type="button" onclick="predict()" id="predictBtn" disabled>Tahmin Et</button>
236
+ </div>
237
+
238
+ <div class="upload-section">
239
+ <h2>Veya Resim Yükle</h2>
240
+ <div class="button-group">
241
+ <input type="file" id="fileUpload" accept="image/*" style="display: none;">
242
+ <button type="button" onclick="document.getElementById('fileUpload').click()" class="secondary">Resim Seç</button>
243
+ </div>
244
+ <div id="fileError"></div>
245
+ <div id="imagePreview"></div>
246
+ </div>
247
+
248
+ <div id="label-container"></div>
249
+ </div>
250
+
251
+ <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest/dist/tf.min.js"></script>
252
+ <script src="https://cdn.jsdelivr.net/npm/@teachablemachine/image@latest/dist/teachablemachine-image.min.js"></script>
253
+
254
+ <script type="text/javascript">
255
+ // Notification function - shows only once on page load
256
+ function showNotification(message) {
257
+ // Check if notification was already shown
258
+ if (sessionStorage.getItem('notificationShown')) return;
259
+
260
+ const notification = document.createElement('div');
261
+ notification.className = 'notification';
262
+ notification.innerHTML = `
263
+ <span>${message}</span>
264
+ <button class="notification-close">&times;</button>
265
+ `;
266
+
267
+ notification.querySelector('.notification-close').onclick = () => {
268
+ notification.remove();
269
+ };
270
+
271
+ document.body.appendChild(notification);
272
+ sessionStorage.setItem('notificationShown', 'true');
273
+ }
274
+
275
+ // Show welcome notification on page load
276
+ window.onload = function() {
277
+ init(); // Original init call
278
+ showNotification('Hoş geldiniz!');
279
+ };
280
+
281
+ // Daha fazla API fonksiyonu burada bulunabilir:
282
+ // https://github.com/googlecreativelab/teachablemachine-community/tree/master/libraries/image
283
+
284
+ // Teachable Machine dışa aktarma panelinden sağlanan modelinizin bağlantısı
285
+ const URL = "https://teachablemachine.withgoogle.com/models/72Gu94mWN1/";
286
+
287
+ let model, webcam, labelContainer, maxPredictions;
288
+
289
+ let cameraActive = false;
290
+
291
+ // Kamerayı aç/kapat
292
+ async function toggleCamera() {
293
+ if (!model) {
294
+ // Model yüklenmemişse önce yükle
295
+ const modelURL = URL + "model.json";
296
+ const metadataURL = URL + "metadata.json";
297
+ model = await tmImage.load(modelURL, metadataURL);
298
+ maxPredictions = model.getTotalClasses();
299
+ }
300
+
301
+ if (!cameraActive) {
302
+ // Kamerayı başlat
303
+ const flip = true;
304
+ webcam = new tmImage.Webcam(400, 400, flip);
305
+ await webcam.setup();
306
+ await webcam.play();
307
+
308
+ document.getElementById("webcam-container").innerHTML = '';
309
+ document.getElementById("webcam-container").appendChild(webcam.canvas);
310
+ document.getElementById('cameraBtn').textContent = 'Kamerayı Kapat';
311
+ document.getElementById('predictBtn').disabled = false;
312
+ cameraActive = true;
313
+
314
+ // Optimize for smoother video
315
+ let lastTime = 0;
316
+ const fps = 30;
317
+ const interval = 1000 / fps;
318
+
319
+ const optimizedLoop = async (timestamp) => {
320
+ if (!cameraActive) return;
321
+
322
+ if (timestamp - lastTime >= interval) {
323
+ webcam.update(); // web kamerası çerçevesini güncelle
324
+ lastTime = timestamp;
325
+ }
326
+
327
+ requestAnimationFrame(optimizedLoop);
328
+ };
329
+
330
+ requestAnimationFrame(optimizedLoop);
331
+
332
+ // Optimized prediction loop for webcam
333
+ const predictWebcam = async () => {
334
+ if (!cameraActive) return;
335
+
336
+ // Predict the current webcam frame
337
+ const prediction = await model.predict(webcam.canvas);
338
+
339
+ // Sort predictions by probability (highest first)
340
+ prediction.sort((a, b) => b.probability - a.probability);
341
+
342
+ // Update label container
343
+ const labelContainer = document.getElementById('label-container');
344
+ labelContainer.innerHTML = '';
345
+ for (let i = 0; i < maxPredictions; i++) {
346
+ const probabilityPercent = (prediction[i].probability * 100).toFixed(2);
347
+
348
+ // Show notification if probability > 80%
349
+ if (prediction[i].probability > 0.8) {
350
+ showNotification(`Bu bir ${prediction[i].className}`);
351
+ }
352
+
353
+ const classPrediction = `
354
+ <div style="margin: 8px 0; padding: 8px; background-color: rgba(52, 152, 219, 0.1); border-radius: 4px;">
355
+ <strong>${prediction[i].className}:</strong> ${probabilityPercent}%
356
+ <div style="height: 5px; background-color: #ecf0f1; margin-top: 5px; border-radius: 3px;">
357
+ <div style="width: ${probabilityPercent}%; height: 100%; background-color: #3498db; border-radius: 3px;"></div>
358
+ </div>
359
+ </div>`;
360
+ labelContainer.innerHTML += classPrediction;
361
+ }
362
+
363
+ // Call this function again on the next animation frame
364
+ requestAnimationFrame(predictWebcam);
365
+ };
366
+
367
+ // Start the prediction loop
368
+ predictWebcam();
369
+ } else {
370
+ // Kamerayı kapat
371
+ if (webcam) {
372
+ webcam.stop();
373
+ }
374
+ document.getElementById('cameraBtn').textContent = 'Kamerayı Aç';
375
+ document.getElementById("webcam-container").innerHTML = '';
376
+ cameraActive = false;
377
+ }
378
+ }
379
+
380
+ // Modeli yükle (başlangıçta)
381
+ async function init() {
382
+ if (!model) {
383
+ const modelURL = URL + "model.json";
384
+ const metadataURL = URL + "metadata.json";
385
+ model = await tmImage.load(modelURL, metadataURL);
386
+ maxPredictions = model.getTotalClasses();
387
+ document.getElementById('predictBtn').disabled = false;
388
+ }
389
+ }
390
+
391
+ // Sayfa yüklendiğinde modeli yükle
392
+ window.onload = init;
393
+
394
+ // Web kamerası görüntüsünü görüntü modelinden geçir
395
+ // Maximum file size in bytes (2MB)
396
+ const MAX_FILE_SIZE = 2 * 1024 * 1024;
397
+ const ALLOWED_TYPES = ['image/jpeg', 'image/png', 'image/gif', 'image/webp'];
398
+
399
+ // Handle file upload
400
+ document.getElementById('fileUpload').addEventListener('change', function(e) {
401
+ const file = e.target.files[0];
402
+ const errorElement = document.getElementById('fileError');
403
+ const previewElement = document.getElementById('imagePreview');
404
+
405
+ // Reset previous state
406
+ errorElement.textContent = '';
407
+ previewElement.innerHTML = '';
408
+
409
+ if (!file) return;
410
+
411
+ // Validate file type
412
+ if (!ALLOWED_TYPES.includes(file.type)) {
413
+ errorElement.textContent = 'Geçersiz dosya türü. Sadece JPG, PNG, GIF veya WEBP yükleyebilirsiniz.';
414
+ return;
415
+ }
416
+
417
+ // Validate file size
418
+ if (file.size > MAX_FILE_SIZE) {
419
+ errorElement.textContent = 'Dosya boyutu çok büyük. Maksimum 2MB boyutunda dosya yükleyebilirsiniz.';
420
+ return;
421
+ }
422
+
423
+ // Create preview
424
+ const reader = new FileReader();
425
+ reader.onload = function(e) {
426
+ const img = document.createElement('img');
427
+ img.src = e.target.result;
428
+ img.style.maxWidth = '200px';
429
+ img.style.maxHeight = '200px';
430
+ previewElement.appendChild(img);
431
+
432
+ // Predict on the uploaded image
433
+ predictImage(img);
434
+ };
435
+ reader.readAsDataURL(file);
436
+ });
437
+
438
+ let lastDetectedClass = null;
439
+ let lastNotificationTime = 0;
440
+
441
+ // Predict on uploaded image (with live updates)
442
+ async function predictImage(imageElement) {
443
+ if (!model) {
444
+ await init();
445
+ }
446
+
447
+ // Clear previous results
448
+ const labelContainer = document.getElementById('label-container');
449
+ labelContainer.innerHTML = '';
450
+
451
+ // Start continuous prediction
452
+ const predictLoop = async () => {
453
+ if (!imageElement.parentNode) return; // Stop if image was removed
454
+
455
+ const prediction = await model.predict(imageElement);
456
+
457
+ // Sort predictions by probability (highest first)
458
+ prediction.sort((a, b) => b.probability - a.probability);
459
+
460
+ labelContainer.innerHTML = '';
461
+ for (let i = 0; i < maxPredictions; i++) {
462
+ const probabilityPercent = (prediction[i].probability * 100).toFixed(2);
463
+
464
+ // Show notification if probability > 80% and class changed or 5 seconds passed
465
+ const currentTime = Date.now();
466
+ if (prediction[i].probability > 0.8 &&
467
+ (prediction[i].className !== lastDetectedClass || currentTime - lastNotificationTime > 5000)) {
468
+ showNotification(`Bu bir ${prediction[i].className}`);
469
+ lastDetectedClass = prediction[i].className;
470
+ lastNotificationTime = currentTime;
471
+ }
472
+
473
+ const classPrediction = `
474
+ <div style="margin: 8px 0; padding: 8px; background-color: rgba(52, 152, 219, 0.1); border-radius: 4px;">
475
+ <strong>${prediction[i].className}:</strong> ${probabilityPercent}%
476
+ <div style="height: 5px; background-color: #ecf0f1; margin-top: 5px; border-radius: 3px;">
477
+ <div style="width: ${probabilityPercent}%; height: 100%; background-color: #3498db; border-radius: 3px;"></div>
478
+ </div>
479
+ </div>`;
480
+ labelContainer.innerHTML += classPrediction;
481
+ }
482
+
483
+ requestAnimationFrame(predictLoop);
484
+ };
485
+
486
+ predictLoop();
487
+ }
488
+
489
+ async function predict() {
490
+ if (!model) {
491
+ alert('Lütfen önce modeli başlatın!');
492
+ return;
493
+ }
494
+
495
+ try {
496
+ // Only predict if we have an active source
497
+ if (!webcam?.canvas && !document.querySelector('#imagePreview img')) return;
498
+
499
+ // predict fonksiyonu bir resim, video veya canvas html öğesi alabilir
500
+ const prediction = await model.predict(webcam?.canvas || document.querySelector('#imagePreview img'), { flipHorizontal: false });
501
+
502
+ // Clear previous results
503
+ labelContainer.innerHTML = '';
504
+
505
+ // Sort predictions by probability (highest first)
506
+ prediction.sort((a, b) => b.probability - a.probability);
507
+
508
+ for (let i = 0; i < maxPredictions; i++) {
509
+ const probabilityPercent = (prediction[i].probability * 100).toFixed(2);
510
+ const classPrediction = `
511
+ <div style="margin: 8px 0; padding: 8px; background-color: rgba(52, 152, 219, 0.1); border-radius: 4px;">
512
+ <strong>${prediction[i].className}:</strong> ${probabilityPercent}%
513
+ <div style="height: 5px; background-color: #ecf0f1; margin-top: 5px; border-radius: 3px;">
514
+ <div style="width: ${probabilityPercent}%; height: 100%; background-color: #3498db; border-radius: 3px;"></div>
515
+ </div>
516
+ </div>`;
517
+ labelContainer.innerHTML += classPrediction;
518
+ }
519
+ } catch (error) {
520
+ console.error('Prediction error:', error);
521
+ labelContainer.innerHTML = '<div style="color: #e74c3c;">Tahmin yapılırken bir hata oluştu. Lütfen kamera veya resim yüklediğinizden emin olun.</div>';
522
+ }
523
+ }
524
+ </script>
525
+
526
+ <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=Denizfe/machinelearning" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
527
+ </html>