Web Plugin#
The web plugin is a very basic alternative interface to beets that
supplements the CLI. It can't do much right now, and the interface is a little
clunky, but you can use it to query and browse your music and---in browsers that
support HTML5 Audio---you can even play music.
While it's not meant to replace the CLI, a graphical interface has a number of advantages in certain situations. For example, when editing a tag, a natural CLI makes you retype the whole thing---common GUI conventions can be used to just edit the part of the tag you want to change. A graphical interface could also drastically increase the number of people who can use beets.
Install#
To use the web plugin, first enable it in your configuration (see
Using Plugins). Then, install beets with web extra
pip install "beets[web]"
Run the Server#
Then just type beet web to start the server and go to
http://localhost:8337/. This is what it looks like:
You can also specify the hostname and port number used by the Web server. These
can be specified on the command line or in the [web] section of your
configuration file.
On the command line, use beet web [HOSTNAME] [PORT]. Or the configuration
options below.
Usage#
Type queries into the little search box. Double-click a track to play it with HTML5 Audio.
Configuration#
To configure the plugin, make a web: section in your configuration file. The
available options are:
host: The server hostname. Set this to 0.0.0.0 to bind to all interfaces. Default: Bind to 127.0.0.1.
port: The server port. Default: 8337.
cors: The CORS allowed origin (see Cross-Origin Resource Sharing (CORS), below). Default: CORS is disabled.
cors_supports_credentials: Support credentials when using CORS (see Cross-Origin Resource Sharing (CORS), below). Default: CORS_SUPPORTS_CREDENTIALS is disabled.
reverse_proxy: If true, enable reverse proxy support (see Reverse Proxy Support, below). Default: false.
include_paths: If true, includes paths in item objects. Default: false.
readonly: If true, DELETE and PATCH operations are not allowed. Only GET is permitted. Default: true.
Implementation#
The Web backend is built using a simple REST+JSON API with the excellent Flask library. The frontend is a single-page application written with Backbone.js. This allows future non-Web clients to use the same backend API.
Eventually, to make the Web player really viable, we should use a Flash fallback for unsupported formats/browsers. There are a number of options for this:
Cross-Origin Resource Sharing (CORS)#
The web plugin's API can be used as a backend for an in-browser client. By
default, browsers will only allow access from clients running on the same server
as the API. (You will get an arcane error about XMLHttpRequest otherwise.) A
technology called CORS lets you relax this restriction.
If you want to use an in-browser client hosted elsewhere (or running from a
different server on your machine), set the cors configuration option to the
"origin" (protocol, host, and optional port number) where the client is served.
Or set it to '*' to enable access from all origins. Note that there are
security implications if you set the origin to '*', so please research this
before using it.
If the web server is behind a proxy that uses credentials, you might want to
set the cors_supports_credentials configuration option to true to let
in-browser clients log in.
For example:
web:
host: 0.0.0.0
cors: 'http://example.com'
Reverse Proxy Support#
When the server is running behind a reverse proxy, you can tell the plugin to
respect forwarded headers. Specifically, this can help when you host the plugin
at a base URL other than the root / or when you use the proxy to handle
secure connections. Enable the reverse_proxy configuration option if you do
this.
Technically, this option lets the proxy provide X-Script-Name and
X-Scheme HTTP headers to control the plugin's the SCRIPT_NAME and its
wsgi.url_scheme parameter.
Here's a sample Nginx configuration that serves the web plugin under the /beets directory:
location /beets {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Scheme $scheme;
proxy_set_header X-Script-Name /beets;
}
JSON API#
GET /item/#
Responds with a list of all tracks in the beets library.
{
"items": [
{
"id": 6,
"title": "A Song",
...
}, {
"id": 12,
"title": "Another Song",
...
}
...
]
}
GET /item/6#
Looks for an item with id 6 in the beets library and responds with its JSON representation.
{
"id": 6,
"title": "A Song",
...
}
If there is no item with that id responds with a 404 status code.
DELETE /item/6#
Removes the item with id 6 from the beets library. If the ?delete query string is included, the matching file will be deleted from disk.
Only allowed if readonly configuration option is set to no.
PATCH /item/6#
Updates the item with id 6 and write the changes to the music file. The body should be a JSON object containing the changes to the object.
Returns the updated JSON representation.
{
"id": 6,
"title": "A Song",
...
}
Only allowed if readonly configuration option is set to no.
GET /item/6,12,13#
Response with a list of tracks with the ids 6, 12 and 13. The format of the response is the same as for GET /item/. It is not guaranteed that the response includes all the items requested. If a track is not found it is silently dropped from the response.
This endpoint also supports DELETE and PATCH methods as above, to operate on all items of the list.
GET /item/path/...#
Look for an item at the given absolute path on the server. If it corresponds to
a track, return the track in the same format as /item/*.
If the server runs UNIX, you'll need to include an extra leading slash:
http://localhost:8337/item/path//Users/beets/Music/Foo/Bar/Baz.mp3
GET /item/query/querystring#
Returns a list of tracks matching the query. The querystring must be a valid query as described in Queries.
{
"results": [
{ "id" : 6, "title": "A Song" },
{ "id" : 12, "title": "Another Song" }
]
}
Path elements are joined as parts of a query. For example,
/item/query/foo/bar will be converted to the query foo,bar. To specify
literal path separators in a query, use a backslash instead of a slash.
This endpoint also supports DELETE and PATCH methods as above, to operate on all items returned by the query.
GET /item/6/file#
Sends the media file for the track. If the item or its corresponding file do not exist a 404 status code is returned.
Albums#
For albums, the following endpoints are provided:
GET /album/GET /album/5GET /album/5/artDELETE /album/5GET /album/5,7DELETE /album/5,7GET /album/query/querystringDELETE /album/query/querystring
The interface and response format is similar to the item API, except replacing
the encapsulation key "items" with "albums" when requesting /album/
or /album/5,7. In addition we can request the cover art of an album with
GET /album/5/art. You can also add the '?expand' flag to get the individual
items of an album.
DELETE is only allowed if readonly configuration option is set to
no.
GET /stats#
Responds with the number of tracks and albums in the database.
{
"items": 5,
"albums": 3
}