rmayormartins commited on
Commit
a61fcf3
1 Parent(s): e268a60
Files changed (4) hide show
  1. .gitattributes +0 -35
  2. README.md +15 -7
  3. app.py +53 -274
  4. requirements.txt +3 -2
.gitattributes DELETED
@@ -1,35 +0,0 @@
1
- *.7z filter=lfs diff=lfs merge=lfs -text
2
- *.arrow filter=lfs diff=lfs merge=lfs -text
3
- *.bin filter=lfs diff=lfs merge=lfs -text
4
- *.bz2 filter=lfs diff=lfs merge=lfs -text
5
- *.ckpt filter=lfs diff=lfs merge=lfs -text
6
- *.ftz filter=lfs diff=lfs merge=lfs -text
7
- *.gz filter=lfs diff=lfs merge=lfs -text
8
- *.h5 filter=lfs diff=lfs merge=lfs -text
9
- *.joblib filter=lfs diff=lfs merge=lfs -text
10
- *.lfs.* filter=lfs diff=lfs merge=lfs -text
11
- *.mlmodel filter=lfs diff=lfs merge=lfs -text
12
- *.model filter=lfs diff=lfs merge=lfs -text
13
- *.msgpack filter=lfs diff=lfs merge=lfs -text
14
- *.npy filter=lfs diff=lfs merge=lfs -text
15
- *.npz filter=lfs diff=lfs merge=lfs -text
16
- *.onnx filter=lfs diff=lfs merge=lfs -text
17
- *.ot filter=lfs diff=lfs merge=lfs -text
18
- *.parquet filter=lfs diff=lfs merge=lfs -text
19
- *.pb filter=lfs diff=lfs merge=lfs -text
20
- *.pickle filter=lfs diff=lfs merge=lfs -text
21
- *.pkl filter=lfs diff=lfs merge=lfs -text
22
- *.pt filter=lfs diff=lfs merge=lfs -text
23
- *.pth filter=lfs diff=lfs merge=lfs -text
24
- *.rar filter=lfs diff=lfs merge=lfs -text
25
- *.safetensors filter=lfs diff=lfs merge=lfs -text
26
- saved_model/**/* filter=lfs diff=lfs merge=lfs -text
27
- *.tar.* filter=lfs diff=lfs merge=lfs -text
28
- *.tar filter=lfs diff=lfs merge=lfs -text
29
- *.tflite filter=lfs diff=lfs merge=lfs -text
30
- *.tgz filter=lfs diff=lfs merge=lfs -text
31
- *.wasm filter=lfs diff=lfs merge=lfs -text
32
- *.xz filter=lfs diff=lfs merge=lfs -text
33
- *.zip filter=lfs diff=lfs merge=lfs -text
34
- *.zst filter=lfs diff=lfs merge=lfs -text
35
- *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
README.md CHANGED
@@ -1,6 +1,6 @@
1
  ---
2
- title: AIA-Scope
3
- emoji: 🔍
4
  colorFrom: gray
5
  colorTo: indigo
6
  sdk: gradio
@@ -10,10 +10,18 @@ pinned: false
10
  license: ecl-2.0
11
  ---
12
 
13
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
14
 
15
  Desenvolvido por Ramon Mayor Martins (2023)
16
- mail rmayormartins@gmail.com
17
- hp https://rmayormartins.github.io/
18
- twitter @rmayormartins
19
- github https://github.com/rmayormartins
 
 
 
1
  ---
2
+ title: Speech-Scope
3
+ emoji: 🎤
4
  colorFrom: gray
5
  colorTo: indigo
6
  sdk: gradio
 
10
  license: ecl-2.0
11
  ---
12
 
