Playing audio in a remote Jupyter Notebook (like Google Colab) - audio

I'd like to play audio on a remote Jupyter Notebook (like in Google Colab or a Binder-hosted Jupyterlab) but I can't figure out how. What I would like to get working is something like this:
from pydub import AudioSegment
from pydub.playback import play
start = 1000
end = 3000
audio = AudioSegment.from_file("someaudio.flac")
audio_piece = audio[start:end]
play(audio_piece)
With a playback package like simpleaudio installed, everything works fine on my local machine. But when I try to run this code in Google Colab, for example, I get this error message:
SimpleaudioError: Error opening PCM device. -- CODE: -2 -- MSG: No such file or directory
I tried several other audio packages but I always ran into some trouble. The only thing that works is IPython.display -> Audio. But I can't use this for my project because I don't want a player displayed (and because it doesn't seem to have the option to play segments of an audio file).
Does anyone know a solution for this?

For MyBinder-served sessions, you have to connect the audio playing ability to IPython abilities imported into the notebook or link the playing of audio to ipywidgets running in the notebook.
Example of playing a wav file in a MyBinder-served notebook
Go to here and press 'launch Binder'.
When the session spins up, paste this into a cell and run that cell:
# PLAY A WAV. BASED ON
# https://ipython.org/ipython-doc/stable/api/generated/IPython.display.html#IPython.display.Audio
from IPython.display import Audio, display
Audio("http://www.nch.com.au/acm/8k16bitpcm.wav") # From URL
# see https://ipython.org/ipython-doc/stable/api/generated/IPython.display.html#IPython.display.Audio
# for other options such as a file you upload to the remote MyBinder-served session
That will show a controller you can click 'play' to play the file found at the URL as the wav file.
See the source linked in the comments for more information, such as how you could play your own wav file.
To demo this in JupyterLab:
If you are starting fresh, click here to launch directly into JupyterLab. When that sessions spins up, open a new notebook and paste in the code above.
If you are already in a session provided by MyBinder in the classic notebook, click the 'Jupyter' logo in the upper left side above the notebook. The page will refresh and the JupyterLab interface will load and you can open a notebook there and paste in the above code.
The environment specified for those sessions isn't overly complex as you can see here.
Example of playing a tone in a MyBinder-served notebook
Similar to everything above; however, use this as the code block you paste into a cell:
# Generate a sound. BASED ON
# https://ipython.org/ipython-doc/stable/api/generated/IPython.display.html#IPython.display.Audio
import numpy as np
from IPython.display import Audio, display
framerate = 44100
t = np.linspace(0,5,framerate*5)
data = np.sin(2*np.pi*220*t) + np.sin(2*np.pi*224*t)
Audio(data,rate=framerate)
Example if an interactive control via ipywidgets of audio-generation in a MyBinder-served notebook.
Click here to launch a session with the JupyterLab interface back by an environment with the necessary modules installed, and then run the following in a cell:
!curl -OL https://raw.githubusercontent.com/mlamoureux/PIMS_YRC/master/Widget_audio.ipynb
That will fetch a notebook that you can run, based on code described here.
Alternatively, you can use the classic interface by launching fresh to one or switching from the JupyterLab inferface back by using from the menubar, 'Help' > 'Launch Classic Notebook'.
(I believe the notebook used in this example is based on here, or vice versa. When I tried that one in the ipywidgets docs from a session that already had ipywidgets installed & not much else, I had to also install matplotlib along with ipywidgets via running %pip install matplotlib, because of the line import matplotlib.pyplot as plt.)
UPDATE: use pydub to edit audio via MyBinder and hear it played
This was added in response to the comments to the general answer. Specifically, pydub use is demonstrated using a different enviornment, since pydub needs ffmpeg.
Go here and click on 'launch binder' to spin up a session where ffmpeg is installed in the backing environment. pydub needs ffmpeg or equivalent.
You can run the following line in a notebook and then open the notebook that it gets to work though that demonstration:
!curl -OL https://gist.githubusercontent.com/fomightez/86482965bbce4bbbb7adb4c98f6cd9e6/raw/d31473699d8a2ec6d31dbf1d9590b8a0ef8972db/pydub_edit_plays_via_mybinder.ipynb```
Or step through the equivalent demonstration code in a notebook in JupyterLan by following these steps.
First enter in a cell the following:
```python
%pip install pydub
Get an audio file to use for testing by running this:
!curl -OL http://www.nch.com.au/acm/8k16bitpcm.wav
Edit that file and playback the result in the notebook without interacting with it, by running this in a cell:
from pydub import AudioSegment
from pydub.playback import play
start = 1000
end = 3000
audio = AudioSegment.from_file("8k16bitpcm.wav")
audio_piece = audio[start:end]
audio_piece.export("test_clip.wav", format='wav')
from IPython.display import Audio, display
Audio("test_clip.wav", autoplay=True)

Related

Hide code cells in Jupyter Notebook, execute with Papermill, transform to PDF with nbconvert

I want to run a python program (not command line) using papermill to execute a jupyter notebook and then transform it into a PDF. The idea is working, but I'm unable to hide the input cells.
For papermill report_mode = True is supposed to hide input cells, but there seems to be a problem with jupyter Classic (https://github.com/nteract/papermill/issues/130)
Other extension like hide_input or html scripts are also not sufficient.
Maybe a nbconvert template for hide cells is a solution, but I didn't get that running.
My minimal Code:
pm.execute_notebook(
"Input.ipynb",
"Output.ipynb",
parameters=dict(id=id),
report_mode=True,
)
notebook_filename = "Output.ipynb"
with open(notebook_filename) as f:
nb = nbformat.read(f, as_version=4)
pdf_exporter = PDFExporter()
pdf_data, resources = pdf_exporter.from_notebook_node(nb)
So I'm looking for a way to execute the Notebook, hide the input cells and transform the Notebook to a PDF. I want to use nbconvert in Python and not as a command line tool, since the Script shall run daily.
I know you said you "don't want to use command line", but how about having your python script execute a subprocess command after running papermill? Mixing with this answer:
import subprocess
subprocess.call('jupyter nbconvert --to pdf --TemplateExporter.exclude_input=True Output.ipynb')
You're missing one small detail in your code:
pm.execute_notebook(
"Input.ipynb",
"Output.ipynb",
parameters=dict(id=id),
report_mode=True,
)
notebook_filename = "Output.ipynb"
with open(notebook_filename) as f:
nb = nbformat.read(f, as_version=4)
pdf_exporter = PDFExporter()
# add this
pdf_exporter.exclude_input = True
pdf_data, resources = pdf_exporter.from_notebook_node(nb)
You can also use Ploomber for this; it has a few benefits, like running notebooks in parallel:
# convert.py
from pathlib import Path
from ploomber import DAG
from ploomber.tasks import NotebookRunner
from ploomber.products import File
from ploomber.executors import Parallel
dag = DAG(executor=Parallel())
# hide input and convert to PDF using the LaTeX converter
NotebookRunner(
Path('input.ipynb'),
File('output-latex.pdf'),
dag=dag,
# do not include input code (only cell's output)
nbconvert_export_kwargs={'exclude_input': True},
name='latex')
# hide input and convert to PDF using the web PDF converter (no need to install LaTeX!
NotebookRunner(
Path('input.ipynb'),
File('output-web.pdf'),
dag=dag,
# do not include input code (only cell's output)
nbconvert_export_kwargs={'exclude_input': True},
# use webpdf converter
nbconvert_exporter_name='webpdf',
name='web')
# generate both PDFs
if __name__ == '__main__':
dag.build()
Note: as of Ploomber 0.20, notebooks must have a "parameters" cell (you can add an empty one). See instructions here.
To run it:
pip install ploomber
python convert.py

Adapting Selenium Script for Raspberry Pi

Preface: I have very limited experience with linux and selenium in general. Also this is a multipart question.
Hi there,
I've written a script that I want to run on my Raspberry Pi model 3B which is running Raspbian OS.
I originally built it on a Windows machine (pretty stupid mistake to build it for the wrong platform but anyway) and now need to adapt it so it runs on the Pi.
The main thing I am concerned about is the usage of selenium and chromedriver. I have downloaded chromium-chromedriver (chromium-chromedriver 34.0.1847.116-0ubuntu2 in armhf (Release)) from this repository.
First Question
The file downloads as a .deb which I have never seen before. It opts to install, however I have no idea where it installs as it does not give the option to install to a different directory. I've tried search for it with find, but nothing comes up. Where does it go by default in Raspbian OS?
Second Question
I know I will have to change some expressions because I am using chromium-chromedriver instead of chrome driver, but I am unsure which ones as I don't know selenium that well. This is the main instance here. Do I just change all instances of "Chrome" including "chrome_options" to "Chromium/chromium_options"?
from selenium.webdriver import Chrome
from contextlib import closing
from selenium.webdriver.chrome.options import Options
chrome_options = Options()
chrome_options.add_argument("--headless")
chrome_options.add_argument("--disable-gpu")
chrome_options.add_argument("--no-sandbox")
#Scrape out the table information
with closing(Chrome(chrome_options=chrome_options)) as driver:
Lastly, for the purpose of finding the process with psutil and ending it with process.kill(), the text ID of the driver in task manager should just be chromium-chromedriver.exe right?
Any and all help and advice appreciated.
Thank you all for your time.
L

Python Selenium : How to hide geckodriver?

I am writing an program for a web automation in python. Is here a ways to hide the geckodriver? So that the console (see picture) won't show up when I start the program.
console of geckodriver
here is a fraction of my code:
from selenium import webdriver
from selenium import *
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC`
driver=webdriver.Firefox()
wait=WebDriverWait(driver,120)
url = r"http://google.com"
driver.get(url) #This line starts the console (see picture)
To prevent geckodriver from displaying any windows, you need to pass -headless argument:
from selenium import webdriver
options = webdriver.FirefoxOptions()
options.add_argument('-headless')
driver = webdriver.Firefox(options=options)
driver.get('https://www.example.com')
...
driver.quit()
This worked for me in C#. It blocks both geckodriver and firefox window
FirefoxOptions f = new FirefoxOptions();
f.AddArgument("-headless");
var ffds = FirefoxDriverService.CreateDefaultService();
ffds.HideCommandPromptWindow = true;
driver = new FirefoxDriver(ffds,f);
I was able to do that after implementing PyVirtualDisplay
sudo pip install pyvirtualdisplay # Install it into your Virtual Environment
Then just import Display as follows:
from pyvirtualdisplay import Display
Then, before fetching, start the virtual display as follows:
# initiate virtual display with 'visible=0' activated
# this way you will hide the browser
display = Display(visible=0, size=(800, 600))
# Start Display
display.start()
...
# Do your fetching/scrapping
...
# Stop Display
display.stop()
I hope it helps
Here the approach which has solved it in my case. I used #thekingofravens suggestion but realized that it is just enough to create the Run.bat file which he mentions in his post. Previously I ran my programms in IDLE with F5. Because of this the Geckodriver popped up every few seconds.
My Solution: I just made the Run.bat file with the same code:
cd C:\PathToYourFileWhichIsCausingTheGeckodriverToPopUp
python FileWhichIsCausingTheGeckodriverToPopUp.py
And thats it. Just start this file when you want to run your code and the Geckodriver won't pop up. (That it works without the whole path to you program, Python has to be in PATH.)
Also, of course you can run your program from the command line with the same commands like above and without creating an extra bat file.
You have to take care of a couple of stuffs here:
Keep the useful imports. Unusual imports like from selenium import * (in your code) must be avoided.
Keep your code minimal. wait=WebDriverWait(driver,120) have no usage in your code block.
When you use the raw r switch remember to use single quotes '...'
If you initialize the webdriver instance remember to call the quit() method.
Be careful about indentation while using Python.
Here is the minimal code which uses geckodriver to open the url http://www.google.com, print the Page Title and quits the driver instance.
from selenium import webdriver
driver=webdriver.Firefox(executable_path=r'C:\Utility\BrowserDrivers\geckodriver.exe')
url = r'http://www.google.com'
driver.get(url)
print("Page Title is : %s" %driver.title)
driver.quit()
Console Output:
Page Title is : Google
So I found a very generic workaround to solve this on Windows (in Linux it doesn't seem to be an issue in the first place, can't speak for OSX).
So you need to make three files and its very awkward.
First, you make a file. call it start.bat (or anything) and put the following code in it:
wscript.exe "C:\Wherever\invisible.vbs" "C:\Some Other Place\Run.bat"
This will be the top level batch script. It will be visible for a split second while it launches a visual basic script and passes a batch script as an argument. The purpose of this is to make the next console invisible. Next we make the VBscript, invisible.vbs:
CreateObject("Wscript.Shell").Run """" & WScript.Arguments(0) & """", 0, False
Finally, we make the script that invisible.vbs is supposed to hide, we could call it Run.bat
cd C:\Wherever
python script_using_geckodriver.py
What happens is, as follows:
The first .bat file launches invisible.vbs
invisible.vbs launches the second .bat file without showing it on screen.
The second .bat file then launches the python program. Python (and geckodriver) output to the invisible cmd therefore hiding the geckodriver console window.
P.S. all of this works with PyInstaller to produce a single redistributable package the user can just click on.
Credit harrymc # superuser.com for this solution, which I found when trying to solve an unrelated problem. I tested and realized it was cross applicable to this.
https://superuser.com/questions/62525/run-a-batch-file-in-a-completely-hidden-way

Plotly graph does not show when jupyter notebook is converted to slides

I have a jupyter notebook with interractive plotly plots. I am converting that notebook into slides using nbconvert. When I do so the plotly plots do not show up in the slides. I get the following tornado warnings as well
$ jupyter nbconvert presentation.ipynb --to slides --post serve
[NbConvertApp] Converting notebook presentation.ipynb to slides
[NbConvertApp] Writing 818538 bytes to presentation.slides.html
[NbConvertApp] Redirecting reveal.js requests to https://cdnjs.cloudflare.com/ajax/libs/reveal.js/3.1.0
Serving your slides at http://127.0.0.1:8000/presentation.slides.html
Use Control-C to stop this server
WARNING:tornado.access:404 GET /custom.css (127.0.0.1) 1.53ms
WARNING:tornado.access:404 GET /custom.css (127.0.0.1) 0.96ms
WARNING:tornado.access:404 GET /plotly.js (127.0.0.1) 0.84ms
To add insult to injury this worked yesterday and I don't think I changed anything substantial. I tried rebooting my browser and my machine and neither helped.
1) Check the JS console for errors and the Jupyter log if you are serving the slides via Jupyter. When you browse the slides.html, you may be getting
404 GET /files/mydir/plotly.js
put the plotly.js file in the directory where the slides.html is located (download e.g. https://cdn.plot.ly/plotly-latest.min.js and rename to plotly.js)
2) make sure you are specifying a Layout height and width in your Jupyter notebook e.g.
trace_data = [trace1]
layout = Layout(
autosize=False,
width=720,
height=480,
margin=Margin(
l=50,
r=50,
b=100,
t=100,
pad=4
),
bargroupgap=0.3
)
fig = Figure(data=trace_data, layout=layout)
Re-run your charts, check they appear properly in the notebook, save the notebook, re-run nbconvert.
You do not need to customize the custom.css and make a myreveal.tpl Reveal template and specify it on the nbconvert command line, but you can do so if you wish to customize your slides.
Following the code found here : https://nbviewer.jupyter.org/format/slides/github/tarokiritani/testjupyter/blob/master/test%20plotly.ipynb#/
I have found adding plotly.offline.init_notebook_mode(connected=True) into the same cell as the plotly.offline.(i)plot function works
You must have a plotly.js file in your directory where you are performing nbconvert. For some reason, "to html" will embed the plotly javascript into the HTML file, but "to slides" searches for a plotly.js file in the directory.
That said, you will have to template reveal.js to change dimensions of the slides depending on the size of your plot charts. That, or customize the dimension of the plotly graphs. If the slide are too big (or the other way around), the graphs will collapse into one line in the slides.

Playing a sound in a ipython notebook

I would like to be able to play a sound file in a ipython notebook.
My aim is to be able to listen to the results of different treatments applied to a sound directly from within the notebook.
Is this possible? If yes, what is the best solution to do so?
The previous answer is pretty old. You can use IPython.display.Audio now. Like this:
import IPython
IPython.display.Audio("my_audio_file.mp3")
Note that you can also process any type of audio content, and pass it to this function as a numpy array.
If you want to display multiple audio files, use the following:
IPython.display.display(IPython.display.Audio("my_audio_file.mp3"))
IPython.display.display(IPython.display.Audio("my_audio_file.mp3"))
A small example that might be relevant : http://nbviewer.ipython.org/5507501/the%20sound%20of%20hydrogen.ipynb
it should be possible to avoid gooing through external files by base64 encoding as for PNG/jpg...
The code:
import IPython
IPython.display.Audio("my_audio_file.mp3")
may give an error of "Invalid Source" in IE11, try in other browsers it should work fine.
The other available answers added an HTML element which I disliked, so I created the ringbell, which gets you both play a custom sound as such:
from ringbell import RingBell
RingBell(
sample = "path/to/sample.wav",
minimum_execution_time = 0,
verbose = True
)
and it also gets you a one-lines to play a bell when a cell execution takes more than 1 minute (or a custom amount of time for that matter) or is fails with an exception:
import ringbell.auto
You can install this package from PyPI:
pip install ringbell
If the sound you are looking for could be also a "Text-to-Speech", I would like to mention that every time a start some long process in the background, I queue the execution of a cell like this too:
from IPython.display import clear_output, display, HTML, Javascript
display(Javascript("""
var msg = new SpeechSynthesisUtterance();
msg.text = "Process completed!";
window.speechSynthesis.speak(msg);
"""))
You can change the text you want to hear with msg.text.

Resources