Last active
June 1, 2020 15:59
-
-
Save scottire/7fe5e25f1654fb901fb7f024533d5508 to your computer and use it in GitHub Desktop.
Interactive Audio Plot using ipywidgets within Jupyter Notebook (not yet working with Jupyter Lab, see comments)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from ipywidgets import IntSlider, ToggleButton, Text | |
from IPython.display import display, Audio, Javascript | |
from scipy.io import wavfile | |
import numpy as np | |
from matplotlib import pyplot as plt | |
import ipywidgets | |
t = Text(value='0', | |
description='Elapsed Time:', | |
style = {'description_width': 'initial'}, | |
) | |
fs, data = wavfile.read('./4k6c030p.wav') | |
a = Audio(data, | |
rate=fs, | |
autoplay=True, | |
element_id = 'audio_element', | |
) | |
fig, ax = plt.subplots(constrained_layout=True, figsize=(6, 4)) | |
line = ax.axvline(0) | |
time = np.linspace(0, len(data) / fs, num=len(data)) | |
ax.plot(time, data) | |
s = IntSlider(max=len(data) / fs, | |
description='Elapsed Time:', | |
style = {'description_width': 'initial'}, | |
) | |
def update(change): | |
"""redraw line (update plot)""" | |
line.set_xdata(np.array([change.new, change.new])) | |
fig.canvas.draw() | |
s.observe(update, 'value') | |
display(a,t,s) | |
jscript = f''' | |
var time_check; | |
var stop_checking = false; | |
function updateTime() {{ | |
var audio_element = document.getElementById("audio_element"); | |
var manager = window.IPython.WidgetManager._managers[0]; | |
if (audio_element == null) {{ | |
clearTimeout(time_check); | |
return; | |
}} | |
// Change value only once after pausing | |
if ((!audio_element.paused) || (!stop_checking)) {{ | |
if (audio_element.paused) stop_checking = true; | |
else stop_checking = false; | |
var model_prom = manager.get_model('{t.model_id}'); | |
model_prom.then(function(model) {{ | |
model.set('value', "" + audio_element.currentTime); | |
model.save_changes(); | |
}}); | |
var model_prom = manager.get_model('{s.model_id}'); | |
model_prom.then(function(model) {{ | |
model.set('value', Math.floor(audio_element.currentTime)); | |
model.save_changes(); | |
}}); | |
}}//endif | |
time_check = setTimeout(updateTime, 1000); | |
}} | |
updateTime(); | |
''' | |
Javascript(jscript) |
@delip I was able to find another method to get the playhead alongside playable audio within Jupyter Lab.
See here: https://gist.github.com/scottire/654019e88e6225c15a68006ab4a3ba98
This already visualises the audio, but the on_time_update
callback can be used to update any visualisations playhead using matplotlib like in the above code with line.set_xdata(np.array([time, time])
.
You'll need to follow the instructions to install jp_proxy_widget with JupyterLab.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
That's good that you now have ipywidgets usable in JupyterLab. Unfortunately, it seems it's not possible to get the WidgetManager from within JupyterLab. I did a bit of reading around and it seems there's no equivalent of
window.IPython
within JupyterLab, which seems to have been done for security reasons so arbitrary javascript can't be run. It would be great if it was possible to get thecurrentTime
from the audio element by some other means but I'm not sure about how/if that can be done from within JupyterLab, other than building a new jupyterlab extension.