Shiva – 不仅仅是音乐收藏的 RESTful API

音乐对我来说不仅仅是日常生活的一部分,更是必不可少的一部分。它帮助我集中注意力,改善我的情绪,分散我的注意力和/或帮助我放松。这对大多数(如果不是全部)人来说都是如此。缺乏音乐或选择错误的曲调会产生完全相反的效果,它对我们的感受有很大的影响。它还在塑造我们的身份方面发挥着关键作用。音乐,就像大多数(如果不是全部)类型的文化一样,不是附属品,不是我们可以选择忽略的东西,而是我们作为人类的需求。

互联网已成为文化传播有史以来最有效的媒介。如今,比以往任何时候都更容易获得种类繁多的文化,来自世界任何地方。同时,您可以立即将您的音乐传播到全世界,只需在一个您可以找到的众多音乐发行网站之一注册即可。正如“旅行开阔视野”一样,音乐分享丰富了文化,并且由于互联网,文化如今比以往任何时候都更加活跃。

不久前,唱片公司是判断什么是好音乐(以他们的标准)和什么不是好音乐的评判者。他们控制着唯一的全球规模分销渠道,因此要使用它,您需要与他们达成协议,这通常意味着放弃您文化作品的大部分权利。创建和维护这样一个渠道既不容易也不便宜,他们提供的服务是必要的,即使他们的目标不是传播文化而是盈利(像每个公司一样),但双方,行业和社会都从中受益。

时代变了,这种模式现在已经过时了;国王死了,所以有一些公司正在争夺这个空缺。商业模式也发生了变化。现在不仅仅是音乐——还包括限制对它的访问并收集(和出售)关于听众的私人信息。换句话说,DRM 和隐私。这就是 Shiva 发挥作用的地方。

什么是 Shiva?

从技术上讲,Shiva 是您音乐收藏的 RESTful API。它索引您的音乐并公开包含文件元数据的 API,以便您可以对其执行查询并根据您的意愿对其进行组织。

然而,在更高层次上,Shiva 旨在成为流行音乐服务的免费(如自由和啤酒)替代方案。它的诞生是为了将对音乐和隐私的控制权交还给用户,保护他们免受行业对控制的痴迷。

它并非旨在与在线音乐服务直接竞争,而是成为您可以安装和修改以满足您需求的替代方案。您将在您的服务器上拥有音乐。除了您(或您授予权限的人)之外,没有人能够删除文件或修改文件的元数据以在错误时进行更正。当然,所有这些都将可供任何具有互联网连接的设备使用。

您还将拥有一个不受限制的、干净的 RESTful 音乐 API。您可以授予朋友访问权限并让他们使用该服务,或者,如果他们有自己的 Shiva 实例,则让两个服务器相互通信并透明地共享音乐。

总之,Shiva 是一个用于共享音乐的分布式社交网络。

您自己的音乐服务器

Shiva-Server 是索引您的音乐并公开 RESTful API 的组件。以下是可用的资源

  • /artists
    • /artists/shows
  • /albums
  • /tracks
    • /tracks/lyrics

它使用 SQLAlchemy 作为 ORM 和 Flask 用于 HTTP 通信,是用 Python 编写的。

索引您的音乐

安装过程非常简单。README 文件中有一个非常完整的指南,但我会在这里对其进行总结

  • 获取源代码
  • 从 requirements.pip 文件安装依赖项
  • 将 /shiva/config/local.py.example 复制到 /shiva/config/local.py
  • 编辑它并配置要扫描的目录
  • 创建数据库(默认情况下为 sqlite)
  • 运行索引器
  • 运行开发服务器

有关任何步骤的详细信息,请查看文档。

音乐被索引后,所有元数据都存储在数据库中并从中查询。文件仅由文件服务器访问以进行流式传输。歌词在首次请求时被抓取,然后缓存。鉴于演出资源的变化性质,这是唯一一个未被缓存的资源;而是每次都进行查询。在撰写本文时,它仅使用一个来源,即 BandsInTown API

服务器运行后,您就可以开始使用 Shiva 了。指向某个资源,例如 /artists,即可查看其运行情况。

抓取歌词

如前所述,歌词会被抓取,您可以为包含所需歌词的特定网站创建自己的抓取器。您只需要在 /shiva/lyrics 目录中创建一个包含继承自 LyricScraper 的类的 Python 文件即可。以下模板清楚地说明了它有多么容易。假设我们有一个文件 /shiva/lyrics/mylyrics.py

shiva.lyrics import LyricScraper

