如何在python中播放wav文件?

Posted

技术标签:

【中文标题】如何在python中播放wav文件?【英文标题】:how to play wav file in python? 【发布时间】:2013-07-13 11:40:33 【问题描述】:

我尝试使用 pygame 播放 wav 文件,如下所示:

import pygame
pygame.init()

pygame.mixer.music.load("mysound.wav")
pygame.mixer.music.play()
pygame.event.wait()

但它改变了声音,我不知道为什么! 我阅读了this link 解决方案,但无法解决播放波形文件的问题!

对于这个解决方案,我不知道我应该导入什么?

s = Sound() 
s.read('sound.wav') 
s.play()

对于这个解决方案 /dev/dsp 不存在于新版本的 linux 中:

from wave import open as waveOpen
from ossaudiodev import open as ossOpen
s = waveOpen('tada.wav','rb')
(nc,sw,fr,nf,comptype, compname) = s.getparams( )
dsp = ossOpen('/dev/dsp','w')
try:
  from ossaudiodev import AFMT_S16_NE
except ImportError:
  if byteorder == "little":
    AFMT_S16_NE = ossaudiodev.AFMT_S16_LE
  else:
    AFMT_S16_NE = ossaudiodev.AFMT_S16_BE
dsp.setparameters(AFMT_S16_NE, nc, fr)
data = s.readframes(nf)
s.close()
dsp.write(data)
dsp.close()

当我尝试 pyglet 时,它给了我这个错误:

import pyglet

music = pyglet.resource.media('mysound.wav')
music.play()

pyglet.app.run()
--------------------------

nima@ca005 Desktop]$ python play.py
Traceback (most recent call last):
  File "play.py", line 4, in <module>
    music = pyglet.resource.media('mysound.wav')
  File "/usr/lib/python2.7/site-packages/pyglet/resource.py", line 587, in media
    return media.load(path, streaming=streaming)
  File "/usr/lib/python2.7/site-packages/pyglet/media/__init__.py", line 1386, in load
    source = _source_class(filename, file)
  File "/usr/lib/python2.7/site-packages/pyglet/media/riff.py", line 194, in __init__
    format = wave_form.get_format_chunk()
  File "/usr/lib/python2.7/site-packages/pyglet/media/riff.py", line 174, in get_format_chunk
    for chunk in self.get_chunks():
  File "/usr/lib/python2.7/site-packages/pyglet/media/riff.py", line 110, in get_chunks
    chunk = cls(self.file, name, length, offset)
  File "/usr/lib/python2.7/site-packages/pyglet/media/riff.py", line 155, in __init__
    raise RIFFFormatException('Size of format chunk is incorrect.')
pyglet.media.riff.RIFFFormatException: Size of format chunk is incorrect.
AL lib: ReleaseALC: 1 device not closed

【问题讨论】:

“它改变声音”是什么意思? 它将男人的声音变成了孩子的声音(对不起,我的英语不是很好,我找不到合适的词来解决我的问题) 你的意思是,它听起来比它应该的高音? 是的,音高更高 试试just_playback 【参考方案1】:

您可以使用PyAudio。在我的 Linux 上运行的一个示例:

#!usr/bin/env python  
#coding=utf-8  

import pyaudio  
import wave  

#define stream chunk   
chunk = 1024  

#open a wav format music  
f = wave.open(r"/usr/share/sounds/alsa/Rear_Center.wav","rb")  
#instantiate PyAudio  
p = pyaudio.PyAudio()  
#open stream  
stream = p.open(format = p.get_format_from_width(f.getsampwidth()),  
                channels = f.getnchannels(),  
                rate = f.getframerate(),  
                output = True)  
#read data  
data = f.readframes(chunk)  

#play stream  
while data:  
    stream.write(data)  
    data = f.readframes(chunk)  

#stop stream  
stream.stop_stream()  
stream.close()  

#close PyAudio  
p.terminate()  

【讨论】:

我收到 ALSA 错误 ***.com/questions/17137701/… 只有一个附加组件:将 while data != '': 更改为 while len(data) &gt; 0: 解决了这个 while 进入无限循环的问题。仅在使用 pyaudio 0.2.9 从 python 3.4 更新到 3.5 后才会出现此问题来源:PyAudio Documentation【参考方案2】:

pygame 更改音频的原因是混音器默认为 22k 采样率:

initialize the mixer module
pygame.mixer.init(frequency=22050, size=-16, channels=2, buffer=4096): return None

您的 wav 可能是 8k。所以当 pygame 播放它时,它的播放速度大约是原来的两倍。因此,请在 init 中指定您的 wav 频率。

Pyglet 在正确读取 RIFF 标头时存在一些问题。如果你有一个非常基本的 wav 文件(正好有一个 16 字节的 fmt 块),而 fmt 块中没有其他信息(如“事实”数据),它就可以工作。但是它没有为块中的额外数据做准备,所以它确实不遵守 RIFF 接口规范。

【讨论】:

【参考方案3】:

在 Windows 上为我工作: https://pypi.org/project/playsound/

>>> from playsound import playsound
>>> playsound('/path/to/a/sound/file/you/want/to/play.wav')

注意:这在 Windows 中有一个错误,它不会关闭流。 我在这里添加了一个 PR 进行修复: https://github.com/TaylorSMarks/playsound/pull/53/commits/53240d970aef483b38fc6d364a0ae0ad6f8bf9a0

【讨论】:

不幸的是,这会在窗口中为每个播放的声音打开一个新的 LAV 音频解码器进程,这很糟糕,因为否则它很简单。 我也注意到了这一点。我添加了一个 PR 进行修复。查看我更新的评论【参考方案4】:

PyGame 有 2 个用于播放声音和音乐的不同模块,pygame.mixer 模块和 pygame.mixer.music 模块。该模块包含用于加载声音对象和控制播放的类。文档中解释了差异:

音乐播放和常规声音播放之间的区别在于,音乐是流式传输的,并且不会一次真正加载。混音器系统一次只支持一个音乐流。

如果你想播放单个 wav 文件,你必须初始化模块并从文件中创建一个pygame.mixer.Sound() 对象。调用play() 开始播放文件。最后,您必须等待文件播放。

使用get_length() 获取声音的长度(以秒为单位)并等待声音结束: (pygame.time.wait() 的参数以毫秒为单位)

import pygame

pygame.mixer.init()
my_sound = pygame.mixer.Sound('mysound.wav')
my_sound.play()
pygame.time.wait(int(my_sound.get_length() * 1000))

或者,您可以使用pygame.mixer.get_busy 来测试是否混合了声音。循环不断地查询混音器的状态:

import pygame
pygame.init()

pygame.mixer.init()
my_sound = pygame.mixer.Sound('mysound.wav')
my_sound.play()

while pygame.mixer.get_busy():
    pygame.time.delay(10)
    pygame.event.poll()

【讨论】:

以上是关于如何在python中播放wav文件?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Windows 中播放 .wav 文件?

如何从内存中播放 Wav 声音样本

如何保存同时播放两个曲目的wav文件?在不同的体积

如何在导出的 jar 文件中播放 .wav 文件?

打开表单时如何让wav文件在后台播放?

如何在 Android 中播放附加到(IP 语音)语音邮件文件的 .wav 文件? [复制]