museria-ms
v0.3.60
Published
Decentralized music storage
Downloads
40
Maintainers
Readme
Museria [alpha]
Museria is a decentralized music storage based on spreadable-ms, storacle-ms and metastocle-ms.
There is an article here with an explanation.
import { Node } from 'museria';
try {
const node = new Node({
port: 4000,
hostname: 'localhost'
});
await node.init();
}
catch(err) {
console.error(err.stack);
process.exit(1);
}
import { Client } from 'museria';
import utils from 'museria/src/utils.js';
try {
const client = new Client({
address: 'localhost:4000'
});
await client.init();
const title = 'Artist - Title';
// Prepare the song tags
await utils.addSongTags('./audio.mp3', {
fullTitle: title,
APIC: './cover.jpg'
});
// Add the song
await client.addSong('./audio.mp3');
// Get the song info
const info = await client.getSong(title);
// Find songs
const songs = await client.findSongs('arti', { limit: 5 });
// Find the artist songs
const artistSongs = await client.findArtistSongs('artist');
// Get the song audio link
const audioLink = await client.getSongAudioLink(title);
// Get the song cover link
const coverLink = await client.getSongCoverLink(title);
// Remove the song
await client.removeSong(title);
}
catch(err) {
console.error(err.stack);
process.exit(1);
}
Browser client
You can also use the client in a browser. Look at the description of the spreadable-ms library. In window you have window.ClientMuseria instead of window.ClientSpreadable. The prepared file name is museria.client.js.
How to use it via the command line
Look at the description of the spreadable-ms library. You only need to change everywhere spreadable-ms word to museria.
How it works
The mechanism of the library is very similar to storacle-ms. The only difference is that the key to the file is the name of the song, not the hash. Also, a unique song is considered not with the full title match, but the percentage of coincidence set in the options.
What are the limitations
Currently only mp3 format is supported. The tags are id3, based on node-id3. TPE1 and TIT2 tags are required to store the song. You can use setter fullTitle as TPE1 - TIT2 when you set the tags using utils. It must be a valid combination for utils.isSongTitle() function. Also, the network may have its own cover size requirements. The number of songs that can be added to one node is configurable as well.
What are the requirements
Look at the storacle-ms requirements and the metastocle-ms requirements.
Moderation and priority
By adding a song, you can indicate whether you moderate it or not. The controlled option is responsible for this. By default, it is false. The moderation mode implies that you take care of the conformity and quality of the song. The file of the corresponding song located in the storage will be replaced with a new one without checks. Adding songs in this mode requires captcha confirmation.
await client.addSong(file, { controlled: true });
You can also specify the priority of your file as -1, 0 or 1. By default, it is 0. If the priority of the new song is higher than the existing one, then it will replace that without checks. If they are equal, then the storage itself will decide which one to choose. If less, then the song in the repository will remain the same. Only the tags, cover and other additional information might be updated in this case. Priority 1 may only be used in moderation mode.
await client.addSong(file, { priority: -1 });
await client.addSong(file, { priority: 1, controlled: true });
Where to use it
1. Wherever songs need to be stored decentralized
For example, we can collect all the music on the planet together in one place, but in a decentralized way with the ability to access it at any time.
2. For own needs
You can use it to store music as you like.
3. Serverless solutions
Since the library is written in javascript, you can receive / send / work with songs in the browser and do not use server code at all. In some cases, it can be very convenient.
Node configuration
When you create an instance of the node you can pass options below. Only specific options of this library are described here, without considering the options of the parent classes.
{object} [music] - section that responds for music settings.
{number} [music.similarity=0.91] - number from 0 to 1 indicating how similar songs titles have to be, in order to consider them the same.
{number|string} [music.audioHeadersMaxSize="180kb"] - maximum audio headers size.
{number|string} [music.coverHeadersMaxSize="5kb"] - maximum cover headers size.
{number} [music.findingStringMinLength=4] - minimum symbols to find songs.
{number} [music.findingLimit=200] - songs finding maximum result list size.
{number|string} [music.relevanceTime="14d"] - how long does an existing song take precedence over newly added.
{boolean} [music.prepareTitle=true] - prepare the title before addition or not. Preparation means bringing the title to a general view.
{boolean} [music.prepareCover=true] - prepare the cover before addition or not. Preparation means bringing the size and image quality to the right values.
{integer} [music.coverQuality=80] - prepared cover quality from 0 to 100. It works only when music.prepareCover is true.
{integer} [music.coverMinSize=200] - minimum cover size in px. It works only when music.prepareCover is true.
{integer} [music.coverMaxSize=500] - maximum cover size in px. It works only when music.prepareCover is true.
{number|string} [music.coverMaxFileSize="110kb"] - maximum cover file size. It works only when music.prepareCover is true.
{number|string} [task.cleanUpMusicInterval="1m"] - music cleanup task interval.
Client interface
async Client.prototype.addSong() - add the file to the network.
- {string|fse.ReadStream|Buffer|Blob} file - mp3 audio file
- {object} [options] - addition options
- {number} [options.timeout] - addition timeout
- {integer} [options.priority=0] - song priority -1, 1 or 0
- {boolean} [options.controlled=false] - enable moderation mode or not
async Client.prototype.getSong() - get the song main info.
- {string} title - song title
- {object} [options] - getting options
- {number} [options.timeout] - getting timeout
async Client.prototype.getSongInfo() - get the song complete info.
- {string} title - song title
- {object} [options] - getting options
- {number} [options.timeout] - getting timeout
async Client.prototype.findSongs() - find songs by the match.
- {string} str - string to match
- {object} [options] - getting options
- {number} [options.limit] - result list maximum size
- {number} [options.timeout] - getting timeout
async Client.prototype.findArtistSongs() - find songs by the artist name.
- {string} artist - artist name
- {object} [options] - getting options
- {number} [options.timeout] - getting timeout
async Client.prototype.getSongAudioLink() - get the song audio file link.
- {string} title - song title
- {object} [options] - getting options
- {number} [options.timeout] - getting timeout
async Client.prototype.getSongCoverLink() - get the song cover file link.
- {string} title - song title
- {object} [options] - getting options
- {number} [options.timeout] - getting timeout
async Client.prototype.getSongAudioToBuffer() - download the song audio file and return the buffer.
- {string} title - song title
- {object} [options] - getting options
- {number} [options.timeout] - getting timeout
async Client.prototype.getSongCoverToBuffer() - download the song cover file and return the buffer.
- {string} title - song title
- {object} [options] - getting options
- {number} [options.timeout] - getting timeout
async Client.prototype.getSongAudioToPath() - download the song audio file and write it to the specified path.
- {string} title - song title
- {object} [options] - getting options
- {number} [options.timeout] - getting timeout
async Client.prototype.getSongCoverToPath() - download the song cover file and write it to the specified path.
- {string} title - song title
- {object} [options] - getting options
- {number} [options.timeout] - getting timeout
async Client.prototype.getSongAudioToBlob() - download the song audio file and return the blob. For browser client only.
- {string} title - song title
- {object} [options] - getting options
- {number} [options.timeout] - getting timeout
async Client.prototype.getSongCoverToBlob() - download the song cover file and return the blob. For browser client only.
- {string} title - song title
- {object} [options] - getting options
- {number} [options.timeout] - getting timeout
async Client.prototype.removeSong() - Remove the song.
- {string} title - song title
- {object} [options] - removal options
- {number} [options.timeout] - removal timeout
Client.prototype.createRequestedSongAudioLink() - сreate a requested audio file link. This is convenient if you need to get the link without doing any asynchronous operations at the moment.
- {string} title - song title
- {object} [options] - options
Client.prototype.createRequestedSongCoverLink() - сreate a requested cover file link. This is convenient if you need to get the link without doing any asynchronous operations at the moment.
- {string} title - song title
- {object} [options] - options
Exporting songs
If necessary, you have the opportunity to export songs from one server to another. There are two options:
Copy all project files to the second server. It is convenient and works at the current moment, because the node is able to reconfigure all information to a new address. But there is no guarantee that this will work in the future.
Use the song export feature: run
node.exportSongs()
method or via the command line asmuseria -a exportSongs -n 2.2.2.2:2079
. Here, you should add the first server to the trust list of the second one to transfer all songs, including those with priority 1. Without this, the node will require a captcha solution and the file will not be added. Use the option network.trustlist of the spreadable-ms library.
Contribution
If you face a bug or have an idea how to improve the library, create an issue on github. In order to fix something or add new code yourself, fork the library, make changes and create a pull request to the master branch. Don't forget about tests in this case. Also you can join the project on github.