如何使用pyaudio播放音频文件?

10

我不理解pyaudio的示例资料。看起来他们写了一个完整的小程序,这让我感到困惑。

我该如何播放单个音频文件?

格式不是问题,我只想知道播放音频文件所需的最少代码。

3个回答

19

这个例子对我来说很清晰。你只需将示例保存为playwav.py并调用:

python playwav.py my_fav_wav.wav

以下是带有一些额外注释的波形示例:

import pyaudio
import wave
import sys

# length of data to read.
chunk = 1024

# validation. If a wave file hasn't been specified, exit.
if len(sys.argv) < 2:
    print "Plays a wave file.\n\n" +\
          "Usage: %s filename.wav" % sys.argv[0]
    sys.exit(-1)

'''
************************************************************************
      This is the start of the "minimum needed to read a wave"
************************************************************************
'''
# open the file for reading.
wf = wave.open(sys.argv[1], 'rb')

# create an audio object
p = pyaudio.PyAudio()

# open stream based on the wave object which has been input.
stream = p.open(format =
                p.get_format_from_width(wf.getsampwidth()),
                channels = wf.getnchannels(),
                rate = wf.getframerate(),
                output = True)

# read data (based on the chunk size)
data = wf.readframes(chunk)

# play stream (looping from beginning of file to the end)
while data:
    # writing to the stream is what *actually* plays the sound.
    stream.write(data)
    data = wf.readframes(chunk)


# cleanup stuff.
wf.close()
stream.close()    
p.terminate()

我收到了“无法连接到服务器请求通道”的错误信息,这可能是因为Jack服务器未运行或无法启动。 - Jonathan
@JonathanLeaders 你可能想要再提一个新问题。 - cwallenpoole
显然,它会在出现错误时播放,但速度不正确,所以我选择了pygame.mixer。 - Jonathan
2
使用Python 3时,我不得不将条件替换为if len(data)>0;否则,此循环将变成无限循环。 - SwiftStudier
1
while data: works correctly, also needs wf.close() - Gringo Suave
显示剩余2条评论

18

也许这个小包装器(警告:是在膝盖上创建的)可以帮助您理解他们编写的代码的含义。

import pyaudio
import wave
import sys

class AudioFile:
    chunk = 1024

    def __init__(self, file):
        """ Init audio stream """ 
        self.wf = wave.open(file, 'rb')
        self.p = pyaudio.PyAudio()
        self.stream = self.p.open(
            format = self.p.get_format_from_width(self.wf.getsampwidth()),
            channels = self.wf.getnchannels(),
            rate = self.wf.getframerate(),
            output = True
        )

    def play(self):
        """ Play entire file """
        data = self.wf.readframes(self.chunk)
        while data != b'':
            self.stream.write(data)
            data = self.wf.readframes(self.chunk)

    def close(self):
        """ Graceful shutdown """ 
        self.stream.close()
        self.p.terminate()

# Usage example for pyaudio
a = AudioFile("1.wav")
a.play()
a.close()

这就是我需要的全部吗?我不需要保存任何示例等等...只需要Pyaudio吗?这是独立的吗? - JShoe
@JShoe:当然,你需要将它保存到某个*.py文件中(例如“somefile.py”),然后使用Python运行它。当然,你需要在工作目录中有一个音频文件“1.wav”。 - Mikhail Churbanov
好的。顺便问一下,Mac和Windows的默认工作目录是什么? - JShoe
这是否考虑了文件的速度? - Jonathan
1
数据不是ASCII码,应该使用带有“b”前缀的“!= b''”,否则会无限循环。 - jotadepicas
显示剩余2条评论

0

这种方法需要使用pydub的ffmpeg,但不仅可以播放wave文件:

import pyaudio
import sys
from pydub import AudioSegment


if len(sys.argv) <= 1:
    print('No File Name!')
    sys.exit(1)


chunk = 1024
fn = ' '.join(sys.argv[1:])


pd = AudioSegment.from_file(fn)
p = pyaudio.PyAudio()

stream = p.open(format =
                p.get_format_from_width(pd.sample_width),
                channels = pd.channels,
                rate = pd.frame_rate,
                output = True)


i = 0
data = pd[:chunk]._data
while data:
    stream.write(data)
    i += chunk
    data = pd[i:i + chunk]._data


stream.close()    
p.terminate()
sys.exit(0)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接