Jupyter Tidbit: Run and say "done!"
August 27, 2018
This post originates from a gist that supports comments, forks, and execution in binder.
Summary
Many modern web browsers provide a speech synthesis API for JavaScript. You can write and invoke a function to have your notebook speak when it finishes executing certain cells, whether you're running it in JupyterLab (>=0.34) or classic Jupyter Notebook.
def speak(text):
from IPython.display import Javascript as js, clear_output
# Escape single quotes
text = text.replace("'", r"\'")
display(js('''
if(window.speechSynthesis) {{
var synth = window.speechSynthesis;
synth.speak(new window.SpeechSynthesisUtterance('{text}'));
}}
'''.format(text=text)))
# Clear the JS so that the notebook doesn't speak again when reopened/refreshed
clear_output(False)
Example
When I open the demo.ipynb
notebook below and Run All
cells, I hear the notebook speak aloud when it finishes
executing the first and second loops.
Why is this useful?
You can add notifications at select locations in your notebook to report execution progress even while you're not looking at the notebook
Alternatives
You can also use the %%javascript
cell magic to achieve the same net effect in Jupyter Notebook.
%%javascript
if(window.speechSynthesis) {{
var synth = window.speechSynthesis;
synth.speak(new window.SpeechSynthesisUtterance('All done!'));
setTimeout(this.clear_output.bind(this), 0);
}}
However, the same code doesn't properly clear the JS from the notebook document in JupyterLab, and the notebook speaks immediately when opened unless you clear the cell output manually.
The jupyter_contrib_nbextensions project includes a notify extension for Jupyter Notebook which can show desktop popups and play a sounds when unattended notebooks become idle.
demo.ipynb
def speak(text):
from IPython.display import Javascript as js, clear_output
# Escape single quotes
text = text.replace("'", r"\'")
display(js(f'''
if(window.speechSynthesis) {{
var synth = window.speechSynthesis;
synth.speak(new window.SpeechSynthesisUtterance('{text}'));
}}
'''))
# Clear the JS so that the notebook doesn't speak again when reopened/refreshed
clear_output(False)
for i in range(int(1e8)): pass
speak("I'm done with the first loop.")
for i in range(int(1e8)): pass
speak("Now I'm really done!")