akhaliq HF Staff commited on
Commit
4387997
·
verified ·
1 Parent(s): 7169b4e

Upload index.js with huggingface_hub

Browse files
Files changed (1) hide show
  1. index.js +157 -63
index.js CHANGED
@@ -1,76 +1,170 @@
1
- import { pipeline } from 'https://cdn.jsdelivr.net/npm/@huggingface/transformers@3.4.1';
2
-
3
- // Reference the elements that we will need
4
- const status = document.getElementById('status');
5
- const fileUpload = document.getElementById('upload');
6
- const imageContainer = document.getElementById('container');
7
- const example = document.getElementById('example');
8
-
9
- const EXAMPLE_URL = 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/city-streets.jpg';
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
- // Create a new object detection pipeline
12
- status.textContent = 'Loading model...';
13
- const detector = await pipeline('object-detection', 'Xenova/detr-resnet-50');
14
- status.textContent = 'Ready';
15
 
16
- example.addEventListener('click', (e) => {
17
- e.preventDefault();
18
- detect(EXAMPLE_URL);
19
  });
20
 
21
- fileUpload.addEventListener('change', function (e) {
22
- const file = e.target.files[0];
23
- if (!file) {
24
- return;
25
- }
 
26
 
27
- const reader = new FileReader();
 
 
28
 
29
- // Set up a callback when the file is loaded
30
- reader.onload = e2 => detect(e2.target.result);
 
 
 
 
31
 
32
- reader.readAsDataURL(file);
 
 
 
 
 
33
  });
34
 
 
 
 
 
35
 
36
- // Detect objects in the image
37
- async function detect(img) {
38
- imageContainer.innerHTML = '';
39
- imageContainer.style.backgroundImage = `url(${img})`;
40
 
41
- status.textContent = 'Analysing...';
42
- const output = await detector(img, {
43
- threshold: 0.5,
44
- percentage: true,
45
- });
46
- status.textContent = '';
47
- output.forEach(renderBox);
48
- }
49
 