13
+ ## Speech-Scope
14
+
15
+ Análise de métricas de áudio.
16
+
17
+ Confira a referência de configuração em [Hugging Face Spaces Config Reference](https://huggingface.co/docs/hub/spaces-config-reference).
18
+
19
+ ## Desenvolvedor
20
 
21
  Desenvolvido por Ramon Mayor Martins (2023)
22
+
23
+ - E-mail: [rmayormartins@gmail.com](mailto:rmayormartins@gmail.com)
24
+ - Homepage: [https://rmayormartins.github.io/](https://rmayormartins.github.io/)
25
+ - Twitter: [@rmayormartins](https://twitter.com/rmayormartins)
26
+ - GitHub: [https://github.com/rmayormartins](https://github.com/rmayormartins)
27
+
app.py CHANGED
@@ -1,304 +1,83 @@
1
  import gradio as gr
2
- from zipfile import ZipFile, BadZipFile
 
 
3
  import tempfile
4
- import os
5
- import re
6
- import pandas as pd
7
- import collections
8
- import json
9
- import glob
10
- from io import BytesIO
11
 
12
 
13
- ai_patterns = [
14
- "PIC*", "PersonalImageClassifier*", "Look*", "LookExtension*", "ChatBot", "ImageBot", "TMIC","TeachableMachine*",
15
- "TeachableMachineImageClassifier*", "SpeechRecognizer*", "FaceExtension*","Pose*","Posenet","PosenetExtension", "Eliza*", "Alexa*"
16
- ]
17
-
18
-
19
- drawing_and_animation_patterns = ["Ball", "Canvas", "ImageSprite"]
20
- maps_patterns = ["Map", "Marker", "Circle", "FeatureCollection", "LineString", "Navigation","Polygon", "Retangle" ]
21
- sensors_patterns = ["AccelerometerSensor", "BarcodeScanner", "Barometer", "Clock", "GyroscopeSensor", "Hygrometer", "LightSensor", "LocationSensor", "MagneticFieldSensor", "NearField","OrientationSensor", "ProximitySensor","Thermometer", "Pedometer"]
22
- social_patterns = ["ContactPicker", "EmailPicker", "PhoneCall", "PhoneNumberPicker", "Texting", "Twitter"]
23
- storage_patterns = ["File", "CloudDB", "DataFile", "Spreadsheet", "FusiontablesControl", "TinyDB", "TinyWebDB"]
24
- connectivity_patterns = ["BluetoothClient", "ActivityStarter", "Serial", "BluetoothServer", "Web"]
25
-
26
-
27
- def extract_components_using_regex(scm_content):
28
- pattern = r'"\$Type":"(.*?)"'
29
- components = re.findall(pattern, scm_content)
30
- if 'roboflow' in scm_content.lower():
31
- components.append("Using Roboflow")
32
- return components
33
-
34
-
35
- def extract_category_components(components, patterns):
36
- category_components = []
37
- for component in components:
38
- for pattern in patterns:
39
- if component.startswith(pattern):
40
- category_components.append(component)
41
- return category_components
42
-
43
-
44
- def extract_extensions_from_aia(file_path: str):
45
- extensions = []
46
- with ZipFile(file_path, 'r') as zip_ref:
47
- for file_path in zip_ref.namelist():
48
- if file_path.endswith('components.json') and 'assets/external_comps/' in file_path:
49
- with zip_ref.open(file_path) as file:
50
- components_json_content = file.read().decode('utf-8', errors='ignore')
51
- components_data = json.loads(components_json_content)
52
- for component in components_data:
53
- extension_type = component.get("type", "")
54
- if extension_type:
55
- extensions.append(extension_type)
56
- return extensions
57
-
58
- def count_events_in_bky_file(bky_content):
59
-
60
- return bky_content.count('<block type="component_event"')
61
-
62
- def extract_app_name_from_scm_files(temp_dir):
63
- scm_files = glob.glob(f"{temp_dir}/src/appinventor/*/*/*.scm")
64
- for scm_file in scm_files:
65
- with open(scm_file, 'r', encoding='utf-8', errors='ignore') as file:
66
- content = file.read()
67
-
68
-
69
- regex_patterns = [
70
- r'"AppName"\s*:\s*"([^"]+)"',
71
- r'"AppName"\s*:\s*\'([^\']+)\''
72
- ]
73
-
74
- for pattern in regex_patterns:
75
- app_name_match = re.search(pattern, content)
76
- if app_name_match:
77
- return app_name_match.group(1)
78
-
79
-
80
- print(f"Aviso: Nome do aplicativo não encontrado no diretório {temp_dir}")
81
- return "N/A"
82
-
83
- def extract_project_info_from_properties(file_path):
84
-
85
- timestamp = "N/A"
86
- app_name = "N/A"
87
- app_version = "N/A"
88
- authURL = "ai2.appinventor.mit.edu"
89
-
90
-
91
- with tempfile.TemporaryDirectory() as temp_dir:
92
- with ZipFile(file_path, 'r') as zip_ref:
93
- zip_ref.extractall(temp_dir)
94
-
95
- project_properties_file_path = 'youngandroidproject/project.properties'
96
-
97
-
98
- if project_properties_file_path in zip_ref.namelist():
99
- with zip_ref.open(project_properties_file_path) as file:
100
- project_properties_lines = file.read().decode('utf-8').splitlines()
101
-
102
-
103
- timestamp = project_properties_lines[1] if len(project_properties_lines) > 1 else "N/A"
104
-
105
-
106
- for line in project_properties_lines:
107
- app_name_match = re.match(r'aname=(.*)', line)
108
- if app_name_match:
109
- app_name = app_name_match.group(1)
110
-
111
- app_version_match = re.match(r'versionname=(.*)', line)
112
- if app_version_match:
113
- app_version = app_version_match.group(1)
114
-
115
-
116
- if app_name == "N/A":
117
- print("O campo App Name não foi encontrado em project.properties. Tentando encontrar em arquivos .scm...")
118
- app_name = extract_app_name_from_scm_files(temp_dir)
119
- print(f"Nome do App encontrado nos arquivos .scm: {app_name}")
120
-
121
- # ...
122
-
123
 
124
  return {
125
- 'timestamp': timestamp,
126
- 'app_name': app_name,
127
- 'app_version': app_version,
128
- 'authURL': authURL
 
129
  }
130
 
131
 
 
 
132
 
 
 
 
133
 
 
 
134
 
135
- def extract_ai_components(components):
136
- ai_components = []
137
- for component in components:
138
- for pattern in ai_patterns:
139
- if '*' in pattern and component.startswith(pattern[:-1]):
140
- ai_components.append(component)
141
- elif component == pattern:
142
- ai_components.append(component)
143
- if "roboflow" in ' '.join(components).lower():
144
- ai_components.append("Using Roboflow")
145
- return ai_components
146
-
147
- def extract_media_files(file_path: str):
148
- media_files = []
149
- with ZipFile(file_path, 'r') as zip_ref:
150
- for file_path in zip_ref.namelist():
151
- if 'assets/' in file_path and not file_path.endswith('/'):
152
- media_files.append(os.path.basename(file_path))
153
- return media_files
154
-
155
- def list_components_in_aia_file(file_path):
156
-
157
- results_df = pd.DataFrame(columns=[
158
- 'aia_file', 'project_info', 'components', 'IA components', 'screens', 'operators',
159
- 'variables', 'events', 'extensions', 'Media',
160
- 'Drawing and Animation', 'Maps', 'Sensors', 'Social', 'Storage', 'Connectivity'])
161
 
162
-
163
- pd.set_option('display.max_colwidth', None)
164
- file_name = os.path.basename(file_path)
165
-
166
 
167
- components_list = []
168
- number_of_screens = 0
169
- operators_count = 0
170
- variables_count = 0
171
- events_count = 0
172
-
173
- media_files = extract_media_files(file_path)
174
- media_summary = ', '.join(media_files)
175
-
176
- project_info = extract_project_info_from_properties(file_path)
177
- project_info_str = f"Timestamp: {project_info['timestamp']}, App Name: {project_info['app_name']}, Version: {project_info['app_version']}, AuthURL: {project_info['authURL']}"
178
 
 
 
 
 
 
 
179
 
180
- with tempfile.TemporaryDirectory() as temp_dir:
181
- with ZipFile(file_path, 'r') as zip_ref:
182
- zip_ref.extractall(temp_dir)
183
- scm_files = glob.glob(temp_dir + '/src/appinventor/*/*/*.scm')
184
- bky_files = glob.glob(temp_dir + '/src/appinventor/*/*/*.bky')
185
 
186
- number_of_screens = len(scm_files)
187
- for scm_file in scm_files:
188
- with open(scm_file, 'r', encoding='utf-8', errors='ignore') as file:
189
- content = file.read()
190
- components = extract_components_using_regex(content)
191
- components_list.extend(components)
192
- operators_count += len(re.findall(r'[+\-*/<>!=&|]', content))
193
- variables_count += len(re.findall(r'"\$Name":"(.*?)"', content))
194
 
195
-
196
- drawing_and_animation_summary = ', '.join(extract_category_components(components_list, drawing_and_animation_patterns))
197
- maps_summary = ', '.join(extract_category_components(components_list, maps_patterns))
198
- sensors_summary = ', '.join(extract_category_components(components_list, sensors_patterns))
199
- social_summary = ', '.join(extract_category_components(components_list, social_patterns))
200
- storage_summary = ', '.join(extract_category_components(components_list, storage_patterns))
201
- connectivity_summary = ', '.join(extract_category_components(components_list, connectivity_patterns))
202
 
 
 
 
203
 
204
-
205
-
206
- extensions_list = []
207
- extensions_list = extract_extensions_from_aia(file_path)
208
 
209
- for bky_file in bky_files:
210
- with open(bky_file, 'r', encoding='utf-8', errors='ignore') as file:
211
- bky_content = file.read()
212
- events_count += count_events_in_bky_file(bky_content)
213
-
214
 
 
 
215
 
216
-
217
- extensions_summary = ', '.join(list(set(extensions_list)))
218
 
219
- components_count = collections.Counter(components_list)
220
- components_summary = [f'{comp} ({count} x)' if count > 1 else comp for comp, count in components_count.items()]
221
- ai_components_summary = extract_ai_components(components_list)
222
- new_row = pd.DataFrame([{
223
- 'aia_file': file_name,
224
- 'project_info': project_info_str,
225
- 'components': ', '.join(components_summary),
226
- 'IA components': ', '.join(ai_components_summary),
227
- 'screens': number_of_screens,
228
- 'operators': operators_count,
229
- 'variables': variables_count,
230
- 'events': events_count,
231
- 'extensions': extensions_summary,
232
- 'Media': media_summary,
233
- 'Drawing and Animation': drawing_and_animation_summary,
234
- 'Maps': maps_summary,
235
- 'Sensors': sensors_summary,
236
- 'Social': social_summary,
237
- 'Storage': storage_summary,
238
- 'Connectivity': connectivity_summary
239
- }])
240
 
241
-
242
- results_df = pd.concat([results_df, new_row], ignore_index=True)
243
- return results_df
244
- #
245
-
246
-
247
- output_style = """
248
- <style>
249
- .output-container {
250
- max-height: 500px; /* Ajuste a altura máxima conforme necessário */
251
- overflow: auto; /* Isso permite a rolagem vertical e horizontal se necessário */
252
- display: block; /* Isso garante que o container seja renderizado abaixo do botão submit */
253
- }
254
- .output-container table {
255
- width: 100%; /* Isso faz com que a tabela utilize toda a largura do container */
256
- border-collapse: collapse;
257
- }
258
- .output-container th, .output-container td {
259
- border: 1px solid #ddd; /* Isso adiciona bordas às células para melhor visualização */
260
- text-align: left;
261
- padding: 8px;
262
- }
263
- </style>
264
- """
265
 
266
 
267
- def analyze_aia(uploaded_file):
268
- try:
269
-
270
- file_path = uploaded_file.name if hasattr(uploaded_file, 'name') else None
271
-
272
- if file_path and os.path.exists(file_path):
273
- with ZipFile(file_path, 'r') as zip_ref:
274
- with tempfile.TemporaryDirectory() as temp_dir:
275
- zip_ref.extractall(temp_dir)
276
- results_df = list_components_in_aia_file(file_path)
277
-
278
- html_result = results_df.to_html(escape=False, classes="output-html")
279
- return output_style + f'<div class="output-container">{html_result}</div>'
280
-
281
-
282
- else:
283
- return output_style + "Não foi possível localizar o arquivo .aia."
284
-
285
- except BadZipFile:
286
- return output_style + "Falha ao abrir o arquivo .aia como um arquivo zip. Ele pode estar corrompido ou não é um arquivo .aia válido."
287
-
288
- except Exception as e:
289
- return output_style + f"Erro ao processar o arquivo: {str(e)}"
290
-
291
  iface = gr.Interface(
292
- fn=analyze_aia,
293
- inputs=gr.File(),
294
- outputs=gr.HTML(),
295
- title="AIA-Scope",
296
- description="Upload an .aia file to analyze its components.",
297
- live=False
298
  )
299
 
300
- if __name__ == "__main__":
301
- iface.launch(debug=True)
302
-
303
-
304
-
 
1
  import gradio as gr
2
+ import librosa
3
+ import numpy as np
4
+ import matplotlib.pyplot as plt
5
  import tempfile
6
+ import librosa.display
 
 
 
 
 
 
7
 
8
 
9
+ def calculate_basic_metrics(y, sr):
10
+ pitches, magnitudes = librosa.piptrack(y=y, sr=sr)
11
+ average_pitch = np.mean(pitches[pitches > 0])
12
+ mfccs = librosa.feature.mfcc(y=y, sr=sr)
13
+ energy = np.sum(y ** 2)
14
+ zero_crossing_rate = np.mean(librosa.feature.zero_crossing_rate(y))
15
+ spectral_centroid = np.mean(librosa.feature.spectral_centroid(y=y, sr=sr))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
  return {
18
+ 'Average Pitch': average_pitch,
19
+ 'Number of MFCCs': mfccs.shape[1],
20
+ 'Energy': energy,
21
+ 'Zero Crossing Rate': zero_crossing_rate,
22
+ 'Spectral Centroid': spectral_centroid
23
  }
24
 
25
 
26
+ def calculate_advanced_metrics(y, sr):
27
+ metrics = {}
28
 
29
+ f0, _, _ = librosa.pyin(y, fmin=50, fmax=4000)
30
+ if f0 is not None:
31
+ metrics['Average F0 (YIN)'] = np.nanmean(f0)
32
 
33
+ chroma = librosa.feature.chroma_stft(y=y, sr=sr)
34
+ metrics['Average Chroma'] = np.mean(chroma)
35
 
36
+ spectral_contrast = librosa.feature.spectral_contrast(y=y, sr=sr)
37
+ metrics['Average Spectral Contrast'] = np.mean(spectral_contrast)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
+ return metrics
 
 
 
40
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
+ def generate_spectrogram(y, sr):
43
+ plt.figure(figsize=(10, 4))
44
+ librosa.display.specshow(librosa.amplitude_to_db(np.abs(librosa.stft(y)), ref=np.max), sr=sr, x_axis='time', y_axis='log')
45
+ plt.colorbar(format='%+2.0f dB')
46
+ plt.title('Spectrogram')
47
+ plt.tight_layout()
48
 
 
 
 
 
 
49
 
50
+ with tempfile.NamedTemporaryFile(delete=False, suffix='.png', mode='w+b') as f:
51
+ plt.savefig(f.name, format='png')
52
+ plt.close()
53
+ return f.name
 
 
 
 
54
 
 
 
 
 
 
 
 
55
 
56
+ def process_audio(file):
57
+ if file is None:
58
+ return {}, "placeholder.png"
59
 
60
+ sr, y = file
 
 
 
61
 
62
+ if y.dtype != np.float32:
63
+ y = y.astype(np.float32) / np.iinfo(y.dtype).max
 
 
 
64
 
65
+ basic_metrics = calculate_basic_metrics(y, sr)
66
+ advanced_metrics = calculate_advanced_metrics(y, sr)
67
 
68
+ metrics = {**basic_metrics, **advanced_metrics}
 
69
 
70
+ image_path = generate_spectrogram(y, sr)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
71
 
72
+ return metrics, image_path
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
73
 
74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
75
  iface = gr.Interface(
76
+ fn=process_audio,
77
+ inputs=gr.Audio(label="Upload Audio"),
78
+ outputs=["json", "image"],
79
+ title="Speech-Scope",
80
+ description="Speech and audio Metrics Analysis"
 
81
  )
82
 
83
+ iface.launch(debug=True)
 
 
 
 
requirements.txt CHANGED
@@ -1,3 +1,4 @@
1
  gradio
2
- pandas
3
- glob2 # se você estiver usando glob2
 
 
1
  gradio
2
+ librosa
3
+ numpy
4
+ matplotlib