Skip to content

Commit cfa6b02

Browse files
authored
Audio integration to front end (#360)
* Audio integration to front end * Add flask end point * Read and decode audio data * refract a typo * fix clang format
1 parent 3ee6207 commit cfa6b02

File tree

4 files changed

+121
-4
lines changed

4 files changed

+121
-4
lines changed

frontend/src/audio/ui/AudioPanel.vue

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
v-model="currentIndex"
1515
></v-slider>
1616

17-
<audio controls>
18-
<source src="horse.ogg" type="audio/ogg">
17+
<audio controls :src="audioData.audioSrc">
1918
Your browser does not support the audio element.
2019
</audio>
2120
</v-card>
@@ -82,7 +81,7 @@ export default {
8281
if (this.data && this.data[index]) {
8382
let currentAudioInfo = this.data ? this.data[index] : {};
8483
let {query, step, wall_time} = currentAudioInfo;
85-
let url = '/data/plugin/images/individualAudio?ts=' + wall_time;
84+
let url = '/data/plugin/audio/individualAudio?ts=' + wall_time;
8685
let audioSrc = [url, query].join('&');
8786
this.audioData = {
8887
audioSrc,

frontend/tool/webpack.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ const config = {
9292
use: getLoaders(isDev, 'stylus')
9393
},
9494
{
95-
test: /\.(gif|png|jpe?g|svg)$/i,
95+
test: /\.(gif|png|jpe?g|svg|wav)$/i,
9696
loader: 'file-loader',
9797
options: {
9898
name: 'assets/[name].[hash].[ext]'

visualdl/server/lib.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import numpy as np
77
from PIL import Image
88
from .log import logger
9+
import wave
910

1011
try:
1112
from urllib.parse import urlencode
@@ -155,6 +156,86 @@ def get_invididual_image(storage, mode, tag, step_index, max_size=80):
155156
return tempfile
156157

157158

159+
def get_audio_tags(storage):
160+
result = {}
161+
162+
for mode in storage.modes():
163+
with storage.mode(mode) as reader:
164+
tags = reader.tags('audio')
165+
if tags:
166+
result[mode] = {}
167+
for tag in tags:
168+
audio = reader.audio(tag)
169+
for i in range(max(1, audio.num_samples())):
170+
caption = tag if audio.num_samples(
171+
) <= 1 else '%s/%d' % (tag, i)
172+
result[mode][caption] = {
173+
'displayName': caption,
174+
'description': "",
175+
'samples': 1,
176+
}
177+
178+
return result
179+
180+
181+
def get_audio_tag_steps(storage, mode, tag):
182+
# remove suffix '/x'
183+
res = re.search(r".*/([0-9]+$)", tag)
184+
sample_index = 0
185+
origin_tag = tag
186+
if res:
187+
tag = tag[:tag.rfind('/')]
188+
sample_index = int(res.groups()[0])
189+
190+
with storage.mode(mode) as reader:
191+
audio = reader.audio(tag)
192+
res = []
193+
194+
for step_index in range(audio.num_records()):
195+
record = audio.record(step_index, sample_index)
196+
197+
query = urlencode({
198+
'sample': 0,
199+
'index': step_index,
200+
'tag': origin_tag,
201+
'run': mode,
202+
})
203+
res.append({
204+
'step': record.step_id(),
205+
'wall_time': audio.timestamp(step_index),
206+
'query': query,
207+
})
208+
209+
return res
210+
211+
212+
def get_individual_audio(storage, mode, tag, step_index, max_size=80):
213+
214+
with storage.mode(mode) as reader:
215+
res = re.search(r".*/([0-9]+$)", tag)
216+
# remove suffix '/x'
217+
offset = 0
218+
if res:
219+
offset = int(res.groups()[0])
220+
tag = tag[:tag.rfind('/')]
221+
222+
audio = reader.audio(tag)
223+
record = audio.record(step_index, offset)
224+
225+
data = np.array(record.data(), dtype='uint8')
226+
227+
tempfile = NamedTemporaryFile(mode='w+b', suffix='.wav')
228+
229+
wavfile = wave.open(tempfile, 'wb')
230+
wavfile.setnchannels(2)
231+
wavfile.setsampwidth(2)
232+
wavfile.writeframes(data.tostring())
233+
234+
tempfile.seek(0, 0)
235+
236+
return tempfile
237+
238+
158239
def get_histogram_tags(storage):
159240
return get_tags(storage, 'histogram')
160241

visualdl/server/visualDL

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,14 @@ def image_tags():
163163
return Response(json.dumps(result), mimetype='application/json')
164164

165165

166+
@app.route("/data/plugin/audio/tags")
167+
def audio_tags():
168+
data = cache_get("/data/plugin/audio/tags", try_call, lib.get_audio_tags,
169+
log_reader)
170+
result = gen_result(0, "", data)
171+
return Response(json.dumps(result), mimetype='application/json')
172+
173+
166174
@app.route("/data/plugin/histograms/tags")
167175
def histogram_tags():
168176
data = cache_get("/data/plugin/histograms/tags", try_call,
@@ -245,6 +253,35 @@ def embeddings():
245253
result = gen_result(0, "", data)
246254
return Response(json.dumps(result), mimetype='application/json')
247255

256+
@app.route('/data/plugin/audio/audio')
257+
def audio():
258+
mode = request.args.get('run')
259+
tag = request.args.get('tag')
260+
key = os.path.join('/data/plugin/audio/audio', mode, tag)
261+
262+
data = cache_get(key, try_call, lib.get_audio_tag_steps, log_reader, mode,
263+
tag)
264+
result = gen_result(0, "", data)
265+
266+
return Response(json.dumps(result), mimetype='application/json')
267+
268+
269+
@app.route('/data/plugin/audio/individualAudio')
270+
def individual_audio():
271+
mode = request.args.get('run')
272+
print mode
273+
tag = request.args.get('tag') # include a index
274+
step_index = int(request.args.get('index')) # index of step
275+
276+
key = os.path.join('/data/plugin/audio/individualAudio', mode, tag,
277+
str(step_index))
278+
data = cache_get(key, try_call, lib.get_individual_audio, log_reader, mode,
279+
tag, step_index)
280+
response = send_file(
281+
data, as_attachment=True, attachment_filename='audio.wav')
282+
return response
283+
284+
248285
@app.route('/data/plugin/graphs/graph')
249286
def graph():
250287
# TODO(ChunweiYan) need to add a config for whether have graph.

0 commit comments

Comments
 (0)