Aug-19-2017, 02:54 PM
Hi,
I was recommended Pyglet for creating music player Here. I encountered an issue of high memory usage while playing mp3 files.
PROBLEM: I created a player object and loaded/queued some mp3s but each time when I use the next_source method to play the next queued mp3 it takes around 50-80mb of additional RAM. I tried to use memory_profiler but in vain.
Here are the steps to recreate the issue:
1: Run below code in a directory with few mp3 files, and plz make sure to fulfill requirements.
I was recommended Pyglet for creating music player Here. I encountered an issue of high memory usage while playing mp3 files.
PROBLEM: I created a player object and loaded/queued some mp3s but each time when I use the next_source method to play the next queued mp3 it takes around 50-80mb of additional RAM. I tried to use memory_profiler but in vain.
Here are the steps to recreate the issue:
1: Run below code in a directory with few mp3 files, and plz make sure to fulfill requirements.
#requirements #Pyglet #http://avbin.github.io/AVbin/Download.html #https://pypi.python.org/pypi/memory_profiler import os import fnmatch from memory_profiler import profile from pyglet.media import * from pyglet.media.avbin import AVbinException class MusicPlayerCore(): def __init__(self): self.player = Player() self.loadsource() #loading all mp3 in player @profile def loadsource(self): songpathlist = self.recur_searchindir() for song in songpathlist: try: source = load(song) self.player.queue(source) except AVbinException: pass @profile def play(self): self.player.play() def pause(self): self.player.pause() @profile def next(self): self.player.next_source() #Find all mp3 in current directory of script def recur_searchindir(self): directory = os.path.dirname(os.path.realpath(__file__)) songpathlist = [] for root, dirnames, filenames in os.walk(directory): for filename in fnmatch.filter(filenames, '*.mp3'): songpathlist.append(os.path.join(root, filename)) return songpathlist def main(): player = MusicPlayerCore() while 1: print("1-Play \n 2-Pause \n 3- Play Next\n 4- Exit") ch = int(input("Enter choice:")) if ch == 1: player.play() elif ch == 2: player.pause() elif ch == 3: player.next() elif ch == 4: break else: print("Wrong choice") if __name__ == "__main__": main()Here's an alternate way I tried by deleting the player object, calling gc, and recreating it but no success.
#requirements #Pyglet #http://avbin.github.io/AVbin/Download.html #https://pypi.python.org/pypi/memory_profiler import os import fnmatch import gc from memory_profiler import profile from pyglet.media import * from pyglet.media.avbin import AVbinException class MusicPlayerCore(): def __init__(self, songlist): self.songlist = songlist #list of path of all songs in dir self.player = Player() #pyglet player object self.songnav = NextandPrev(songlist) self.currentsong = songlist[0] # path of current song | initially first song self.loadsource() # load currentsong #loading current song in player @profile def loadsource(self): try: source = load(self.currentsong) self.player.queue(source) except AVbinException: self.songnavupdate_next() #updating previous and current song path @profile def songnavupdate_next(self): if self.songnav.n_song != None: self.makenewplayer() # create new player object self.currentsong = self.songnav.n_song self.songnav.remake_list(self.currentsong) self.loadsource() #updating previous and current song path @profile def songnavupdate_prev(self): if self.songnav.p_song !=None: self.makenewplayer() # create new player object self.currentsong = self.songnav.p_song self.songnav.remake_list(self.currentsong) self.loadsource() #Make a new Player object, deleting previous one @profile def makenewplayer(self): '''memory_profiler shows no change in memory usage here''' self.player.delete() #deleting current player object #del self.player gc.collect() #explicitly calling gc.collect to remove out of scope player object self.player = Player() #new player object @profile def play(self): self.player.play() def pause(self): self.player.pause() @profile def play_next(self): self.songnavupdate_next() self.player.play() @profile def play_prev(self): self.songnavupdate_prev() self.player.play() class NextandPrev(): def __init__(self, songlist): self.songlist = songlist self.n_song = songlist[1] self.p_song = None def remake_list(self, current_song): index = self.songlist.index(current_song) try: self.n_song = self.songlist[index + 1] except IndexError: self.n_song = None try: self.p_song = self.songlist[index - 1] except IndexError: self.p_song = None #Find all mp3 in current directory of script def recur_searchindir(): directory = os.path.dirname(os.path.realpath(__file__)) songpathlist = [] for root, dirnames, filenames in os.walk(directory): for filename in fnmatch.filter(filenames, '*.mp3'): songpathlist.append(os.path.join(root, filename)) return songpathlist def main(): songpathlist = recur_searchindir() player = MusicPlayerCore(songpathlist) while 1: print("1-Play \n 2-Pause \n 3- Play Next\n 4- Previous \n 5- Exit") ch = int(input("Enter choice:")) if ch == 1: player.play() elif ch == 2: player.pause() elif ch == 3: player.play_next() elif ch == 4: player.play_prev() elif ch == 5: break else: print("Wrong choice") if __name__ == "__main__": main()I also tried to understand the pyglet code but it is too optimized for readability and I'm not pro enough.