class MyLyricsScraper(LyricScraper):
    “““ Fetches lyrics from mylyrics.com ”””

    def fetch(self, artist, title):
        # Magic happens here

        if not lyrics:
            return False

        self.lyrics = lyrics
        self.source = lyrics_url

        return True

之后,您需要将全新的抓取器添加到本地 .py 配置文件中的 scrapers 列表中

SCRAPERS = {
    ‘lyrics’: (
        ‘mylyrics.MyLyricScraper’,
    )
}

Shiva 将实例化您的抓取器并调用 fetch() 方法。如果它返回 True,则它将继续在 lyrics 属性中查找歌词,以及从 source 属性中抓取歌词的 URL

if scraper.fetch():
    lyrics = Lyrics(text=scraper.lyrics, source=scraper.source,
                    track=track)
    g.db.session.add(lyrics)
    g.db.session.commit()

    return lyrics

查看现有抓取器以获取实际示例。

仅当您请求特定曲目时才会获取歌词,而不是检索多个曲目时。这样做的原因是每个曲目的歌词可能需要两个或多个请求,并且我们不希望在检索艺术家的唱片目录时对网站进行 DoS 攻击。那不好。

设置文件服务器

开发服务器顾名思义,不应用于生产环境。事实上,这几乎是不可能的,因为它一次只能服务一个请求,并且音频元素将在文件播放期间保持连接打开,因此完全阻塞了 API。

Shiva 提供了一种将文件服务委托给专用服务器的方法。为此,您必须编辑 /shiva/config/local.py 文件,并编辑 MEDIA_DIRS 设置。此选项需要一个 MediaDir 对象元组,该元组提供定义要扫描的目录和通过套接字为文件提供服务的机制

