Skip to content

Instantly share code, notes, and snippets.

@parente
Last active September 14, 2023 13:25
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save parente/41a13f4c8fa6165d345cc7703be291a3 to your computer and use it in GitHub Desktop.
Save parente/41a13f4c8fa6165d345cc7703be291a3 to your computer and use it in GitHub Desktop.
Jupyter Tidbit: Run and say "done!"

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

  • Binder (Jupyter Notebook)
  • Binder (JupyterLab)

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.

Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"def speak(text):\n",
" from IPython.display import Javascript as js, clear_output\n",
" # Escape single quotes\n",
" text = text.replace(\"'\", r\"\\'\")\n",
" display(js(f'''\n",
" if(window.speechSynthesis) {{\n",
" var synth = window.speechSynthesis;\n",
" synth.speak(new window.SpeechSynthesisUtterance('{text}'));\n",
" }}\n",
" '''))\n",
" # Clear the JS so that the notebook doesn't speak again when reopened/refreshed\n",
" clear_output(False)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"for i in range(int(1e8)): pass\n",
"speak(\"I'm done with the first loop.\")"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"for i in range(int(1e8)): pass"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"speak(\"Now I'm really done!\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment