Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Playing mp3 in a folder with jupyter notebook

To play video in jupyter notebook: I do: from IPython.display import * Audio("linktomp3.mp3", autoplay=True) This creates an audio player like feel and you can play the mp3.

Now I want to solve one thing. I have many mp3 files in a folder. I want to play all of them in jupyter notebook one by one. How to do that? Any help please?

Also is there a way to tweak this function to enable to play .m4a music file?

Thanks in advance!!

like image 712
Suman Khanal Avatar asked Jan 07 '23 06:01

Suman Khanal


1 Answers

Audio Playlist

We can display html code directly with IPython.display.HTML in Jupyter, all you need to do is create an audio playlist controller and assign filename to the href or src attr.

I just borrowed an demo from HTML5 Audio and Video and how to make a playlist since I'm not quite familiar with web dev. Small modification of css style was made to make the example more intuitive. The author deserves all compliments!

Under the same parent directory of the .ipynb file I created Music dir and copied two album directories into it. The directory structure is like:

../Music/:
Stille/  贼/

The following code will load all .mp3 files under Music dir and generate a playlist.

import os
from IPython.display import display,Audio,HTML
playlist_html=""
audio_html=""
music_dir = u'Music'
count=0
for root, dirs, files in os.walk(music_dir):
    #print 'root: ' + repr(root)
    #print 'dirs: ' + repr(dirs)
    #print 'files: ' + repr(files)
    for file in files:
        if count==0:
            playlist_html = u'''<li class="active"><a href="{0}">{1}</a>
                </li>\n'''.format(os.path.join(root, file), file)
            audio_html = u'''<audio id="audio" preload="auto" tabindex="0" controls="" type="audio/mpeg">
                <source type="audio/mp3" src="{}">Sorry, your browser does not support HTML5 audio.
                </audio>'''.format(os.path.join(root, file))
        else:
            playlist_html +=u'''<li><a href="{0}">{1}</a></li>\n'''.format(os.path.join(root, file), file)
        count += 1

playlist_html = audio_html + u'''\n<ol id="playlist">\n{}</ol>'''.format(playlist_html)
#print playlist_html


playlist_css = """
<style>
#playlist .active a{color:#CC0000;text-decoration:none;}
#playlist li a:hover{text-decoration:none;}
</style>
"""

playlist_js = """
<script>
var audio;
var playlist;
var tracks;
var current;

init();
function init(){
    current = 0;
    audio = $('audio');
    playlist = $('#playlist');
    tracks = playlist.find('li a');
    len = tracks.length - 1;
    audio[0].volume = .10;
    playlist.find('a').click(function(e){
        e.preventDefault();
        link = $(this);
        current = link.parent().index();
        run(link, audio[0]);
    });
    audio[0].addEventListener('ended',function(e){
        current++;
        if(current == len){
            current = 0;
            link = playlist.find('a')[0];
        }else{
            link = playlist.find('a')[current];    
        }
        run($(link),audio[0]);
    });
}
function run(link, player){
        player.src = link.attr('href');
        par = link.parent();
        par.addClass('active').siblings().removeClass('active');
        audio[0].load();
        audio[0].play();
}
</script>
"""
display(HTML(playlist_html))
display(HTML(playlist_css))
display(HTML(playlist_js))

All this code snippet does is inserting html, css and js code into the cell output. Replacing href attr with correct filenames is a bit cumbersome but not difficult. Actually the js code may be much harder to read.

The output in Jupyter is well enough. The controller loaded all files and could play audio files sequentially.

enter image description here

If you want to refactor the code into IPython.core.display.DisplayObject subclasses, I'd suggest reading ipython/Custom Display Logic.ipynb at c4ef808311f2bb84bf4a0a5d3bb980b3d81c373b · ipython/ipython, there's still a lot of work to do.

.m4a support

I tested on my own Jupyter environment (with Chrome) and it fails to play .m4a either. I guess it's because the type attr of audio tag is audio/m4a, which is not correctly recognized by Chrome.

I've come across this similar situation once: python - IPython.display.Audio cannot correctly handle .ogg file type? - Stack Overflow. Manually change the MIME type of .m4a to audio/mp4 will solve the problem according to my test. Add this code snippet before you play .m4a file in IPython:

import mimetypes
mimetypes.init()
mimetypes.add_type('audio/mp4', '.m4a')
like image 163
Joshz Avatar answered Jan 16 '23 11:01

Joshz