MediaDir(‘/srv/music’, url=’http://localhost:8080’)

这样,您的应用程序在哪个套接字中运行就无关紧要了,/src/music 目录中的文件将通过 url 属性中定义的 URL 提供服务。此对象还允许定义要扫描的子目录。例如

MediaDir(‘/srv/music’, dirs=(‘/pop’, ‘/rock’), url=’http://localhost:8080’)

在这种情况下,只会扫描 /srv/music/pop 和 /srv/music/rock 目录。您可以根据需要定义任意数量的 MediaDir 对象。假设您有文件 /srv/music/rock/nofx-dinosaurs_will_die.mp3,一旦到位,该曲目的 download_uri 属性将为

{
    "slug": "dinosaurs-will-die",
    "title": "Dinosaurs Will Die",
    "uri": "/track/510",
    "id": 510,
    "stream_uri": "http://localhost:8080/nofx-dinosaurs_will_die.mp3"
}

您自己的音乐播放器

一旦您的音乐被扫描并且 API 运行,您就需要一个使用这些服务并播放您的音乐的客户端,例如 Shiva-Client。该客户端作为使用 AngularJS 和 HTML5 技术(如音频和拖放)的单页应用程序构建,将允许您浏览您的目录,将文件添加到播放列表并播放它们。

由于同源策略,您将需要一个充当 Web 应用程序和 API 之间代理的服务器。为此,您将在存储库中找到一个 server.py 文件,它将为您执行此操作。此文件唯一的依赖项是 Flask,但我假设您已经安装了它。现在只需执行它

python server.py

这将在 http://localhost:9001/ 上运行服务器

访问该 URI 并检查服务器输出,您将不仅看到应用程序所需的媒体(如图像和 JavaScript 文件),还看到 /api/artists 调用。这就是代理。对 /api/ 的任何调用都将由服务器重定向到 http://localhost:9002/

如果您打开一个控制台(如 Firebug),您将在全局命名空间中看到一个 Shiva 对象。在其内部,您将找到两个主要属性,Player 和 Playlist。这些对象封装了排队和播放音乐的所有逻辑。Player 仅保存当前曲目,充当 HTML5 的 Audio 元素的包装器。一开始可能看起来不自然的是,通常您不会与 Player 交互,而是与 Playlist 交互,后者充当外观,因为它知道所有曲目并指示 Player 加载和播放下一首曲目。

这些对象的源代码位于 js/controllers.js 文件中。您还将在其中找到 AngularJS 控制器,这些控制器执行对 API 的实际调用。它仅包含两个调用,一个用于获取艺术家列表,另一个用于获取艺术家的唱片目录。检查代码,非常简单。

因此,一旦曲目被添加到播放列表中,您就可以执行以下操作,例如播放它

Shiva.Playlist.play()

停止它

Shiva.Playlist.stop()

或跳过曲目

Shiva.Playlist.next()

进行了一些性能优化,以尽可能降低处理量。例如,您将在播放音乐时看到一个进度条,该进度条仅在需要显示时才会更新。事件将在不需要时被删除,以避免对不可见元素进行任何不必要的 DOM 操作

Shiva.Player.audio.removeEventListener('timeupdate',    Shiva.Player.audio.timeUpdateHandler, false);

现在和未来

在撰写本文时,Shiva 处于可用状态并提供了核心功能,但它仍然很年轻并且缺少一些重要功能。这也是本文没有深入研究代码的原因,因为它将迅速发生变化。要了解当前状态,请查看文档

如果您想做出贡献,有很多方法可以帮助该项目。首先,为服务器和客户端都创建分支,使用它们并将您的改进发送回上游。

请求功能。如果您认为“看起来不错,但我不会使用它”,请写下原因并发送这些想法,理想情况下还有一些关于如何解决这些想法的建议。缺乏功能的清单很长;您的帮助对于确定优先级至关重要。

但最重要的是;构建您自己的客户端。您知道您喜欢自己喜欢的音乐播放器的哪些功能,也知道哪些功能很糟糕。为现有客户端创建分支并进行修改,或从头开始创建自己的客户端,为音乐播放器的旧世界带来新的想法。为 API 提供新的和创造性的用途。

有很多工作要做,在许多不同的方面。未来的一些计划是

  • Shiva-jslib:一个易于使用的 JavaScript 库,封装了 API 调用,因此您可以专注于构建 GUI 并忘记协议。
  • Shiva 到 Shiva 通信:让两个(或更多)Shiva 实例相互通信,以允许在服务器之间透明地共享音乐。
  • Shiva-FXOS:Firefox OS 的 Shiva 客户端。

以及您能想到的任何其他事情。编写代码,发送想法,编写您的客户端。

快乐地黑客攻击!

关于 Alvaro Mouriño

Alvaro 是一位来自乌拉圭的自由软件黑客活动家,目前居住在柏林。多年来一直作为活跃成员参与自由软件团体,组织了许多当地活动并在南锥体地区参加了许多其他活动。

Alvaro Mouriño 的更多文章…

关于 Robert Nyman [荣誉编辑]

Mozilla Hacks 的技术布道师和编辑。发表演讲和博客文章,内容涉及 HTML5、JavaScript 和开放网络。Robert 坚定地相信 HTML5 和开放网络,自 1999 年以来一直从事 Web 前端开发工作——在瑞典和纽约市。他还在 http://robertnyman.com 上定期发表博客文章,并且喜欢旅行和结识新朋友。

Robert Nyman [荣誉编辑] 的更多文章…


26 条评论

  1. ant cosentino

    太棒了。

    2013 年 3 月 11 日 上午 10:31

  2. mikekij

    看起来真的很酷。有演示网站吗?

    2013 年 3 月 11 日 上午 11:37

    1. Alvaro Mouriño

      还没有,至少目前还没有。但是,如果您(或任何人)想设置一个,请告诉我,我会将其添加到文档中。

      2013 年 3 月 13 日 上午 11:04

  3. Kai

    不错!

    顺便说一句,Shiva-Client 链接已损坏。

    2013 年 3 月 11 日 上午 12:22

    1. Alvaro Mouriño

      谢谢。已修复。

      2013 年 3 月 14 日 上午 02:22

  4. R. Kyle Murphy

    我喜欢这个概念,尽管我对 Python 并不是特别感兴趣。尽管如此,只要 API 有文档,就可以用任何东西创建服务器/客户端(REST 的优点),所以即使我不特别喜欢 Python,我也可以用任何我想要的语言编写一个符合 Shiva 标准的服务器。一旦它成熟并且 API 稳定一些,我可能会这样做。

    2013 年 3 月 11 日 下午 01:36

    1. Alvaro Mouriño

      这正是重点所在。Shiva 最关注的不是实际的软件,而是干净的 API。我使用了 Python,但只要您坚持使用该协议,就可以用任何语言创建服务器和客户端。

      您说得对:这就是 REST 的优点。

      但您说得对,API 仍在增长和开发中。如果您启动自己的服务器,请注意它可能会发生变化。

      2013 年 3 月 13 日 上午 11:24

  5. ucuzmuzikaleti

    看起来很棒..

    2013 年 3 月 11 日 下午 02:17

  6. oneknlr

    太棒了!

    我玩过这个想法一段时间了,几乎完全是为了做到这一点 :) 当我回家并使用 Shiva 时,我将尝试弄清楚

    – 是否支持多种流派(大多数播放器/DJ 软件不支持,这使得我很难按照我想要的方式标记我的音乐)
    – 是否有将搜索引擎(如 Elasticsearch)加入愿望清单的计划?
    – 它可以与某种 DJ 软件集成吗?(因为我想用它来构建我在现场播放的音乐结构)

    感谢您开源它 :)(虽然您没有提到许可证,但我认为它应该是宽松许可的)

    2013年3月11日 14:59

    1. Alvaro Mouriño

      . 许可证是 MIT。
      . Shiva 仅读取每个文件的标题、专辑和艺术家信息。完全不考虑流派。
      . 我还没有决定一个好的 API 来支持搜索,但这绝对在愿望清单中。
      . 你所说的“集成”是什么意思?我认为问题在于 DJ 软件是否允许与 REST API 集成。

      服务器和客户端位于不同存储库的原因之一是为了确保服务器与任何客户端都没有依赖关系。不能知道它们的存在。客户端负责与 REST API 集成。

      2013年3月13日 14:33

  7. TheSisb

    我一直在寻找这样的东西。谢谢!希望在不久的将来能够贡献代码。

    2013年3月11日 18:10

  8. Dimitris

    感谢分享!
    对于非程序员来说,似乎足够简单。
    :-)

    2013年3月11日 23:35

  9. h00dy

    开发 iOS 应用超过两年,差点加入 Spotify 团队;)

    我非常乐意为它创建一个“应用程序”。

    如果您有兴趣,请给我发送邮件;)

    2013年3月12日 02:38

    1. Alvaro Mouriño

      是的,请继续。当您完成一些工作时,请告诉我,以便我将其添加到客户端列表中。如果您需要帮助,请随时与我联系。

      谢谢!

      2013年3月13日 11:45

  10. Alex

    哇!太棒了!
    干得好!

    2013年3月12日 07:21

  11. jasonxu

    太棒了~~

    2013年3月12日 19:46

  12. Freso

    您不使用 MusicBrainz 标识符的原因是什么?MBID 可以直接用于 BBC、Last.fm 和其他一些服务(例如 Freebase(以及由此扩展到 YouTube 等)),更不用说您可以使用 MBID 获取 MusicBrainz 上关于实体的数据(包括到更多外部来源的链接(AllMusic、VIAF/WorldCat、Amazon、封面艺术档案等))。

    2013年3月13日 10:03

    1. Alvaro Mouriño

      目前,不集成它的唯一原因是:简单性。

      鉴于我已经集成了 Last.FM,以及其他领域需要完成的工作量,添加 MBID 本身并没有带来额外的价值。至少在这个阶段是这样。

      但这并不意味着它不会被添加,我只是需要优先考虑。

      2013年3月13日 14:08

  13. M7700

    如果整个 archive.org 音乐收藏都可以在 Shiva API 下访问,那就太棒了。

    2013年3月13日 20:56

  14. Agresvig

    看起来很棒,迫不及待地想尝试一下!
    它在移动设备上的外观/工作方式如何?

    2013年3月14日 01:54

    1. Alvaro Mouriño

      客户端在移动设备上的外观不是很好。目标只是做一个概念验证,一个有效的 Web 客户端来展示这个想法,但它仍然需要更多工作。

      不过,您可以随意调整或移植它。

      2013年3月14日 02:21

  15. silopolis

    Flask 为我们其余的耳朵提供动力!
    令人惊叹的作品,以及更具潜力的项目。
    继续努力
    最好的祝愿

    2013年3月14日 03:43

  16. Freso

    嗯。如果您只是使用简单的递增整数来标识,那么您如何区分例如 John Williams 与例如 John WilliamsJohn WilliamsJohn WilliamsJohn Williams

    2013年3月14日 07:44

  17. Tom

    我刚刚让它工作起来,这太棒了!

    2013年3月14日 15:08

  18. Rudolf

    只想提一下,一些 GNU/Linux 用户长期以来都知道使用服务器管理其音乐收藏的功能。有一个叫做 MPD(音乐播放守护进程)的东西,它有命令行客户端、Qt 和 GTK 客户端,当然还有使用 AJAX 的 Web 客户端。

    如果能看到一个使用与 Shiva 相同 RESTful 接口的 MPD 插件,以便 Shiva 的 Web 接口可以与 MPD 一起使用,那就很酷了!我尤其喜欢歌词收藏,非常实用。

    2013年3月18日 09:13

  19. Sonicjar Music

    @Rudolf – 是的,歌词和音乐收藏的界面非常有用,如果我们可以找到某种方法将它们与语音识别功能自动同步,那就更好了!!

    2013年4月2日 09:40

本文的评论已关闭。