Build Status

node-libspotify

Node bindings for the libspotify C library

This is still very alpha, but you can already play around I suppose

Install & test

Please note that you must have the libspotify library installed on your system you can get it from here.

You must provide your own spotify application key, because I'm not giving mine away :] You also must provide valid credentials for a spotify account.

Once you cloned the repository run npm install then test the module with npm test.

Main objectives

As there are already a number of spotify bindings or modules for the REST API, the main goal of this module is not to give access to the artist and tracks catalog. It's main purpose is to allow for playback of the tracks. The idea is to expose a Player object in which the user can load tracks, play them, and get decompressed audio data from it (as provided by the libspotify C library).

What the user can do with the audio stream is up to him/her. As it is raw PCM data, it is easy to pipe to some kind of encoder (like gstreamer) in order to broadcast music or stream it to a web user (as long as it complies with the Spotify terms of service ;).

The user can also choose to play the song locally with a node module like speaker or pipe the audio data to another process like aplay.

The main goal is now achieved. Audio data is exposed as the Player object which behaves like a readable stream.

Snippet

Here is a code snippet of how to play a track from spotify

var sp = require('../lib/libspotify');
var cred = require('../spotify_key/passwd');
var spawn = require('child_process').spawn;

var session = new sp.Session({
    applicationKey: __dirname + '/../spotify_key/spotify_appkey.key'
});
session.login(cred.login, cred.password);
session.once('login', function(err) {
    if(err) this.emit('error', err);

    var search = new sp.Search('artist:"rick astley" track:"never gonna give you up"');
    search.trackCount = 1; // we're only interested in the first result;
    search.execute();
    search.once('ready', function() {
        if(!search.tracks.length) {
            console.error('there is no track to play :[');
            session.logout();
        }

        var track = search.tracks[0];
        var player = session.getPlayer();
        player.load(track);
        player.play();

        // linux
        var play = spawn('aplay', ['-c', 2, '-f', 'S16_LE', '-r', '44100']);
        // osx with `brew install sox`
        var play = spawn('play', ['-r', 44100, '-b', 16, '-L', '-c', 2, '-e', 'signed-integer', '-t', 'raw', '-']);

        player.pipe(play.stdin);

        console.error('playing track. end in %s', track.humanDuration);
        player.on('data', function(buffer) {
            // buffer.length
            // buffer.rate
            // buffer.channels
            // 16bit samples
        });
        player.once('track-end', function() {
            console.error('track ended');
            player.stop();
            session.close();
        });
    });
});

TODO

  • Bind to the rest of the API...

Credits

Thanks to IainCole for his help on the playlist subsystem. Thanks to LinusU and swissmanu for their help on album cover retreivals



构建状态data-canonical-src

node-libspotify

libspotify C库的节点绑定

这仍然是非常alpha的,但是你可以先玩玩,假设

安装&测试

请注意,您必须在系统上安装libspotify库 您可以从此处获取。

您必须提供自己的识别应用程序密钥,因为我没有给我提供:] 您也必须提供有效的凭证来进行识别帐户。

一旦您克隆了存储库,运行 npm install ,然后使用 npm test 测试该模块。

主要目标

由于已经有许多针对REST API的特定绑定或模块,主要目标是 的这个模块不是给予艺术家和跟踪目录的访问。它的主要目的是 以允许播放曲目。这个想法是公开一个用户的 Player 对象 可以加载轨道,播放它们,并从中获取解压缩的音频数据(由libspotify C库提供)。

用户可以使用音频流做什么取决于他/她。由于是原始的PCM数据,因此易于管理 某种编码器(如gstreamer)为了播放音乐或将其流式传输给网络用户(只要符合要求) 与Spotify服务条款;)。

用户还可以选择使用节点模块本地播放歌曲,如演讲者 或将音频数据导管到另一个进程,如 aplay

主要目标是实现。音频数据被公开为Player对象,其行为像可读流。

片段

这是一个如何从spotify

播放曲目的代码片段
var sp = require('../lib/libspotify');
var cred = require('../spotify_key/passwd');
var spawn = require('child_process').spawn;

