Python Forum
Pyglet Media: unjustifiable memory usage
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Pyglet Media: unjustifiable memory usage
#1
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#requirements
    #Pyglet
 
 
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.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
#requirements
    #Pyglet
 
 
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.
Reply
#2
The docs advise using:
1
2
music = pyglet.resource.media('music.mp3')
music.play()
see: http://pythonhosted.org/pyglet/programmi...music.html

I am not familiar with this package, but will show this anyway
Reply
#3
(Aug-19-2017, 04:04 PM)Larz60+ Wrote: The docs advise using:
1
2
music = pyglet.resource.media('music.mp3')
music.play()

pyglet.resource.media and pyglet.media.load[I used] both are same.
[inline] pyglet.resource.media locates the sound file in the application's directory (not the working directory).
If you know the actual filesystem path (either relative or absolute), use pyglet.media.load.[/inline]

They just load the source and return source object which is passed to the player. I think the problem is with player object, but then my alternate method didn't work either.
Reply
#4
(Aug-19-2017, 02:54 PM)hbknjr Wrote: 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.
Pyglet use Python garbage collector to release stuff from memory.
There is a Player.delete() method that release resources immediately.
They doc for this is here.
Reply
#5
(Aug-19-2017, 08:06 PM)snippsat Wrote: Pyglet use Python garbage collector to release stuff from memory.
There is a Player.delete() method that release resources immediately.
I tried that in second method:

(Aug-19-2017, 02:54 PM)hbknjr Wrote: Here's an alternate way I tried by deleting the player object, calling gc, and recreating it but no success.

1
2
3
4
5
6
7
8
  #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

But the above code doesn't effect the memory usage at all. I also tried del which obviously doesn't work as song keeps playing in background, assigning self.player=None and calling gc also didn't work. Tell me where I'm wrong.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Getting an error while trying to process data, low memory when memory is not low? bkeith12 0 554 Dec-20-2024, 03:06 PM
Last Post: bkeith12
  Media Pipe Python Interfacing with MATLAB cmcreecc 1 989 May-30-2024, 07:23 AM
Last Post: TrentErnser
  negative memory usage akbarza 1 1,265 Apr-27-2024, 08:43 AM
Last Post: Gribouillis
  How would I be able to detect a media player app playing a video. phpjunkie 2 1,442 Oct-16-2023, 02:09 PM
Last Post: phpjunkie
  Python & Windows Media Player Extra 9 8,477 Apr-05-2022, 10:34 PM
Last Post: Extra
  Playing mp3 with pyglet constantin01 3 6,686 Dec-17-2021, 01:14 PM
Last Post: Legumen
  Reducing runtime memory usage in Cpython interpreter david_the_graower 2 3,022 Oct-18-2021, 09:56 PM
Last Post: david_the_graower
  Adding variable to Python code - media sentiment analysis Marietje 3 3,503 May-25-2021, 05:15 PM
Last Post: jefsummers
  pyglet problem deansenecal 1 2,725 Feb-15-2021, 11:15 PM
Last Post: Larz60+
  Python - Import file sequence into Media Pool jensenni 1 2,979 Feb-02-2021, 05:11 PM
Last Post: buran

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020