J'exécute souvent des cellules longues dans mon ordinateur portable Ipython. J'aimerais que le cahier soit automatiquement émettrice ou joue un son lorsque la cellule est terminée en cours d'exécution. Existe-t-il un moyen de le faire dans Ipython Notebook ou peut-être une commande que je peux mettre à la fin d'une cellule qui jouera automatiquement un son?
J'utilise Chrome si cela fait une différence.
En haut de votre cahier
from IPython.display import Audio
sound_file = './sound/beep.wav'
sound_file
devrait pointer vers un fichier sur votre ordinateur ou accessible depuis Internet.
Puis plus tard, à la fin de la cellule longue courante
<code that takes a long time>
Audio(sound_file, autoplay=True)
Cette méthode utilise la balise audio intégrée à des versions plus récentes d'Ipython/Jupyter.
Les versions plus anciennes sans la balise audio peuvent utiliser la méthode suivante.
Mettez ceci dans une cellule et passez-la avant de vouloir jouer votre son:
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)
À la fin de la cellule, vous voulez faire un bruit à la fin, mettez ceci:
HTML(play_beep)
Comment ça fonctionne:
Il lit un fichier à partir du système de fichiers à l'aide des méthodes intégrées _ et open
et read
. Ensuite, il code cela dans la base64. Il crée ensuite une balise audio avec l'identifiant beep
et injecte les données de base64. Le dernier élément de configuration crée une petite balise de script qui joue le son.
Cette méthode doit fonctionner dans n'importe quel navigateur prenant en charge la balise audio HTML5.
Remarque: Si vous préférez ne pas afficher les commandes audio de votre ordinateur portable, supprimez simplement l'attribut controls
de la variable nommée sound_tag
Ma solution préférée (pas besoin d'un module externe):
import os
os.system("printf '\a'") # or '\7'
Fonctionne sur OS X.
Cependant, la remarque de Davep s'applique toujours: ce n'est pas le navigateur qui joue le son, mais le serveur.
Voici une autre version (Python-côté surtout) qui fonctionne bien avec 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)
Le bip sera automatiquement émis après chaque exécution de code qui a pris plus de 5 secondes, mais les exécutions consécutives ne sont pas comptées ensemble.
Par exemple:
# cell 0:
from time import sleep
# cell 1:
sleep(6) # will ring
Si vous ajoutez ensuite une autre cellule
# cell 3:
sleep(3) # it won't ring
Testé avec JupyterLab 0.32.1 et Jupyter Notebook 5.5.0.
EDIT : Pour réduire le fouillis des lecteurs audio montrés, j'utilise à la suite d'un extrait (pour Python plus âgé que 3,6, vous devez utiliser .format()
[Fonction ()] _ au lieu de F-Strings):
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>'
puis utilisez InvisibleAudio
au lieu de Audio
in post_execute
.
Mention honorable.
Je suis venu chercher cette réponse particulière plusieurs fois, mais je ne pouvais pas le trouver ici.
winsound.Beep(freq, time_in_millisec)
J'utilise:
winsound.Beep(300, 200)
winsound.Beep(300, 200)
winsound.Beep(300, 700)
Basé sur la réponse de @ Krassowski, voici ma solution à cela. La principale différence est que @ Krassowski exécute après chaque chaque exécution de cellules "longue" (où vous définissez ce que vous définissez quel "long" signifie); Je préfère dire explicitement quand je veux que le son joué, alors j'ai enveloppé cela dans une magie (gist - ici et copiée ci-dessous).
"""
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://stackoverflow.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://stackoverflow.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)