树莓派瞎折腾[1]-实现简单的命令行音乐播放器

声明:

树莓派采用树莓派3B。

音乐源来自网易云音乐。


正文:

根据整个树莓派折腾的经历,该项目主要沿着如下的路线递进:听歌->在线听歌->在线自由听歌->远程操控树莓派播放。

         首先是听歌部分。无论是在Windows图形界面还是Linux图形界面中,都有许多可供选择的音乐播放器。但是在命令行情形下,就少得多了。其中比较知名的有mplayer,mpg123等。经测试,mpg123对mp3的支持不好,mplayer最佳。它的运行格式如下:

mplayer/home/pi/Music/XXX.mp3

         但是以上方法有个缺点,只能播放本地音乐。由于SD卡容积较小,存放大量音乐过于浪费空间,播放在线音乐能解决以上问题。幸运的是,mplayer支持直接播放在线音乐,只需知道歌曲的URL地址即可。网络上有许多能提取直链的网站,比如:http://music.liuzhijin.cn/。

mplayer播放在线音乐的格式如下:

mplayer http://m2.236.net.XXX.mp3

         同样的,这一个方法也有一个问题:每当我们想要听一首歌,还必须搜索它的直链,这无疑非常麻烦。为了解决这个问题,网络上有不少获取音乐直链的方法。以网易云音乐为例,主要有三种方法:

         1.模拟登录web界面,进行处理。该方法不仅能实现音乐播放,还能实现登录等功能。

         2.模拟网易云音乐安卓客户端1.5.2的行为,每次申请从网易服务端读取数据。

         3.从网易给某些应用提供的音乐插件入手,分析其行为,得到数据。但功能有限

         由于我只需要获得音乐直链,不需要进行登录,查看榜单等操作。因此我选择第三种方式,并寻找到了网易云音乐给网易旗下产品LOFTER的音乐接口。可能因为同属一家公司的缘故,该接口异常简单。它的形式如下:http://s.music.163.com/search/get/?src=lofter &type=1&s=X&limit=3,其中,s=后面即是需要搜索的内容,甚至无任何编码,type为搜索类型查询类型,1为单曲,10为专辑,100为歌手,1000为歌单,1002为用户。limit后为返回条数。而且网页返回的为裸露的json数据,非常易于提取。

         到此,我们需要的数据基本采集完毕。我制作了一个脚本,用户输入想要搜索的歌曲名字,并指定播放曲目,便能轻松听歌。

         脚本的实现思路如下:第一步,利用 urllib2函数将网页上的内容得到。第二步,通过reads及json.loads方法将内容解码成字典形式。第三步,观察字典格式,提取出我们想要的数据,比如直链可由以下命令提取:name1 = html[‘result’][‘songs’][0][‘name’]。第四步,调用mplayer播放该流媒体。为了方便,我们使用commands.getoutput方法让播放之灵在Python内部执行。

         看上去简单,但是在编写脚本中遇到了不少的问题,比如某些歌曲很冷门,返回数据不足三首,我们利用字典路径查询时会出错。要解决这个问题,首先要知道它返回了多少首歌,并根据不同情况返回相应提示。一般来说,有两种方法:一是检查song下属有多少个段落,则得到多少首歌。二是通过一些特殊字符的个数得到歌曲数,我的方法是数“=”字符的个数,因为每一首歌会返回两个地址,一是专辑图片,二是音频地址。每个地址都包含两个“=”字符,因此数“=”的个数,再除以四即可。(注:此处直接得到json字段长度即可,更加简便)

         完成脚本基本功能之后,为了方便用户使用,我还添加了一些实用的功能。比如帮助按钮,比如改变字体颜色,更加醒目。

         该脚本的源码见附录。

         该脚本能够实现在命令行中自动搜索并播放,但很多时候我们需要在移动设备上控制音箱。比如:在微信上发送指令,即可实现多种功能。这里介绍一个比较成熟的项目:微信-树莓派-网易云音乐[1],它基于ItChat项目以及命令行云音乐项目。将树莓派作为播放器,通过ItChat将树莓派和微信账号结合起来。任何对该账号的指令都能被树莓派读取。树莓派读取相关指令,结合Python代码中的定义,执行相关指令。


