forked from dingdang-robot/dingdang-contrib
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBaiduFM.py
227 lines (179 loc) · 6.64 KB
/
BaiduFM.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
# -*- coding: utf-8-*-
import json
import logging
import os
import socket
import subprocess
import sys
import tempfile
import threading
from urllib import urlopen
reload(sys)
sys.setdefaultencoding('utf8')
socket.setdefaulttimeout(10)
WORDS = ["BAIDUYINYUE"]
SLUG = "baidufm"
DEFAULT_CHANNEL = 14
class MusicPlayer(threading.Thread):
def __init__(self, playlist, logger):
super(MusicPlayer, self).__init__()
self.event = threading.Event()
self.event.set()
self.playlist = playlist
self.idx = 0
self.is_stop = False
self.is_pause = False
self.song_file = "dummy"
self.directory = tempfile.mkdtemp()
self.logger = logger
def run(self):
while True:
if self.event.wait():
self.play()
if not self.is_pause:
self.pick_next()
def play(self):
self.logger.debug('MusicPlayer play')
song_url = "http://music.baidu.com/data/music/fmlink?" +\
"type=mp3&rate=320&songIds=%s" % self.playlist[self.idx]['id']
song_name, song_link, song_size, song_time =\
self.get_song_real_url(song_url)
self.download_mp3_by_link(song_link, song_name, song_size)
self.play_mp3_by_link(song_link, song_name, song_size, song_time)
def get_song_real_url(self, song_url):
try:
htmldoc = urlopen(song_url).read().decode('utf8')
except:
return(None, None, 0, 0)
content = json.loads(htmldoc)
try:
song_link = content['data']['songList'][0]['songLink']
song_name = content['data']['songList'][0]['songName']
song_size = int(content['data']['songList'][0]['size'])
song_time = int(content['data']['songList'][0]['time'])
except:
self.logger.error('get real link failed')
return(None, None, 0, 0)
return song_name, song_link, song_size, song_time
def play_mp3_by_link(self, song_link, song_name, song_size, song_time):
process = subprocess.Popen("pkill play", shell=True)
process.wait()
if os.path.exists(self.song_file):
if not self.is_stop:
cmd = ['play', self.song_file]
self.logger.debug('begin to play')
with tempfile.TemporaryFile() as f:
subprocess.call(cmd, stdout=f, stderr=f)
f.seek(0)
output = f.read()
print(output)
self.logger.debug('play done')
if not self.is_pause:
self.logger.debug('song_file remove')
os.remove(self.song_file)
def download_mp3_by_link(self, song_link, song_name, song_size):
file_name = song_name + ".mp3"
self.song_file = os.path.join(self.directory, file_name)
if os.path.exists(self.song_file):
return
self.logger.debug("begin DownLoad %s size %d" % (song_name, song_size))
mp3 = urlopen(song_link)
block_size = 8192
down_loaded_size = 0
file = open(self.song_file, "wb")
while True and not self.is_stop:
try:
buffer = mp3.read(block_size)
down_loaded_size += len(buffer)
if(len(buffer) == 0):
if down_loaded_size < song_size:
if os.path.exists(self.song_file):
os.remove(self.song_file)
break
file.write(buffer)
if down_loaded_size >= song_size:
self.logger.debug('%s download finshed' % self.song_file)
break
except:
if os.path.getsize(self.song_file) < song_size:
self.logger.debug('song_file remove')
if os.path.exists(self.song_file):
os.remove(self.song_file)
break
file.close()
def pick_next(self):
self.idx += 1
if self.idx > len(self.playlist) - 1:
self.idx = 0
def pause(self):
try:
self.event.clear()
self.is_pause = True
subprocess.Popen("pkill play", shell=True)
except:
pass
def resume(self):
self.is_pause = False
self.event.set()
def stop(self):
self.pause()
self.is_stop = True
self.playlist = []
if os.path.exists(self.song_file):
os.remove(self.song_file)
if os.path.exists(self.directory):
os.removedirs(self.directory)
def get_channel_list(page_url):
try:
htmldoc = urlopen(page_url).read().decode('utf8')
except:
return {}
content = json.loads(htmldoc)
channel_list = content['channel_list']
return channel_list
def get_song_list(channel_url):
try:
htmldoc = urlopen(channel_url).read().decode('utf8')
except:
return{}
content = json.loads(htmldoc)
song_id_list = content['list']
return song_id_list
def handle(text, mic, profile, bot=None):
logger = logging.getLogger(__name__)
page_url = 'http://fm.baidu.com/dev/api/?tn=channellist'
channel_list = get_channel_list(page_url)
if 'robot_name' in profile:
persona = profile['robot_name']
channel = DEFAULT_CHANNEL
if SLUG in profile and 'channel' in profile[SLUG]:
channel = profile[SLUG]['channel']
channel_id = channel_list[channel]['channel_id']
channel_name = channel_list[channel]['channel_name']
mic.say(u"播放" + channel_name)
while True:
channel_url = 'http://fm.baidu.com/dev/api/' +\
'?tn=playlist&format=json&id=%s' % channel_id
song_id_list = get_song_list(channel_url)
music_player = MusicPlayer(song_id_list, logger)
music_player.start()
while True:
try:
threshold, transcribed = mic.passiveListen(persona)
except Exception, e:
logger.error(e)
threshold, transcribed = (None, None)
if not transcribed or not threshold:
logger.info("Nothing has been said or transcribed.")
continue
music_player.pause()
input = mic.activeListen()
if input and any(ext in input for ext in [u"结束", u"退出", u"停止"]):
mic.say(u"结束播放", cache=True)
music_player.stop()
return
else:
mic.say(u"什么?", cache=True)
music_player.resume()
def isValid(text):
return any(word in text for word in [u"百度音乐", u"百度电台"])