50
- // Render a bounding box and label on the image
51
- function renderBox({ box, label }) {
52
- const { xmax, xmin, ymax, ymin } = box;
53
-
54
- // Generate a random color for the box
55
- const color = '#' + Math.floor(Math.random() * 0xFFFFFF).toString(16).padStart(6, 0);
56
-
57
- // Draw the box
58
- const boxElement = document.createElement('div');
59
- boxElement.className = 'bounding-box';
60
- Object.assign(boxElement.style, {
61
- borderColor: color,
62
- left: 100 * xmin + '%',
63
- top: 100 * ymin + '%',
64
- width: 100 * (xmax - xmin) + '%',
65
- height: 100 * (ymax - ymin) + '%',
66
- })
67
-
68
- // Draw label
69
- const labelElement = document.createElement('span');
70
- labelElement.textContent = label;
71
- labelElement.className = 'bounding-box-label';
72
- labelElement.style.backgroundColor = color;
73
-
74
- boxElement.appendChild(labelElement);
75
- imageContainer.appendChild(boxElement);
76
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { pipeline } from '@huggingface/transformers';
2
+
3
+ // Global variables
4
+ let transcriber = null;
5
+ let audioData = null;
6
+ let mediaRecorder = null;
7
+ let audioChunks = [];
8
+ let isModelLoading = true;
9
+
10
+ // DOM Elements
11
+ const audioInput = document.getElementById('audioInput');
12
+ const recordBtn = document.getElementById('recordBtn');
13
+ const stopBtn = document.getElementById('stopBtn');
14
+ const useTimestamps = document.getElementById('useTimestamps');
15
+ const useWordTimestamps = document.getElementById('useWordTimestamps');
16
+ const transcribeBtn = document.getElementById('transcribeBtn');
17
+ const audioPlayer = document.getElementById('audioPlayer');
18
+ const audioPlayerContainer = document.querySelector('.audio-player');
19
+ const resultDiv = document.getElementById('result');
20
+ const loadingSpinner = document.getElementById('loading');
21
+
22
+ // Load the model on startup
23
+ async function loadModel() {
24
+ try {
25
+ loadingSpinner.hidden = false;
26
+ transcriber = await pipeline(
27
+ 'automatic-speech-recognition',
28
+ 'Xenova/whisper-tiny.en'
29
+ );
30
+ isModelLoading = false;
31
+ loadingSpinner.hidden = true;
32
+ transcribeBtn.disabled = false;
33
+ console.log('Model loaded successfully');
34
+ } catch (error) {
35
+ console.error('Failed to load model:', error);
36
+ resultDiv.innerHTML = `<p class="error">❌ Failed to load model. Check console for details.</p>`;
37
+ loadingSpinner.hidden = true;
38
+ }
39
+ }
40
 
41
+ // Handle file upload
42
+ audioInput.addEventListener('change', (event) => {
43
+ const file = event.target.files[0];
44
+ if (!file) return;
45
 
46
+ const objectUrl = URL.createObjectURL(file);
47
+ audioData = objectUrl;
48
+ setAudioSource(objectUrl);
49
  });
50
 
51
+ // Setup recording
52
+ recordBtn.addEventListener('click', async () => {
53
+ audioChunks = [];
54
+ try {
55
+ const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
56
+ mediaRecorder = new MediaRecorder(stream);
57
 
58
+ mediaRecorder.addEventListener('dataavailable', (event) => {
59
+ audioChunks.push(event.data);
60
+ });
61
 
62
+ mediaRecorder.addEventListener('stop', () => {
63
+ const audioBlob = new Blob(audioChunks, { type: 'audio/wav' });
64
+ const audioUrl = URL.createObjectURL(audioBlob);
65
+ audioData = audioUrl;
66
+ setAudioSource(audioUrl);
67
+ });
68
 
69
+ mediaRecorder.start();
70
+ recordBtn.disabled = true;
71
+ stopBtn.disabled = false;
72
+ } catch (err) {
73
+ resultDiv.innerHTML = `<p class="error">❌ Error accessing microphone: ${err.message}</p>`;
74
+ }
75
  });
76
 
77
+ stopBtn.addEventListener('click', () => {
78
+ mediaRecorder.stop();
79
+ recordBtn.disabled = false;
80
+ stopBtn.disabled = true;
81
 
82
+ // Stop all audio tracks
83
+ mediaRecorder.stream.getTracks().forEach(track => track.stop());
84
+ });
 
85
 
86
+ // Toggle timestamp options
87
+ useTimestamps.addEventListener('change', () => {
88
+ useWordTimestamps.disabled = !useTimestamps.checked;
89
+ });
 
 
 
 
90
 
91
+ // Set audio player source
92
+ function setAudioSource(src) {
93
+ audioPlayer.src = src;
94
+ audioPlayerContainer.hidden = false;
95
+ transcribeBtn.disabled = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
  }
97
+
98
+ // Transcribe audio
99
+ transcribeBtn.addEventListener('click', async () => {
100
+ if (!transcriber || isModelLoading || !audioData) return;
101
+
102
+ resultDiv.innerHTML = '';
103
+ loadingSpinner.hidden = false;
104
+
105
+ try {
106
+ const options = {};
107
+ if (useTimestamps.checked) {
108
+ options.return_timestamps = useWordTimestamps.checked ? 'word' : true;
109
+ }
110
+
111
+ const output = await transcriber(audioData, options);
112
+
113
+ // Display result
114
+ if (options.return_timestamps === 'word') {
115
+ resultDiv.innerHTML = `
116
+ <h2>Transcription (Word-level timestamps):</h2>
117
+ <p><strong>Text:</strong> ${output.text}</p>
118
+ <h3>Words:</h3>
119
+ <ul>
120
+ ${output.chunks
121
+ .map(
122
+ (chunk) =>
123
+ `<li><strong>[${chunk.timestamp[0].toFixed(
124
+ 2
125
+ )}s - ${chunk.timestamp[1].toFixed(
126
+ 2
127
+ )}s]</strong>: ${chunk.text.trim()}`
128
+ )
129
+ .join('')}
130
+ </ul>
131
+ `;
132
+ } else if (options.return_timestamps === true) {
133
+ resultDiv.innerHTML = `
134
+ <h2>Transcription (Segment-level timestamps):</h2>
135
+ <p><strong>Text:</strong> ${output.text}</p>
136
+ <h3>Segments:</h3>
137
+ <ul>
138
+ ${output.chunks
139
+ .map(
140
+ (chunk) =>
141
+ `<li><strong>[${chunk.timestamp[0]}s - ${
142
+ chunk.timestamp[1]
143
+ }s]</strong>: ${chunk.text.trim()}`
144
+ )
145
+ .join('')}
146
+ </ul>
147
+ `;
148
+ } else {
149
+ resultDiv.innerHTML = `
150
+ <h2>Transcription:</h2>
151
+ <p>${output.text}</p>
152
+ `;
153
+ }
154
+ } catch (error) {
155
+ resultDiv.innerHTML = `<p class="error">❌ Transcription failed: ${error.message}</p>`;
156
+ console.error(error);
157
+ } finally {
158
+ loadingSpinner.hidden = true;
159
+ }
160
+ });
161
+
162
+ // Preload example audio on page load
163
+ window.addEventListener('DOMContentLoaded', () => {
164
+ // Default example audio (optional, can be removed if only file/upload)
165
+ const defaultAudioUrl =
166
+ 'https://huggingface.co/datasets/Xenova/transformers.js-docs/resolve/main/jfk.wav';
167
+ audioData = defaultAudioUrl;
168
+ setAudioSource(defaultAudioUrl);
169
+ loadModel(); // Start model loading when app starts
170
+ });