热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Ubuntu下自制douban.fm播放器

douban.fm是我常用的网络音乐电台,但因为是web应用,无法使用全局热键控制,官方又没有提供linux桌面版本,故打算自己开发一个linuxdoufan.fm播放器。要实现的功能:

douban.fm 是我常用的网络音乐电台,但因为是web应用,无法使用全局热键控制,官方又没有提供linux桌面版本,故打算自己开发一个linux doufan.fm播放器。

要实现的功能:

  1. 全局热键控制
  2. 开始播放时桌面通知
  3. 登录、选频道

想要实现并不一定能实现,但我会花时间来慢慢攻破困难,目前为止已经简单的实现了基本功能。

 

douban.fm 播放器的简单实现

既然是简单实现,那么在保证功能的前提下应该尽量保持实现的简单,以便后续完善。在开发工具上我选择python,以便快速交付和测试我的想法。

数据来源

如何获取要播放的音乐及相关信息是首要解决的问题,这就必须要研究douban.fm的工作流程。其实我们可以思考一下,如果要我们实现一个网络电台,该怎么实现?不可能把所有的播放列表都放在客户端,是了,一个很好的方案是先由客户端发送请求播放列表,服务端返回播放列表,客户端再根据播放列表中的url请求文件以播放。

当然,具体情况还是要实际分析过才可得知,我们可以用网页调试工具(firebug或chrome的开发者工具),甚至抓包软件,分析douban.fm的数据通信。

刷新后,可以看到douban.fm发出的所有http请求,接下来,我们要有目的的寻找携带播放列表的http响应:

从url可以明显的看到playlist字样,展开该请求响应,可以看出响应数据的格式是json,继续展开,终于找到了我们想要的数据。

接着,我们要研究该url的参数,以便定制我们的播放器。在新标签打开该url:

经过多次尝试,大概可以确定这几个参数的行为:

  • type:字面意义是类型,具体作用不明,由douban.fm发出的所有请求都使用了type=n,缺少该参数将无法正常获取播放列表;
  • sid:作用不明,可省,猜测与用户相关;
  • pt:作用不明,可省,猜测与音乐类型相关;
  • chanel:频道ID,经过测试发现,0:公共/私人(指定sid时)兆赫、1:华语、-3:红心兆赫;
  • from:客户端来源,可省;
  • r:从值来看,应该是random的缩写,可省;

所以,一条最简单的获取播放列表的url是:http://douban.fm/j/mine/playlist?type=n&channel=0

播放音乐

有了音乐文件,怎么用python播放呢?我们没有必要先把mp3文件下载到,又自己实现一个播放器。即使利用已有的模块或库都显得过于麻烦。linux如此多基于命令行的流媒体播放器,为什么不直接拿来用?比如我经常使用的mplayer。

使用mplayer:mplayer http://mr3.douban.com/201212101049/fbc67748d2c7791b86653220b2ccbd08/view/song/small/p1472407.mp3,一条命令就可以播放在线的音乐。然后,用python的subprocess模块调用即可。

至此已经可以写出一个最简单的douban.fm播放器:

httpCOnnection= httplib.HTTPConnection('douban.fm')
httpConnection.request('GET', '/j/mine/playlist?type=n&channel=0')
song = json.loads(httpConnection.getresponse().read())['song']
subprocess.call(['mplayer', song[0]['url']])

激动人心的是,这一功能的实现只用了4行代码。

Ubuntu桌面通知

统一的桌面通知是很有意义的(想想windows下混乱的弹窗吧),从OS X v10.8 “Mountain Lion"开始,Mac开始统一Notification Center,与此同时各linux桌面也在完善各自的通知系统。

ubuntu unity拥有自己的桌面通知接口,打开~/.bashrc,可以发现有这样一条命令别名:

alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'

在shell中输入命令:alert "test",可以看到如下效果:

alert是别名,核心命令是notify-send,通过man notify-send,我们可以查看其用法。

ubuntu下播放器开启notify插件后,每次切歌都会发出一个桌面提示:

这是一个很酷的功能,那么如何实现?

仔细想想的话并不难,图片可以由song[0]['picture']下载,然后构造命令notify-send -i pictrue_path ['title'] ['artist'] ['albumtitle']即可。其中涉及到图片文件的下载保存,可以用httplib+文件读写来完成,实际中我用的是wget。

用python来实现就是:

picture = 'images/' + song[0]['picture'].split('/')[4]

# 下载专辑封面
if not os.path.exists(picture):
    subprocess.call([
        'wget',
        '-P',
        'images',
        song[0]['picture']])

# 发送桌面通知
subprocess.call([
    'notify-send',
    '-i',
    os.getcwd() + '/' + picture,
    song[0]['title'],
    song[0]['artist'] + '\n' + song[0]['albumtitle']])

获取图片名时小小的hack了一下,song[0]['picture'].split('/')[4] 这句用来获取url中的图片名,当然,这并不是一个很好的方法。

小结

最后,结合前面的播放代码,已经算是基本完成了,虽然没有实现全局热键控制、登录,但已经可以使用了。

完整的代码:

 1 #!/usr/bin/python
 2 # coding: utf-8
 3 
 4 import httplib
 5 import json
 6 import os
 7 import sys
 8 import subprocess
 9 import time