var session = new sp.Session({ applicationKey: __dirname + '/../spotify_key/spotify_appkey.key' }); session.login(cred.login, cred.password); session.once('login', function(err) { if(err) this.emit('error', err);

<span class="pl-k">var</span> search <span class="pl-k">=</span> <span class="pl-k">new</span> <span class="pl-en">sp.Search</span>(<span class="pl-s"><span class="pl-pds">&#39;</span>artist:&#34;rick astley&#34; track:&#34;never gonna give you up&#34;<span class="pl-pds">&#39;</span></span>);
<span class="pl-smi">search</span>.<span class="pl-smi">trackCount</span> <span class="pl-k">=</span> <span class="pl-c1">1</span>; <span class="pl-c"><span class="pl-c">//</span> we&#39;re only interested in the first result;</span>
<span class="pl-smi">search</span>.<span class="pl-en">execute</span>();
<span class="pl-smi">search</span>.<span class="pl-en">once</span>(<span class="pl-s"><span class="pl-pds">&#39;</span>ready<span class="pl-pds">&#39;</span></span>, <span class="pl-k">function</span>() {
    <span class="pl-k">if</span>(<span class="pl-k">!</span><span class="pl-smi">search</span>.<span class="pl-smi">tracks</span>.<span class="pl-c1">length</span>) {
        <span class="pl-en">console</span>.<span class="pl-c1">error</span>(<span class="pl-s"><span class="pl-pds">&#39;</span>there is no track to play :[<span class="pl-pds">&#39;</span></span>);
        <span class="pl-smi">session</span>.<span class="pl-en">logout</span>();
    }

    <span class="pl-k">var</span> track <span class="pl-k">=</span> <span class="pl-smi">search</span>.<span class="pl-smi">tracks</span>[<span class="pl-c1">0</span>];
    <span class="pl-k">var</span> player <span class="pl-k">=</span> <span class="pl-smi">session</span>.<span class="pl-en">getPlayer</span>();
    <span class="pl-smi">player</span>.<span class="pl-c1">load</span>(track);
    <span class="pl-smi">player</span>.<span class="pl-c1">play</span>();

    <span class="pl-c"><span class="pl-c">//</span> linux</span>
    <span class="pl-k">var</span> play <span class="pl-k">=</span> <span class="pl-en">spawn</span>(<span class="pl-s"><span class="pl-pds">&#39;</span>aplay<span class="pl-pds">&#39;</span></span>, [<span class="pl-s"><span class="pl-pds">&#39;</span>-c<span class="pl-pds">&#39;</span></span>, <span class="pl-c1">2</span>, <span class="pl-s"><span class="pl-pds">&#39;</span>-f<span class="pl-pds">&#39;</span></span>, <span class="pl-s"><span class="pl-pds">&#39;</span>S16_LE<span class="pl-pds">&#39;</span></span>, <span class="pl-s"><span class="pl-pds">&#39;</span>-r<span class="pl-pds">&#39;</span></span>, <span class="pl-s"><span class="pl-pds">&#39;</span>44100<span class="pl-pds">&#39;</span></span>]);
    <span class="pl-c"><span class="pl-c">//</span> osx with `brew install sox`</span>
    <span class="pl-k">var</span> play <span class="pl-k">=</span> <span class="pl-en">spawn</span>(<span class="pl-s"><span class="pl-pds">&#39;</span>play<span class="pl-pds">&#39;</span></span>, [<span class="pl-s"><span class="pl-pds">&#39;</span>-r<span class="pl-pds">&#39;</span></span>, <span class="pl-c1">44100</span>, <span class="pl-s"><span class="pl-pds">&#39;</span>-b<span class="pl-pds">&#39;</span></span>, <span class="pl-c1">16</span>, <span class="pl-s"><span class="pl-pds">&#39;</span>-L<span class="pl-pds">&#39;</span></span>, <span class="pl-s"><span class="pl-pds">&#39;</span>-c<span class="pl-pds">&#39;</span></span>, <span class="pl-c1">2</span>, <span class="pl-s"><span class="pl-pds">&#39;</span>-e<span class="pl-pds">&#39;</span></span>, <span class="pl-s"><span class="pl-pds">&#39;</span>signed-integer<span class="pl-pds">&#39;</span></span>, <span class="pl-s"><span class="pl-pds">&#39;</span>-t<span class="pl-pds">&#39;</span></span>, <span class="pl-s"><span class="pl-pds">&#39;</span>raw<span class="pl-pds">&#39;</span></span>, <span class="pl-s"><span class="pl-pds">&#39;</span>-<span class="pl-pds">&#39;</span></span>]);

    <span class="pl-smi">player</span>.<span class="pl-en">pipe</span>(<span class="pl-smi">play</span>.<span class="pl-smi">stdin</span>);

    <span class="pl-en">console</span>.<span class="pl-c1">error</span>(<span class="pl-s"><span class="pl-pds">&#39;</span>playing track. end in %s<span class="pl-pds">&#39;</span></span>, <span class="pl-smi">track</span>.<span class="pl-smi">humanDuration</span>);
    <span class="pl-smi">player</span>.<span class="pl-en">on</span>(<span class="pl-s"><span class="pl-pds">&#39;</span>data<span class="pl-pds">&#39;</span></span>, <span class="pl-k">function</span>(<span class="pl-smi">buffer</span>) {
        <span class="pl-c"><span class="pl-c">//</span> buffer.length</span>
        <span class="pl-c"><span class="pl-c">//</span> buffer.rate</span>
        <span class="pl-c"><span class="pl-c">//</span> buffer.channels</span>
        <span class="pl-c"><span class="pl-c">//</span> 16bit samples</span>
    });
    <span class="pl-smi">player</span>.<span class="pl-en">once</span>(<span class="pl-s"><span class="pl-pds">&#39;</span>track-end<span class="pl-pds">&#39;</span></span>, <span class="pl-k">function</span>() {
        <span class="pl-en">console</span>.<span class="pl-c1">error</span>(<span class="pl-s"><span class="pl-pds">&#39;</span>track ended<span class="pl-pds">&#39;</span></span>);
        <span class="pl-smi">player</span>.<span class="pl-c1">stop</span>();
        <span class="pl-smi">session</span>.<span class="pl-c1">close</span>();
    });
});

});

TODO

  • 绑定到API的其余部分…

Credits

感谢 IainCole 对播放列表子系统的帮助。 感谢 LinusU swissmanu 的相关帮助覆盖检索




相关问题推荐