我经常在我的IPython笔记本中运行长时间运行的单元格。我希望笔记本能够在单元格执行完毕后自动发出蜂鸣声或播放声音。有没有办法在iPython笔记本中做到这一点,或者我可以在一个自动播放声音的单元格末尾放置一些命令?
如果有任何不同,我正在使用Chrome。
答案 0 :(得分:31)
在笔记本的顶部
from IPython.display import Audio
sound_file = './sound/beep.wav'
sound_file
应指向您计算机上的文件,或者可从互联网访问。
然后,在长时间运行的单元格的末尾
<code that takes a long time>
Audio(sound_file, autoplay=True)
此方法使用较新版本的iPython / Jupyter中内置的Audio标记。
没有Audio标签的旧版本可以使用以下方法。
将它放在一个单元格中并在你想播放声音之前运行它:
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)
在单元格的末尾,您想要在完成时发出噪音:
HTML(play_beep)
工作原理:
它使用内置open
和read
方法的iPython从文件系统中读取文件。然后它将其编码为base64。然后,它会创建一个ID为beep
的音频标记,并将base64数据注入其中。最后一段设置会创建一个播放声音的小脚本标签。
此方法适用于任何支持HTML5音频标记的浏览器。
注意:如果您不想在笔记本中显示音频控件,只需从名为controls
sound_tag
属性即可
答案 1 :(得分:7)
我最喜欢的解决方案(不需要外部模块):
import os
os.system("printf '\a'") # or '\7'
适用于OS X.
然而DaveP的评论仍然适用:浏览器不是播放声音而是服务器。
答案 2 :(得分:6)
你可以使用python的外部模块。尝试在单元格末尾添加来自Snack Sound Toolkit的s.play()
调用。
The Snack Sound Toolkit可以播放wav,au和mp3文件。
s = Sound()
s.read('sound.wav')
s.play()
这个问题基本上是重复的: Play a Sound with Python
上面的代码片段来自@csexton。
答案 3 :(得分:5)
这是另一个版本(主要是Python端),与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)
每执行一次代码超过5秒后会自动发出蜂鸣声,但连续执行不会一起计算。
例如:
# cell 0:
from time import sleep
# cell 1:
sleep(6) # will ring
如果您再添加另一个单元格
# cell 3:
sleep(3) # it won't ring
使用JupyterLab 0.32.1和Jupyter笔记本5.5.0进行测试。
编辑以减少我在以下片段中使用的所显示音频播放器的混乱(对于3.6以上的Python,您需要使用.format()
而不是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>'
然后在InvisibleAudio
中使用Audio
代替post_execute
。
答案 4 :(得分:2)
如果执行的时间长于给定的时间,那么在执行每个单元格之后输入一次代码并使其工作怎么样?
使用以下JavaScript创建并执行一个单元格(调整超时和声音)
%%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();
}
});
})()
之后,您应该听到“哔”声。每次执行代码后花费的时间超过5秒。例如:
# cell 0:
from time import sleep
# cell 1:
sleep(6) # will ring
如果您再添加另一个单元格
# cell 3:
sleep(3) # it won't ring
除非你一次执行几个单元格:
# cell 4:
sleep(3)
# cell 5:
sleep(3) # will ring if queued for execution after cell 4
使用Jupyter笔记本5.5.0进行测试。
代码可能需要进一步改进(随意编辑)。要使其在Google Colab上运行,需要自己加载jQuery。 似乎还没有与JupyterLab一起使用。
要关闭,请使用:
%%javascript
// a slightly better version would unbind only the handlers defined above
$([Jupyter.events]).unbind('execute.CodeCell')
$([Jupyter.events]).unbind('finished_iopub.Kernel')
您还可以使用base64编码的哔声(请参阅this answer和this gist):
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=');
答案 5 :(得分:0)
基于@krassowski的回答,这是我对此的解决方案。主要的区别是@krassowski在每个每个“长”单元执行之后运行(您定义“长”的含义);我希望在播放声音时明确说出来,所以我将其包装成魔术(要点here,并在下面复制)。
"""
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)
答案 6 :(得分:0)
值得一提。
我多次寻找这个特定答案,但在这里找不到。
winsound.Beep(freq, time_in_millisec)
我使用:
winsound.Beep(300, 200)
winsound.Beep(300, 200)
winsound.Beep(300, 700)