python - reproduce - jupyter notebook tutorial pdf
Reproduce automáticamente el sonido en el portátil IPython (6)
A menudo corro celdas de larga duración en mi cuaderno de IPython. Me gustaría que la notebook emita un pitido o reproduzca un sonido automáticamente cuando la celda haya terminado de ejecutarse. ¿Hay alguna forma de hacer esto en el cuaderno iPython, o tal vez algún comando que pueda poner al final de una celda que reproduzca automáticamente un sonido?
Estoy usando Chrome si eso hace alguna diferencia.
TL; DR
En la parte superior de tu cuaderno.
from IPython.display import Audio
sound_file = ''./sound/beep.wav''
sound_file
debe apuntar a un archivo en su computadora, o accesible desde internet.
Luego, más tarde, al final de la celda de larga duración.
<code that takes a long time>
Audio(sound_file, autoplay=True)
Este método utiliza la etiqueta de Audio integrada en las versiones más nuevas de iPython / Jupyter.
Nota para versiones anteriores
Las versiones anteriores sin la etiqueta de audio pueden usar el siguiente método.
Coloca esto en una celda y ejecútalo antes de que quieras reproducir tu sonido:
from IPython.display import HTML
from base64 import b64encode
path_to_audio = "/path/to/snd/my-sound.mp3"
audio_type = "mp3"
sound = open(path_to_audio, "rb").read()
sound_encoded = b64encode(sound)
sound_tag = """
<audio id="beep" controls src="data:audio/{1};base64,{0}">
</audio>""".format(sound_encoded, audio_type)
play_beep = """
<script type="text/javascript">
var audio = document.getElementById("beep");
audio.play();
</script>
"""
HTML(sound_tag)
Al final de la celda que desea hacer un ruido al finalizar, coloque esto:
HTML(play_beep)
Cómo funciona:
Lee un archivo del sistema de archivos utilizando los métodos de read
y open
integrados de iPython. Luego codifica esto en base64. A continuación, crea una etiqueta de audio con el beep
ID e inyecta los datos base64 en ella. La pieza final de la configuración crea una pequeña etiqueta de secuencia de comandos que reproduce el sonido.
Este método debería funcionar en cualquier navegador que admita la etiqueta de audio HTML5.
Nota: si prefiere no mostrar los controles de audio en su computadora portátil, simplemente elimine el atributo de controls
de la variable llamada sound_tag
¿Qué hay de escribir el código una vez y hacer que funcione después de la ejecución de cada celda si se ejecuta más tiempo que el dado?
Simplemente crea y ejecuta una celda con JavaScript siguiente (ajuste de tiempo de espera y sonido)
%%javascript
(function(){
var startTime;
$([Jupyter.events]).on(''execute.CodeCell'', function(event, target)
{
startTime = performance.now();
});
$([Jupyter.events]).on(''finished_iopub.Kernel'', function(event, target)
{
var endTime = performance.now();
if(endTime - startTime > 5 * 1000)
{
var audio = new Audio(''http://www.soundjay.com/button/beep-07.wav'');
audio.play();
}
});
})()
Después de eso, debería escuchar el "pitido" después de cada ejecución de código que duró más de 5 segundos. Por ejemplo:
# cell 0:
from time import sleep
# cell 1:
sleep(6) # will ring
Si luego agregas otra celda
# cell 3:
sleep(3) # it won''t ring
A menos que ejecutes varias celdas a la vez:
# cell 4:
sleep(3)
# cell 5:
sleep(3) # will ring if queued for execution after cell 4
Probado con el cuaderno Jupyter 5.5.0.
El código puede requerir mejoras adicionales (no dudes en editarlo). Para que funcione en Google Colab, uno necesita cargar jQuery por su cuenta. Parece que no funciona con JupyterLab todavía.
Para apagar, utilice:
%%javascript
// a slightly better version would unbind only the handlers defined above
$([Jupyter.events]).unbind(''execute.CodeCell'')
$([Jupyter.events]).unbind(''finished_iopub.Kernel'')
También puede usar el sonido de pitido codificado en base64 (vea esta respuesta y esta idea ):
var audio = new Audio(''data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU='');
Aquí hay otra versión (Python-side principalmente) que funciona bien con JupyterLab:
from time import time
from IPython import get_ipython
from IPython.display import Audio, display
class Beeper:
def __init__(self, threshold, **audio_kwargs):
self.threshold = threshold
self.start_time = None # time in sec, or None
self.audio = audio_kwargs
def pre_execute(self):
if not self.start_time:
self.start_time = time()
def post_execute(self):
end_time = time()
if self.start_time and end_time - self.start_time > self.threshold:
audio = Audio(**self.audio, autoplay=True)
display(audio)
self.start_time = None
beeper = Beeper(5, url=''http://www.soundjay.com/button/beep-07.wav'')
ipython = get_ipython()
ipython.events.register(''pre_execute'', beeper.pre_execute)
ipython.events.register(''post_execute'', beeper.post_execute)
El pitido se emitirá automáticamente después de cada ejecución de código que duró más de 5 segundos, pero las ejecuciones consecutivas no se cuentan juntas.
Por ejemplo:
# cell 0:
from time import sleep
# cell 1:
sleep(6) # will ring
Si luego agregas otra celda
# cell 3:
sleep(3) # it won''t ring
Probado con JupyterLab 0.32.1 y Jupyter notebook 5.5.0.
Editar: para reducir el desorden de los reproductores de audio que se muestran, uso el siguiente fragmento de código (para Python anterior a 3.6 debe usar .format()
lugar de cadenas de caracteres):
from IPython.display import Audio, display
class InvisibleAudio(Audio):
def _repr_html_(self):
audio = super()._repr_html_()
audio = audio.replace(''<audio'', f''<audio onended="this.parentNode.removeChild(this)"'')
return f''<div style="display:none">{audio}</div>''
y luego use InvisibleAudio
lugar de Audio
en post_execute
.
Basado en la respuesta de @krassowski, aquí está mi solución a esto. La principal diferencia es que @ krassowski se ejecuta después de cada ejecución de celda "larga" (donde se define lo que significa "larga"); Prefiero decir explícitamente cuándo quiero que se reproduzca el sonido, así que lo he envuelto en una magia ( here copia y se copia a continuación).
"""
Adds a magic to IPython which will play a given sound when a cell finishes running.
Requires Python 3.6+.
Put this file in, e.g., ~/.ipython/profile_default/startup to load this magic on startup.
USAGE:
```
%%notify
run_long_function()
```
If you want, you can specify the URL of the audio file to play:
```
%%notify -u "{URL}"
run_long_function()
```
To always play your preferred audio file, just change the default below.
"""
from IPython.display import HTML, Audio, display
from IPython.core.magic_arguments import magic_arguments, argument, parse_argstring
from IPython.core.magic import cell_magic, Magics, magics_class
from IPython import get_ipython
class _InvisibleAudio(Audio):
"""
An invisible (`display: none`) `Audio` element which removes itself when finished playing.
Taken from https://.com/a/50648266.
"""
def _repr_html_(self) -> str:
audio = super()._repr_html_()
audio = audio.replace(
"<audio", ''<audio onended="this.parentNode.removeChild(this)"''
)
return f''<div style="display:none">{audio}</div>''
@magics_class
class NotificationMagics(Magics):
"""
Inspired by https://.com/a/50648266.
"""
@cell_magic
@magic_arguments()
@argument(
"-u",
"--url",
help="URL of sound to play",
default="https://freewavesamples.com/files/E-Mu-Proteus-FX-CosmoBel-C3.wav",
)
def notify(self, line: str, cell: str):
args = parse_argstring(self.notify, line)
ret = self.shell.ex(cell)
audio = _InvisibleAudio(url=args.url, autoplay=True)
display(audio)
return ret
get_ipython().register_magics(NotificationMagics)
Mi solución favorita (sin necesidad de un módulo externo):
import os
os.system("printf ''/a''") # or ''/7''
Funciona en OS X.
Sin embargo, la observación de DaveP sigue siendo válida: no es el navegador que reproduce el sonido, sino el servidor.
Podrías usar un módulo externo con python. Intente agregar esta llamada s.play()
desde Snack Sound Toolkit al final de la celda.
Snack Sound Toolkit puede reproducir archivos wav, au y mp3.
s = Sound()
s.read(''sound.wav'')
s.play()
esta pregunta es básicamente un duplicado de: Reproducir un sonido con Python .
El código-snipit anterior fue de @csexton en esa pregunta.