10 
11 reload(sys)
12 sys.setdefaultencoding('utf-8')
13 
14 while True:
15     # 获取播放列表
16     httpCOnnection= httplib.HTTPConnection('douban.fm')
17     httpConnection.request('GET', '/j/mine/playlist?type=n&channel=0')
18     sOng= json.loads(httpConnection.getresponse().read())['song']
19 
20     picture = 'images/' + song[0]['picture'].split('/')[4]
21 
22     # 下载专辑封面
23     if not os.path.exists(picture):
24         subprocess.call([
25             'wget',
26             '-P',
27             'images',
28             song[0]['picture']])
29 
30     # 发送桌面通知
31     subprocess.call([
32         'notify-send',
33         '-i',
34         os.getcwd() + '/' + picture,
35         song[0]['title'],
36         song[0]['artist'] + '\n' + song[0]['albumtitle']])
37 
38     # 播放
39     player = subprocess.Popen(['mplayer', song[0]['url']])
40     time.sleep(song[0]['length'])
41     player.kill()

 


推荐阅读
  • 本文探讨了领域驱动设计(DDD)的核心概念、应用场景及其实现方式,详细介绍了其在企业级软件开发中的优势和挑战。通过对比事务脚本与领域模型,展示了DDD如何提升系统的可维护性和扩展性。 ... [详细]
  • ASP.NET MVC中Area机制的实现与优化
    本文探讨了在ASP.NET MVC框架中,如何通过Area机制有效地组织和管理大规模应用程序的不同功能模块。通过合理的文件夹结构和命名规则,开发人员可以更高效地管理和扩展项目。 ... [详细]
  • MySQL 数据库迁移指南:从本地到远程及磁盘间迁移
    本文详细介绍了如何在不同场景下进行 MySQL 数据库的迁移,包括从一个硬盘迁移到另一个硬盘、从一台计算机迁移到另一台计算机,以及解决迁移过程中可能遇到的问题。 ... [详细]
  • 本教程涵盖OpenGL基础操作及直线光栅化技术,包括点的绘制、简单图形绘制、直线绘制以及DDA和中点画线算法。通过逐步实践,帮助读者掌握OpenGL的基本使用方法。 ... [详细]
  • 本文详细记录了在银河麒麟操作系统和龙芯架构上使用 Qt 5.15.2 进行项目打包时遇到的问题及解决方案,特别关注于 linuxdeployqt 工具的应用。 ... [详细]
  • 根据最新发布的《互联网人才趋势报告》,尽管大量IT从业者已转向Python开发,但随着人工智能和大数据领域的迅猛发展,仍存在巨大的人才缺口。本文将详细介绍如何使用Python编写一个简单的爬虫程序,并提供完整的代码示例。 ... [详细]
  • 本文介绍如何使用Python进行文本处理,包括分词和生成词云图。通过整合多个文本文件、去除停用词并生成词云图,展示文本数据的可视化分析方法。 ... [详细]
  • 本文详细介绍了Python中文件的基本操作,包括打开、读取、写入和关闭文件的方法,并通过实例展示了如何将Excel文件转换为CSV文件以及进一步转换为HTML文件。此外,还涉及了成绩等级替换的具体实现。 ... [详细]
  • 基于KVM的SRIOV直通配置及性能测试
    SRIOV介绍、VF直通配置,以及包转发率性能测试小慢哥的原创文章,欢迎转载目录?1.SRIOV介绍?2.环境说明?3.开启SRIOV?4.生成VF?5.VF ... [详细]
  • 深入探讨CPU虚拟化与KVM内存管理
    本文详细介绍了现代服务器架构中的CPU虚拟化技术,包括SMP、NUMA和MPP三种多处理器结构,并深入探讨了KVM的内存虚拟化机制。通过对比不同架构的特点和应用场景,帮助读者理解如何选择最适合的架构以优化性能。 ... [详细]
  • 本文探讨了如何在 PHP 的 Eloquent ORM 中实现数据表之间的关联查询,并通过具体示例详细解释了如何将关联数据嵌入到查询结果中。这不仅提高了数据查询的效率,还简化了代码逻辑。 ... [详细]
  • 本文详细介绍了Linux系统中init进程的作用及其启动过程,解释了运行级别的概念,并提供了调整服务启动顺序的具体步骤和实例。通过了解这些内容,用户可以更好地管理系统的启动流程和服务配置。 ... [详细]
  • 深入解析 Apache Shiro 安全框架架构
    本文详细介绍了 Apache Shiro,一个强大且灵活的开源安全框架。Shiro 专注于简化身份验证、授权、会话管理和加密等复杂的安全操作,使开发者能够更轻松地保护应用程序。其核心目标是提供易于使用和理解的API,同时确保高度的安全性和灵活性。 ... [详细]
  • 微软Exchange服务器遭遇2022年版“千年虫”漏洞
    微软Exchange服务器在新年伊始遭遇了一个类似于‘千年虫’的日期处理漏洞,导致邮件传输受阻。该问题主要影响配置了FIP-FS恶意软件引擎的Exchange 2016和2019版本。 ... [详细]
  • 本文介绍如何在现有网络中部署基于Linux系统的透明防火墙(网桥模式),以实现灵活的时间段控制、流量限制等功能。通过详细的步骤和配置说明,确保内部网络的安全性和稳定性。 ... [详细]
author-avatar
神秘人-2012
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有