Progressbar to show amount of music played

强颜欢笑 提交于 2021-02-08 08:35:19

问题


Suppose I use mp3play module to play mp3 files, and using ttk.Progressbar, I want to show the amount(duration) of music played. Is there any code to achieve it?

I also want a timer a to show the duration of music played.

import ttk
import mp3play
self.music = mp3play.load('filename')
self.fr=ttk.Frame()
self.fr.pack(expand=True, fill=BOTH, side=TOP)
self.seek=ttk.Progressbar(self.fr, orient='horizontal', mode='determinate', length=500)
self.seek.place(x=50, y=325)
self.seek.start()

回答1:


It appears that the mp3play module uses the Windows winmm library. Specifically, it uses function mciSendString to control the multimedia system.

One option to achieve what you want would be to use the status command to periodically retrieve the current playback position and display it as you like.

It would seem most appropriate to modify both versions of the AudioClip class from the mp3play library.


Modifying mp3play Library

Class AudioClip in windows.py

First, on line 59 of windows.py you can see a function that uses the status command

    def _mode(self):
        err, buf = self._mci.directsend('status %s mode' % self._alias)
        return buf

We can write a new function based on this example, which will get the current playback position:

    def current_position(self):
        err, buf = self._mci.directsend('status %s position' % self._alias)
        return buf

This function will return a string encoding a number representing the current position in milliseconds.

Class AudioClip in init.py

The next step is to modify AudioClip class on line 12 of __init__py, adding the following function:

    def current_position(self):
        """Get current position of clip in milliseconds."""
        return int(self._clip.current_position())

CLI Example

Now we can test it with a simple script:

import time
import mp3play

clip = mp3play.load(r'test.mp3')

clip.play()

for i in range(5):
    print "Position: %d / %d" % (clip.current_position(), clip.milliseconds())
    time.sleep(1)

clip.stop()

The console output looks as follows:

>python test.py
Position: 0 / 174392
Position: 905 / 174392
Position: 1906 / 174392
Position: 2906 / 174392
Position: 3907 / 174392

GUI Example

import tkinter as tk
from tkinter import ttk

import mp3play

# ================================================================================

def format_duration(ms):
    total_s = ms / 1000
    total_min = total_s / 60
    remain_s = total_s % 60
    return "%0d:%02d" % (total_min, remain_s)

# ================================================================================

class SimplePlayer(tk.Tk):

    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)

        # Variables we use to dynamically update the text of the labels
        self.music_title = tk.StringVar()
        self.music_progress = tk.StringVar()

        self.fr=ttk.Frame()
        self.fr.pack(expand=True, fill=tk.BOTH, side=tk.TOP)

        # Label to display the song title
        self.title_lbl = ttk.Label(self.fr, textvariable = self.music_title)
        self.title_lbl.pack()

        # Playback progress bar
        self.progress_bar = ttk.Progressbar(self.fr, orient='horizontal', mode='determinate', length=500)
        self.progress_bar.pack()

        # Shows the progress numerically
        self.progress_lbl = ttk.Label(self.fr, textvariable = self.music_progress)
        self.progress_lbl.pack()


    def start(self, music_file):
        self.music = mp3play.load(music_file)

        # Update the title
        self.music_title.set(music_file)

        # Start playback
        self.music.play()

        # Start periodically updating the progress bar and progress label
        self.update_progress()

    def update_progress(self):
        pos_ms = self.music.current_position()
        total_ms = self.music.milliseconds()
        progress_percent = pos_ms / float(total_ms) * 100

        # Update the label
        label_text = "%s / %s   (%0.2f %%)" % (format_duration(pos_ms), format_duration(total_ms), progress_percent)
        self.music_progress.set(label_text)

        # Update the progress bar
        self.progress_bar["value"] = progress_percent

        # Schedule next update in 100ms        
        self.after(100, self.update_progress)

# ================================================================================

app = SimplePlayer()

app.start('test.mp3')
app.mainloop()

Screenshot:

Screenshot of running GUI example




回答2:


Looking at the code of mp3playmodule, mp3play.load() returns an AudioClip object. This object has the methods seconds() and milliseconds() that provide the length of the clip in seconds or milliseconds respectively.

You can save the time when you started playing and compare it to the current time and the total length of the clip to determine the status of the progressbar.

# assuming time would me measured in milliseconds
start = time()
while playing:
    # progress measured in percentages
    progress = 100 * (time() - start)/ clip.milliseconds()


来源:https://stackoverflow.com/questions/39789577/progressbar-to-show-amount-of-music-played

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!