punab3 commited on
Commit
5a619f5
·
verified ·
1 Parent(s): 32d010b

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +158 -19
index.html CHANGED
@@ -1,19 +1,158 @@
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="id">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Pengenalan Pose dengan Suara</title>
7
+ <style>
8
+ body {
9
+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
10
+ text-align: center;
11
+ background-color: #f4f4f9;
12
+ padding: 20px;
13
+ }
14
+ h2 { color: #333; }
15
+ #canvas {
16
+ border: 5px solid #007bff;
17
+ border-radius: 15px;
18
+ background-color: #000;
19
+ margin-top: 15px;
20
+ box-shadow: 0 4px 8px rgba(0,0,0,0.2);
21
+ }
22
+ button {
23
+ padding: 12px 30px;
24
+ font-size: 18px;
25
+ font-weight: bold;
26
+ cursor: pointer;
27
+ background-color: #28a745;
28
+ color: white;
29
+ border: none;
30
+ border-radius: 50px;
31
+ transition: 0.3s;
32
+ }
33
+ button:hover { background-color: #218838; }
34
+ #label-container {
35
+ margin-top: 20px;
36
+ display: flex;
37
+ flex-direction: column;
38
+ align-items: center;
39
+ gap: 10px;
40
+ }
41
+ #label-container div {
42
+ background: white;
43
+ padding: 10px 20px;
44
+ border-radius: 8px;
45
+ width: 250px;
46
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
47
+ font-weight: bold;
48
+ }
49
+ </style>
50
+ </head>
51
+ <body>
52
+
53
+ <h2>Teachable Machine Pose Model + Audio</h2>
54
+ <button type="button" onclick="init()">Mulai Kamera</button>
55
+
56
+ <div><canvas id="canvas"></canvas></div>
57
+ <div id="label-container"></div>
58
+
59
+ <!-- Load TensorFlow.js dan Teachable Machine Library -->
60
+ <script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@1.3.1/dist/tf.min.js"></script>
61
+ <script src="https://cdn.jsdelivr.net/npm/@teachablemachine/pose@0.8/dist/teachablemachine-pose.min.js"></script>
62
+
63
+ <script type="text/javascript">
64
+ // 1. Lokasi model (Hugging Face folder)
65
+ const URL = "./my_model/";
66
+ let model, webcam, ctx, labelContainer, maxPredictions;
67
+
68
+ // 2. Deklarasi file audio (Pastikan nama file di folder sama persis)
69
+ const audioFiles = {
70
+ "semangat": new Audio('mp3semangat.mp3'),
71
+ "berjuang": new Audio('mp3berjuang.mp3'),
72
+ "sukses": new Audio('mp3sukses.mp3'),
73
+ "hidup jokowi": new Audio('mp3hidup_jokowi.mp3'),
74
+ "mp3kicaukicaw": new Audio('mp3kicawkicaw.mp3')
75
+ };
76
+
77
+ let lastPlayedClass = "";
78
+
79
+ async function init() {
80
+ const modelURL = URL + "model.json";
81
+ const metadataURL = URL + "metadata.json";
82
+
83
+ // Load model
84
+ model = await tmPose.load(modelURL, metadataURL);
85
+ maxPredictions = model.getTotalClasses();
86
+
87
+ // Setup Webcam
88
+ const size = 400;
89
+ const flip = true;
90
+ webcam = new tmPose.Webcam(size, size, flip);
91
+ await webcam.setup();
92
+ await webcam.play();
93
+ window.requestAnimationFrame(loop);
94
+
95
+ // Persiapan Canvas & UI
96
+ const canvas = document.getElementById("canvas");
97
+ canvas.width = size; canvas.height = size;
98
+ ctx = canvas.getContext("2d");
99
+ labelContainer = document.getElementById("label-container");
100
+ for (let i = 0; i < maxPredictions; i++) {
101
+ labelContainer.appendChild(document.createElement("div"));
102
+ }
103
+ }
104
+
105
+ async function loop(timestamp) {
106
+ webcam.update();
107
+ await predict();
108
+ window.requestAnimationFrame(loop);
109
+ }
110
+
111
+ async function predict() {
112
+ const { pose, posenetOutput } = await model.estimatePose(webcam.canvas);
113
+ const prediction = await model.predict(posenetOutput);
114
+
115
+ for (let i = 0; i < maxPredictions; i++) {
116
+ const className = prediction[i].className;
117
+ const probability = prediction[i].probability;
118
+
119
+ // Update tampilan label
120
+ labelContainer.childNodes[i].innerHTML = `${className}: ${(probability * 100).toFixed(0)}%`;
121
+
122
+ // LOGIKA AUDIO:
123
+ // Putar jika akurasi > 90% DAN pose berubah dari sebelumnya
124
+ if (probability > 0.90 && lastPlayedClass !== className) {
125
+ playVoice(className);
126
+ lastPlayedClass = className;
127
+ }
128
+ }
129
+ drawPose(pose);
130
+ }
131
+
132
+ function playVoice(className) {
133
+ // Hentikan suara yang sedang berputar (Reset)
134
+ Object.values(audioFiles).forEach(audio => {
135
+ audio.pause();
136
+ audio.currentTime = 0;
137
+ });
138
+
139
+ // Cari audio berdasarkan nama class di Teachable Machine
140
+ const sound = audioFiles[className];
141
+ if (sound) {
142
+ sound.play().catch(e => console.log("Audio play error:", e));
143
+ }
144
+ }
145
+
146
+ function drawPose(pose) {
147
+ if (webcam.canvas) {
148
+ ctx.drawImage(webcam.canvas, 0, 0);
149
+ if (pose) {
150
+ const minPartConfidence = 0.5;
151
+ tmPose.drawKeypoints(pose.keypoints, minPartConfidence, ctx);
152
+ tmPose.drawSkeleton(pose.keypoints, minPartConfidence, ctx);
153
+ }
154
+ }
155
+ }
156
+ </script>
157
+ </body>
158
+ </html>