素材牛VIP会员
Python如何播放还存在StringIO中的MP3?
 闪***星  分类:Python  人气:660  回帖:2  发布于6年前 收藏

我尝试利用百度语音云API来实现一个包含TTS的桌面服务。已经成功获取返回MP3,并缓存在cStringIO中,但是不知道如何播放。代码播放抛出错误。

参考了http://guzalexander.com/2012/... 中提到的pywave/pyaudio/pyglet等方法。

代码如下:


#!/usr/bin/env python
#encoding=utf-8  
  
#import wave  
import pyaudio
import pyglet
import urllib, urllib2, pycurl  
import base64  
import json  
import cStringIO
import binascii

## get access token by api key & secret key  
  
def get_token():
    apiKey = "xxxxxxxxxx"  
    secretKey = "yyyyyyyyyyyyyyyyyyyyy"
    auth_url = "https://openapi.baidu.com/oauth/2.0/token?grant_type=client_credentials&client_id=" + apiKey + "&client_secret=" + secretKey;  
  
    res = urllib2.urlopen(auth_url)  
    json_data = res.read()  
    return json.loads(json_data)['access_token']  
  
def dump_res(buf):  
    #print buf  
    pass
  
  
## post audio to server  
def use_cloud(token):  
    fp = wave.open('vad_0.wav', 'rb')  
    nf = fp.getnframes()  
    f_len = nf * 2  
    audio_data = fp.readframes(nf)  
      
    cuid = "xxxxxxxxxx" #my xiaomi phone MAC  
    srv_url = 'http://vop.baidu.com/server_api' + '?cuid=' + cuid + '&token=' + token  
    http_header = [  
    'Content-Type: audio/pcm; rate=8000',  
    'Content-Length: %d' % f_len  
    ]  
      
    c = pycurl.Curl()  
    c.setopt(pycurl.URL, str(srv_url)) #curl doesn't support unicode  
    #c.setopt(c.RETURNTRANSFER, 1)  
    c.setopt(c.HTTPHEADER, http_header)   #must be list, not dict  
    c.setopt(c.POST, 1)  
    c.setopt(c.CONNECTTIMEOUT, 30)  
    c.setopt(c.TIMEOUT, 30)  
    c.setopt(c.WRITEFUNCTION, dump_res)  
    c.setopt(c.POSTFIELDS, audio_data)  
    c.setopt(c.POSTFIELDSIZE, f_len)  
    c.perform() #pycurl.perform() has no return val  
    

def get_audio(token):
    cuid = "00030DAF5784"   # MAC address
    text = "从前有座山,山上有个庙,庙里有个老和尚和小和尚,老和尚对小和尚说:"
    #baidu_url = "http://tsn.baidu.com/text2audio?tex=" + urllib.urlencode(text) + "&lan=zh&cuid=" + cuid + "&ctp=1&tok=" + token
    baidu_url = "http://tsn.baidu.com/text2audio?tex=" + urllib.quote(text) + "&lan=zh&cuid=" + cuid + "&ctp=1&tok=" + token
    
    
    print("URL:\t{0}".format(baidu_url))
    buf = cStringIO.StringIO()

    c = pycurl.Curl()  
    c.setopt(c.URL, str(baidu_url)) #curl doesn't support unicode  
    #c.setopt(c.HTTPHEADER, http_header)   #must be list, not dict  
    #c.setopt(c.GET, 1)  
    c.setopt(c.WRITEFUNCTION, buf.write)
    c.setopt(c.CONNECTTIMEOUT, 30)  
    c.setopt(c.TIMEOUT, 30)  
    c.setopt(c.WRITEFUNCTION, dump_res)  
    c.perform() #pycurl.perform() has no return val  
    #print "type:\t{0}".format(c.CONTENT_TYPE)
    print(c.getinfo(c.CONTENT_TYPE))
    #print buf.getvalue()
    song = pyglet.media.load(buf)
    song.play()
    buf.close()
    
if __name__ == "__main__":  
    token = get_token()  
    print("token:\t{0}".format(token))
    #use_cloud(token)  
    get_audio(token)

抛出错误如下:

Traceback (most recent call last):
  File "C:\BOM_Planner\source\soldering_assistant_mvp.py", line 87, in <module>
    get_audio(token)
  File "C:\BOM_Planner\source\soldering_assistant_mvp.py", line 79, in get_audio
    song = pyglet.media.load(buf)
  File "C:\Python27\lib\site-packages\pyglet\media\__init__.py", line 1429, in load
    source = get_source_loader().load(filename, file)
  File "C:\Python27\lib\site-packages\pyglet\media\__init__.py", line 1410, in load
    return riff.WaveSource(filename, file)
  File "C:\Python27\lib\site-packages\pyglet\media\riff.py", line 185, in __init__
    file = open(filename, 'rb')
TypeError: coercing to Unicode: need string or buffer, cStringIO.StringO found
 标签:python

讨论这个帖子(2)垃圾回帖将一律封号处理……

Lv6 码匠
13***62 产品经理 6年前#1

如果是Linux环境下解决方案就比较多了,如果要实现跨平台建议用pygame。

Lv3 码奴
18***30 Linux系统工程师 6年前#2

你写的Python3就推荐pygame,可以用pygame.mixen.music来播放本地mp3文件。
当时我也找了很多都没有成功,最后用pygame播放的。

这是我写的一个例子。可以看看,我是把网络音乐保存到本地mp3文件再播放的,readme里面有相关信息。
https://github.com/kompasim/p...

 文明上网,理性发言!   😉 阿里云幸运券,戳我领取