附录:

# -*- coding: utf-8 -*-
import urllib2
import json
import sys, getopt
import commands
import collections
reload(sys)
sys.setdefaultencoding('utf-8')

def main(argv):
	searchname = ''
	number = '0'
	try:
		opts, args = getopt.getopt(argv,'h',["name=","num="])
	except getopt.GetoptError:
		print '对不起,参数输入不完整,请重新输入'
		sys.exit()
	for opt, arg in opts:
		if opt == '-h':
			print '\n本项目源采用网易云音乐,播放器采用mplayer\n--name 写入歌曲名字\n--num  选择歌曲序号\n<- , -> 可快进快退\n9,0可增加减小音量'
			sys.exit()
		elif opt in ("--name"):
			searchname = arg
		elif opt in ("--num"):
			number = arg

	shtml = r'http://s.music.163.com/search/get/?src=lofter&type=1&filterDj=true&s=%s&limit=3'%(searchname)
	html = urllib2.urlopen(shtml)
	html = html.read()	#句柄转化成字符串处理

	counts = collections.Counter(html)
	counts = counts['=']	#此处最好用len函数判断songs底下的段落数目
	counts = counts/4

	html = json.loads(html)	#解码json格式

	if counts>0:
		name1 = html['result']['songs'][0]['name']
		singer1 = html['result']['songs'][0]['artists'][0]['name']
		album1 = html['result']['songs'][0]['album']['name']
		url1 = html['result']['songs'][0]['audio']
		print '\n\033[1;36;40m1.歌名:%s \n  歌手:%s \n  专辑:%s \033[0m'%(name1,singer1,album1)
	if counts>1:
		name2 = html['result']['songs'][1]['name']
		singer2 = html['result']['songs'][1]['artists'][0]['name']
		album2 = html['result']['songs'][1]['album']['name']
		url2 = html['result']['songs'][1]['audio']
		print '\n\033[1;36;40m2.歌名:%s \n  歌手:%s \n  专辑:%s \033[0m'%(name2,singer2,album2)
	if counts>2:
		name3 = html['result']['songs'][2]['name']
		singer3 = html['result']['songs'][2]['artists'][0]['name']
		album3 = html['result']['songs'][2]['album']['name']
		url3 = html['result']['songs'][2]['audio']
		print '\n\033[1;36;40m3.歌名:%s \n  歌手:%s \n  专辑:%s \033[0m'%(name3,singer3,album3)
	if counts==0:
		print '未指定搜索内容或搜索无结果'

	if number =='1':
		a = 'mplayer %s'%(url1)
		print '\n\033[5;31;40m♪♪\033[0m\033[0;31;40m正在播放第一首曲目\033[0m\033[5;31;40m♪♪\033[0m'
		commands.getoutput(a)
	if number =='2':
		a = 'mplayer %s'%(url2)
		print '\n\033[5;31;40m♪♪\033[0m\033[0;31;40m正在播放第二首曲目\033[0m\033[5;31;40m♪♪\033[0m'
		commands.getoutput(a)
	if number =='3':
		a = 'mplayer %s'%(url3)
		print '\n\033[5;31;40m♪♪\033[0m\033[0;31;40m正在播放第三首曲目\033[0m\033[5;31;40m♪♪\033[0m'
		commands.getoutput(a)

if __name__ == "__main__":
   main(sys.argv[1:])

效果图:


[1] GitHub上的地址为:https://github.com/yaphone/RasWxNeteaseMusic

你可能感兴趣的:(树莓派瞎折腾[1]-实现简单的命令行音乐播放器)