【问题标题】:How to solve 'set_pos()' unsupported for codec error in pygame?如何解决 pygame 中编解码器错误不支持的“set_pos()”?
【发布时间】:2021-02-14 09:33:57
【问题描述】:

我创建了一个项目,在我的 python 脚本中需要“set_pos()”函数,但它给出了编解码器不支持的错误。

这是我的代码:

#code 

fast_forward_icon= tk.PhotoImage(file=__file__+ '/../images/JPEG, PNG/icons/fast_forward.png')
def fast_forward(event=None):
    def func():
        global progressbar_music
        current_song_Length = mixer.music.get_pos()//1000
        print(current_song_Length)
        # mixer.music.pause()
        f= current_song_Length+10
        mixer.music.set_pos(f)
        progressbar_music['value']=f
        # mixer.music.progressbar_music(seconds=current_song_Length+10)
        progressbar_music_starttime.configure(text='{}'.format(str(datetime.timedelta(seconds=f))))
        progressbar_music.after(2,func)
    func()

fastForwardBtn = Button(root, bg='#310A3D', image=fast_forward_icon, command=fast_forward)

我的错误:

Tkinter 回调 Traceback 中的异常(最近一次调用最后一次):
文件 "C:\Users\soham\AppData\Local\Programs\Python\Python36\lib\tkinter_init_.py", 第 1702 行,在 调用 return self.func(*args) 文件 "C:\Users\soham\AppData\Local\Programs\Python\Python36\lib\tkinter_init_.py", 第 746 行,调用中 func(*args) 文件“e:/python projects/MUSIC PLAYER/music_player.py”,第 346 行,在 func Mixer.music.set_pos(f) pygame.error: set_pos 不支持此编解码器

【问题讨论】:

  • 尝试将声音文件转换为其他类型
  • WAV音频格式应该很容易支持设置位置,像你这样的其他格式可能不支持设置到随机位置,因此需要转换为WAV。
  • 先生,如何在代码中将mp3转换为wav音频格式并在python队列中导出而不保存在磁盘中?
  • @SDBDARKNINJA 实现了my solution/answer,用于将 MP3 转换为 WAV,甚至将任何音频格式转换为任何其他格式。

标签: python tkinter pygame


【解决方案1】:

一种简单的方法是使用pydub 库,通过python -m pip install pydub 安装一次。我编写的下一个函数接受 MP3 字节(或任何其他音频格式)并返回 WAV 字节(或由format = '...' 参数表示的任何其他格式),函数不使用任何文件系统(全部在内存中完成)。

Try it online!

# Needs: python -m pip install pydub
# Convert
def conv_aud(data, format = 'wav'):
    import pydub, io
    inp, out = io.BytesIO(data), io.BytesIO()
    pydub.AudioSegment.from_file(inp).export(out, format = format)
    return out.getvalue()
# Test
with open('test.mp3', 'rb') as f:
    print(conv_aud(f.read())[:32].hex().upper())

我的test.mp3 的输出:

5249464624D0110357415645666D7420100000000100020044AC000010B10200

另一种方法是在我的下一个解决方案中使用 FFMpeg。

我写了下一个函数conv_aud(),它可以将任何音频格式转换为任何其他格式,实际上它也可以转换视频。

默认情况下,如果未提供格式,它会将 MP3 转换为 WAV。

函数使用FFMpeg,安装一次。此外,如果它位于不在 PATH 系统变量中的 dir 内,那么您应该将参数 ffmpeg = 'c:/path/to/ffmpeg.exe' 提供给函数 conv_aud()。

函数接受输入音频的字节数据或输入文件的 str 路径或打开以供读取的任何类似文件的对象。它还接受 ifmt 参数用于输入格式字符串,如'mp3' 和/或接受ofmt 参数用于输出格式字符串,如'wav'。

函数返回WAV的字节数据。

函数使用中间临时目录和退出时删除的文件。如果出现错误,该函数还会打印来自 FFMpeg 的错误输出。如果有错误,则函数是静默的,不打印任何内容。

代码末尾有test()函数,用于测试使用test.mp3文件作为输入调用函数的不同方式。

Try it online!

# Converts any audio/video format (MP3 by default) to any other format (WAV by default).
# Input to function either "bytes" data or "str" path or read-opened "file" object.
# "ifmt" is input format (taken from input path by default or MP3 if not provided)
# "ofmt" is output format, WAV by default
# "ffmpeg" should contain path to ffmpeg executable
# Function returns converted audio bytes.
def conv_aud(data, ifmt = None, ofmt = 'wav', *, ffmpeg = 'ffmpeg'):
    import tempfile, subprocess, secrets, traceback
    inp_path = None
    if type(data) is str:
        inp_path, data = data, None
    elif type(data) is not bytes:
        data = data.read()
    assert inp_path is not None or type(data) is bytes, (inp_path, type(data))
    if inp_path is not None:
        ifmt_ = inp_path[inp_path.rfind('.') + 1:].lower()
        assert ifmt is None or ifmt.lower() == ifmt_, (ifmt, ifmt_)
        ifmt = ifmt_
    elif ifmt is None:
        ifmt = 'mp3'
    assert ifmt is not None and ofmt is not None, (ifmt, ofmt)
    with tempfile.TemporaryDirectory() as td:
        if data is not None:
            inp_path = str(td) + '/' + secrets.token_hex(8).upper() + '.' + ifmt.lower()
            with open(inp_path, 'wb') as f:
                f.write(data)
        out_path = str(td) + '/' + secrets.token_hex(8).upper() + '.' + ofmt.lower()
        try:
            with open(str(td) + '/out', 'wb') as fout, open(str(td) + '/err', 'wb') as ferr:
                subprocess.run([ffmpeg, '-i', inp_path, out_path], check = True, stdout = fout, stderr = ferr)
            good = True
        except:
            with open(str(td) + '/out', 'rb') as fout, open(str(td) + '/err', 'rb') as ferr:
                for f, n in [(fout, ' stdout '), (ferr, ' stderr ')]:
                    print('-' * 20 + n + '-' * 20 + '\n', f.read().decode('utf-8', 'replace'), sep = '', end = '')
            print('-' * 50)
            good = False
        if not good:
            assert False, 'FFMpeg returned error!'
        with open(out_path, 'rb') as f:
            return f.read()
            
# Testing conv_aud
def test():
    for inp in [open('test.mp3', 'rb').read(), 'test.mp3', open('test.mp3', 'rb')]:
        print(conv_aud(inp)[:32].hex().upper())

if __name__ == '__main__':
    test()

我的test.mp3 文件的输出:

5249464654D0110357415645666D7420100000000100020044AC000010B10200
5249464654D0110357415645666D7420100000000100020044AC000010B10200
5249464654D0110357415645666D7420100000000100020044AC000010B10200

【讨论】:

  • 我想得到这个stackoverflow.com/questions/64640560/…先生的解决方案,我已经尝试过但它不起作用如果它不起作用那么我没有问题我只想制作快进按钮我的音乐播放器,如果你能解决我的问题,我会很高兴
  • @SDBDARKNINJA 好的,我现在会尝试解决您的其他问题,我会在那里回复。
  • @SDBDARKNINJA 我解决了你的第二个任务,here is the answer。
  • 谢谢先生,我会尝试并通知您
猜你喜欢
  • 1970-01-01
  • 2015-01-09
  • 1970-01-01
  • 2019-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-31
  • 1970-01-01
相关资源
最近更新 更多