Self-hosted music streaming server 🎶 with RESTful API and Web interface

Euterpe

Euterpe Icon

Euterpe is self-hosted streaming service for music. Formerly known as "HTTPMS (HTTP Media Server)".

A way to listen to your music library from everywhere. Once set up you won't need anything but a browser. Think of it as your own Spotify service over which you have full control. Euterpe will let you browse through and listen to your music over HTTP(s). Up until now I've had a really bad time listening to my music which is stored back home. I would create a mount over ftp, sshfs or something similar and point the local player to the mounted library. Every time it resulted in some upleasantries. Just imagine searching in a network mounted directory!

No more!

Build Status GoDoc Go Report Card Coverage Status

Web UI

Have a taste of how its web interface looks like

Euterpe Screenshot

It comes with a custom jPlayer which can handle playlists with thousands of songs. Which is an imrovement over the original which never included this performance patch.

I feel obliged to say that the music on the screenshot is written and performed by my close friend Velislav Ivanov.

Features

  • Simple. It is just one binary, that's it! You don't need to faff about with interpreters or web servers
  • Fast. A typical response time on my more than a decade old mediocre computer is 26ms for a fairly large collection
  • Supports the most common audio formats such as mp3, oga, ogg, wav, flac, opus, web and m4a audio formats
  • Built-in fast and simple Web UI so that you can play your music on every device
  • Media and UI could be served over HTTP(S) natively without the need for other software
  • User authentication (HTTP Basic, query token, Bearer token)
  • Media artwork from local files or automatically downloaded from the Cover Art Archive
  • Artist images could be downloaded automatically from Discogs
  • Search by track name, artist or album
  • Download whole album in a zip file with one click
  • Controllable via media keys in OSX with the help of BeardedSpice
  • Extensible via stable API
  • Multiple clients and player plugins
  • Uses jplayer to play your music on really old browsers

Demo

Just show, don't talk, will ya? I will! You may take the server a spin with the live demo if you would like to. Feel free to thank all the artists who made their music available for this!

Requirements

If you want to install it from source you will need:

Install

The safest route is installing one of the releases.

Linux & macOS

If you have one of the releases (for example euterpe_1.1.0_linux.tar.gz) it includes an install script which would install Euterpe in /usr/bin/euterpe. You will have to uninstall any previously installed versions first. An uninstall script is provided as well.

Windows

Automatically creating a release version for Windows is in progress at the moment. For the time being check out the next section, "From Source". Pay attention to the requirements section above. As of writing this the author hasn't been yet initiated in the secret art of building and installing libraries on Windows so you are on your own.

From Source (any OS)

If installing from source running go install in the project root directory will compile euterpe and move its binary in your $GOPATH. Releases from v1.0.1 onward have their go dependencies vendored in.

So, to install the master branch, you can just run

go install github.com/ironsmile/euterpe

Or alternatively, if you want to produce a release version you will have to get the repository. Then in the root of the project run

make release

This will produce a binary euterpe which is ready for distribution. Check its version with

./euterpe -v

First Run

Once installed, you are ready to use your media server. After its initial run it will create a configuration file which you will have to edit to suit your needs.

  1. Start it with euterpe

  2. Edit the config.json and add your library paths to the "library" field. This is an important step. Without it, euterpe will not know where your media files are.

Docker

Alternatively to installing everything in your environment you can use the Docker image.

Start the server by running:

docker run -v "${HOME}/Music/:/root/Music" -p 8080:9996 -d ironsmile/euterpe:latest euterpe

Then point your browser to https://localhost:8080 and you will see the Euterpe web UI. The -v flag in the Docker command will mount your $HOME/Music directory to be discoverable by Euterpe.

Building the Image Yourself

You can use the Dockerfile in this repository to build the image yourself.

docker build -t ironsmile/euterpe github.com/ironsmile/euterpe

The euterpe binary there is placed in /usr/local/bin/euterpe.

Configuration

HTTPS configuration is saved in a JSON file, different for every user in the system. Its location is as follows:

  • Linux or BSD: $HOME/.euterpe/config.json
  • Windows: %APPDATA%\euterpe\config.json

When started for the first time Euterpe will create one for you. Here is an example:

{
    // Address and port on which Euterpe will listen. It is in the form hostname[:port]
    // For exact explanation see the Addr field in the Go's net.http.Server
    // Make sure the user running Euterpe have permission to bind on the specified
    // port number
    "listen": ":443",

    // true if you want to access Euterpe over HTTPS or false for plain HTTP.
    // If set to true the "ssl_certificate" field must be configured as well.
    "ssl": true,

    // Provides the paths to the certificate and key files. Must be full paths, not
    // relatives. If "ssl" is false this can be left out.
    "ssl_certificate": {
        "crt": "/full/path/to/certificate/file.crt",
        "key": "/full/path/to/key/file.key"
    },

    // true if you want the server to require HTTP basic authentication. Credentials
    // are set by the 'authentication' field below.
    "basic_authenticate": true,
    
    // User and password for the HTTP basic authentication.
    "authentication": {
        "user": "example",
        "password": "example"
    },

    // An array with all the directories which will be scanned for media. They must be
    // full paths and formatted according to your OS. So for example a Windows path
    // have to be something like "D:\Media\Music".
    // As expected Euterpe will need permission to read in the library folders.
    "libraries": [
        "/path/to/my/files",
        "/some/more/files/can/be/found/here"
    ],
    
    // Optional configuration on how to scan libraries. Note that this configuration
    // is applied to each library separately.
    "library_scan": {
        // Will wait this much time before actually starting to scan a library.
        // This might be useful when scanning is resource hungry operation and you
        // want to postpone it on start up.
        "initial_wait_duration": "1s",
        
        // With this option a "operation" is defined by this number of scanned files.
        "files_per_operation": 1500,

        // After each "operation", sleep this amount of time.
        "sleep_after_operation": "15ms"
    },

    // When true, Euterpe will search for images on the internet. This means album artwork
    // and artists images. Cover Art Archive is used for album artworks when none is
    // found locally. And Discogs for artist images. Anything found will be saved in
    // the Euterpe database and later used to prevent further calls to the archive.
    "download_artwork": true,

    // If download_artwork is true the server will try to find artist artwork in the
    // Discogs database. In order for this to work an authentication is required
    // with their API. This here must be a personal access token. In effect the server
    // will make requests on your behalf.
    //
    // See the API docs for more information:
    // https://www.discogs.com/developers/#page:authentication,header:authentication-discogs-auth-flow
    "discogs_auth_token": "some-personal-token"
}

List with all directives can be found in the configration wiki.

As an API

You can use Euterpe as a REST API and write your own player. Or maybe a plugin for your favourite player which would use your Euterpe installation as a back-end.

v1 Compatibility Promise

The API presented in this README is stable and will continue to be supported as long as version one of the service is around. And this should be very long time. I don't plan to make backward incompatible changes. Ever. It has survived in this form since 2013. So it should be good for at least double than this amount of time in the future.

This means that clients written for Euterpe will continue to work. I will never break them on purpose and if this happened it will be considered a bug to be fixed as soon as possible.

Authentication

When your server is open you don't have to authenticate requests to the API. Installations protected by user name and password require you to authenticate requests when using the API. For this the following methods are supported:

  • Bearer token in the Authorization HTTP header (as described in RFC 6750):
Authorization: Bearer token
  • Basic authentication (RFC 2617) with your username and password:
Authorization: Basic base64(username:password)

Authentication tokens can be acquired using the /v1/login/token/ endpoint described below. Using tokens is the preferred method since it does not expose your username and password in every request. Once acquired users must register the tokens using the /v1/register/token/ endpoint in order to "activate" them. Tokens which are not registered may or may not work. Tokens may have expiration date or they may not. Integration applications must provide a mechanism for token renewal.

Endpoints

Search

One can do a search query at the following endpoint

GET /v1/search/?q={query}

wich would return an JSON array with tracks. Every object in the JSON represents a single track which matches the query. Example:

[
   {
      "album" : "Battlefield Vietnam",
      "title" : "Somebody to Love",
      "track" : 10,
      "artist" : "Jefferson Airplane",
      "artist_id": 33,
      "id" : 18,
      "album_id" : 2,
      "format": "mp3",
      "duration": 180000
   },
   {
      "album" : "Battlefield Vietnam",
      "artist" : "Jefferson Airplane",
      "track" : 14,
      "format": "flac",
      "title" : "White Rabbit",
      "album_id" : 2,
      "id" : 22,
      "artist_id": 33,
      "duration": 308000
   }
]

The most important thing here is the track ID at the id key. It can be used for playing this track. The other interesting thing is album_id. Tracks can be grouped in albums using this value. And the last field of particular interest is track. It is the position of this track in the album.

Note that the track duration is in milliseconds.

Browse

A way to browse through the whole collection is via the browse API call. It allows you to get its albums or artists in an ordered and paginated manner.

GET /v1/browse/[?by=artist|album][&per-page={number}][&page={number}][&order-by=id|name][&order=desc|asc]

The returned JSON contains the data for the current page, the number of all pages for the current browse method and URLs of the next or previous pages.

{
  "pages_count": 12,
  "next": "/v1/browse/?page=4&per-page=10",
  "previous": "/v1/browse/?page=2&per-page=10",
  "data": [ /* different data types are returned, determined by the `by` parameter */ ]
}

For the moment there are two possible values for the by parameter. Consequently there are two types of data that can be returned: "artist" and "album" (which is the default).

by=artist

would result in value such as

{
  "artist": "Jefferson Airplane",
  "artist_id": 73
}

by=album

would result in value such as

{
  "album": "Battlefield Vietnam"
  "artist": "Jefferson Airplane",
  "album_id": 2
}

Additional parameters

per-page: controls how many items would be present in the data field for every particular page. The default is 10.

page: the generated data would be for this page. The default is 1.

order-by: controls how the results would be ordered. The value id means the ordering would be done by the album or artist ID, depending on the by argument. The same goes for the name value. Defaults to name.

order: controls if the order would ascending (with value asc) or descending (with value desc). Defaults to asc.

Play a Song

GET /v1/file/{trackID}

This endpoint would return you the media file as is. A song's trackID can be found with the search API call.

Download an Album

GET /v1/album/{albumID}

This endpoint would return you an archive which contains the songs of the whole album.

Album Artwork

Euterpe supports album artwork. Here are all the methods for managing it through the API.

Get Artwork

GET /v1/album/{albumID}/artwork

Returns a bitmap image with artwork for this album if one is available. Searching for artwork works like this: the album's directory would be scanned for any images (png/jpeg/gif/tiff files) and if anyone of them looks like an artwork, it would be shown. If this fails, you can configure Euterpe to search in the MusicBrainz Cover Art Archive. By default no external calls are made, see the 'download_artwork' configuration property.

By default the full size image will be served. One could request a thumbnail by appending the ?size=small query.

Upload Artwork

PUT /v1/album/{albumID}/artwork

Can be used to upload artwork directly on the Euterpe server. This artwork will be stored in the server database and will not create any files in the library paths. The image should be send in the body of the request in binary format without any transformations. Only images up to 5MB are accepted. Example:

curl -i -X PUT \
  --data-binary @/path/to/file.jpg \
  http://127.0.0.1:9996/v1/album/18/artwork

Remove Artwork

DELETE /v1/album/{albumID}/artwork

Will remove the artwork from the server database. Note, this will not touch any files on the file system. Thus it is futile to call it for artwork which was found on disk.

Artist Image

Euterpe could build a database with artists' images. Which it could then be used throughout the interfaces. Here are all the methods for managing it through the API.

Get Artist Image

GET /v1/artist/{artistID}/image

Returns a bitmap image representing an artist if one is available. Searching for artwork works like this: if artist image is found in the database then it will be used. In case there is not and Euterpe is configured to download images from interned and has a Discogs access token then it will use the MusicBrainz and Discogs APIs in order to retrieve an image. By default no internet requests are made.

By default the full size image will be served. One could request a thumbnail by appending the ?size=small query.

Upload Artist Image

PUT /v1/artist/{artistID}/image

Can be used to upload artist image directly on the Euterpe server. It will be stored in the server database and will not create any files in the library paths. The image should be send in the body of the request in binary format without any transformations. Only images up to 5MB are accepted. Example:

curl -i -X PUT \
  --data-binary @/path/to/file.jpg \
  http://127.0.0.1:9996/v1/artist/23/image

Remove Artist Image

DELETE /v1/artist/{artistID}/image

Will remove the artist image the server database. Note, this will not touch any files on the file system.

Token Request

POST /v1/login/token/
{
  "username": "your-username",
  "password": "your-password"
}

You have to send your username and password as a JSON in the body of the request as described above. Provided they are correct you will receive the following response:

{
  "token": "new-authentication-token"
}

Before you can use this token for accessing the API you will have to register it with on "Register Token" endpoint.

Register Token

POST /v1/register/token/

This endpoint registers the newly generated tokens with Euterpe. Only registered tokens will work. Requests at this endpoint must authenticate themselves using a previously generated token.

Media Keys Control For OSX

You can control your Euterpe web interface with the media keys the same way you can control any native media player. To achieve this a third-party program is required: BearderSpice. Sadly, Euterpe (HTTPMS) is not included in the default web strategies bundled-in with the program. You will have to import the strategy file included in this repo yourself.

How to do it:

  1. Install BeardedSpice. Here's the download link
  2. Then go to BeardedSpice's Preferences -> General -> Media Controls -> Import
  3. Select the bearded-spice.js strategy from this repo

Or with images:

BeardedSpice Preferences:

BS Install Step 1

Select "Import" under Genral tab:

BS Install Step 2

Select the bearded-spice.js file:

BS Install Step 3

Then you are good to go. Smash those media buttons!

Clients

You are not restricted to using the web UI. The server has a RESTful API which can easily be used from other clients. I will try to keep a list with all of the known clients here:

  • httpms-android is a Android client for HTTPMS. Long abandoned in favour of a React Native mobile client.
  • euterpe-mobile is an iOS/Android mobile client written with React Native.
  • euterpe-rhythmbox is Euterpe client plugin for Gnome's Rhythmbox.

Name Change

Euterpe was previously known as "HTTPMS" from "HTTP Media Server". This name is too generic, it proved to be very hard to remember and was all-around a bad choice. At the time I was mostly thinking about the function and not the presentation of the project. Since there are more people using it now it makes sense to improve this aspect as well.

"Euterpe" was chosen because of the obvious association with the muse of music. There are still places where internally the software refers to itself as "HTTPMS" but they will go away with time. Hopefully soon.

Comments
  • Use Alpine Linux for Docker Builds

    Use Alpine Linux for Docker Builds

    Hello! Exploring euterpe and considering the possibility of adopting it for my personal music server. I thought I'd contribute a small change in return.

    I suggest switching to alpine linux in the Dockerfile.

    This results in:

    • Smaller image sizes
    • More secure application environment
    • Only use packages required for build

    Thanks so much!

  • Unable to persist database

    Unable to persist database

    Regardless of whatever I try to do, I am unable to persist the database when installed via docker.

    docker-compose.yml:

    version: '3.3'
    services:
        euterpe:
            volumes:
                - '/home/keo7/services/euterpe/data:/root/.euterpe'
                - '/home/keo7/consti/Music/:/root/Music'
            ports:
                - '9996:9996'
            image: 'ironsmile/euterpe:latest'
    
    
  • Album Artwork

    Album Artwork

    How hard would it be to implement adding the track/album art within the API? i think it would be a pretty cool feature. as well as adding POST / PUT / DELETE features so you can edit your library from the frontend. 💯

  • maint: upgrade gbrlsnchs/jwt to v3

    maint: upgrade gbrlsnchs/jwt to v3

    Related to issue #27, the gbrlsnchs/jwt package needed an upgrade to a non backward-compatible version. This PR bumps it from v1 to v3 with the appropriate code changes.

    Please let me know if changes are needed to better suit the project conventions.

    Personal note: there is a world in which I would avoid creating an new JWT algorithm for each issue or verification, but that's probably out of the scope of this PR.

  • Error generating JWT: jwt.(Signer).Sign: HMAC key is empty.

    Error generating JWT: jwt.(Signer).Sign: HMAC key is empty.

    hi After sign in the page return:

    Error generating JWT: jwt.(Signer).Sign: HMAC key is empty.

    my docker-compose.yml:

    version: '3'
    services:
        kavita:
            image: ironsmile/euterpe:latest
            container_name: euterpe
            volumes:
                - /data/euterpe/config:/root/.euterpe
                - /data/euterpe/Music:/root/Music
            ports:
                - "4000:9996"
            restart: unless-stopped
    

    config.json :

    {
        "listen": ":9996",
        "ssl": false,
        "ssl_certificate": {
            "crt": "/full/path/to/certificate/file.crt",
            "key": "/full/path/to/key/file.key"
        },
        "basic_authenticate": true,
        "authentication": {
            "user": "kong",
            "password": "xxxxxxxxxxxxxxxxxxxxxx"
        },
        "libraries": [
            "/root/Music"
        ],
        "library_scan": {
            "initial_wait_duration": "1s",
            "files_per_operation": 1500,
            "sleep_after_operation": "15ms"
        },
        "download_artwork": true,
        "discogs_auth_token": "xxxxxxxxxxxxxxxxxxxxxxx"
    }
    

    Thanks

  • Help to setup the dev environment

    Help to setup the dev environment

    I would appreciate if you could please help me on how to setup the dev environment for this project.I would like to tinker a bit with the project to learn.

  • Default listen address for docker

    Default listen address for docker

    I tried to install euterpe use docker, by following command.

    docker build -t ironsmile/euterpe github.com/ironsmile/euterpe
    

    but I cannot access from the host. I found that the default listening address of the server is localhost:9996, and you need to manually change it to 0.0.0.0:9996.

    For out-of-the-box use, can you change the default listening address in docker to 0.0.0.0:9996.

    Also if you can publish docker image to dockerhub, that would be great.

  • Do not gzip media files over HTTP even when gzip setting is on

    Do not gzip media files over HTTP even when gzip setting is on

    The gzip handler should not gzip media content. This has no point since savings will be small for mp3 files and the like which are more or less compressed already as much as possible. Ideally it should detect content type here and make a decision based on some configuration. This have the following benefits:

    • Easier on the CPU for the server and client both. Considering mobile clients this could be a huge saving.
    • Will probably allow implementing io.ReaderFrom with io.Copy for non-gzipped files. This makes possible sending them with sendfile and friends.
  • [Web player] Unexpected Shuffle button behaviour

    [Web player] Unexpected Shuffle button behaviour

    In most audio players, the Shuffle button toggles an option wether the next track should be according to the playlist or a random song. In Euterpe, it immediately plays a random song, which is unexpected, and therefore undesireable. It is also confusing since the Repeat button besides it is simply a toggle as it should (instead of also immediately restarting the current song).

  • Automatic building and pushing images to Docker Hub

    Automatic building and pushing images to Docker Hub

    It would be great if images to the Docker Hub were pushed automatically. For this end a new GitHub action could be created.

    What to push?

    • Merges to master should cause building and pushing an image with the latest tag
    • Tags for released versions should cause building and pushing this version with a docker image tag matching the release tag

    Testing

    The Docker Hub publishing pipeline should make sure that the pushed Docker images are actually operational. So it should try to run the image and check that Euterpe is actually starting inside it.

  • Update JWT lib to latest version (v2)

    Update JWT lib to latest version (v2)

    Hi there! I was checking which libs use the JWT library I have created and found your project. I like it very much, congrats. But I advise you to update my lib to version 2 since there are some performance enhancements. However, code is not backwards compatible, so you might need to make some adjustments in order to make it work, but it's definitely worth it.

    Anyway, thanks for your trust in my work.

  • Apple TV app

    Apple TV app

    I think we could easily build an Apple TV app for this.

    There are 2 options that might work. Tvml is apples own markup for Apple TV that may also support music . We could serve that from the server or another project t that imports the pkg of the server.

    https://developer.apple.com/documentation/tvmljs/playing_media_in_a_client-server_app

    The other way is with golang . You can build advanced golang gui that can play music using gioui. It compiles to iOS and hence apple tv. I use gioui a fair bit.

    It can also be used to output web and mobile and desktop apps.

    https://github.com/gioui

  • Caching proxy

    Caching proxy

    Cool project . Really great to see desktop and mobile supported too. I would like to help with those .

    I was wondering if a proxy that supports also caching the audio files efficiently is envisaged ?

    maybe if it’s outside the scope of the project you have sone suggestions.

    My use case is that I host everything on tiny Linux server in my house and expose it over a proxy .

    So it would ease the load on my home server if I could run a simple proxy in the cloud , that of course Proxies my home server .

    I saw a old golang proxy called “nedomi” and was wondering if this would be a good match to my use case of a simple proxy. It looked really cool in that it chunked the files into smaller parts and so match user habits of jumping forward in a stream .

    thanks again for this awesome project !!

    Don’t know if anyone remembers google music when it allowed you to upload your music btw . I was one of these users that got stung by google shutting it down.

  • Sort by

    Sort by "Album Artist" instead of "Artist"

    Like the title says, it'll help listing music libraries with Compilations and Split Albums.

    Brief explanation in this comment: https://community.mp3tag.de/t/album-artist-vs-artist/12774/2

  • Euterpe not starting (WebUI) after mounting '/root/.euterpe'

    Euterpe not starting (WebUI) after mounting '/root/.euterpe'

    Hello, I'm having problems when I try to mount the '/root/.euterpe' container directory.

    When I start the container with this mount, pointing to a physical directory on my server to allow the persistance of the information (db, logs, configs), Euterpe just doesn't start. I mean, the container starts without erros (no terminal errors nor nothing related, I think, in the log file), but it doesn't show the WebUI from port 9996.

    I tried changing the permissions of the mounted volume manually, if that could be the problem, being Euterpe not able to access or write to the directory, but nothing. It has full access as all the files are created: config.json, euterpe.db, euterpe.log, pidfile,pid.

    Thank you for your attention.

A tool coded by GO to decode cryptoed netease music files and qqmusic files

nqdumpgo A tool coded by GO to decode cryptoed netease music files and qqmusic files 一个使用 Go 语言编写的用于解密被网易云音乐或 QQ 音乐加密的文件的程序,Go 程序在拥有与 C++程序相近的效率的同时,大大

Dec 13, 2022
Sequence-based Go-native audio mixer for music apps

Mix https://github.com/go-mix/mix Sequence-based Go-native audio mixer for music apps See demo/demo.go: package main import ( "fmt" "os" "time"

Dec 1, 2022
Unlock Music Project - CLI Edition

Unlock Music Project - CLI Edition Original: Web Edition

Nov 2, 2022
Go library for searching on YouTube Music.

ytmusic Go library for searching on YouTube Music and getting other useful information. Installing go get github.com/raitonoberu/ytmusic Usage Search

Oct 15, 2022
A music programming language for musicians. :notes:

Installation | Docs | Changelog | Contributing composers chatting Alda is a text-based programming language for music composition. It allows you to co

Dec 30, 2022
Small application to convert my music library folder structure to 'crates' in the open-source DJ software Mixxx

Small application to convert my music library folder structure to 'crates' in the open-source DJ software Mixxx

Nov 18, 2022
Gomu is intuitive, powerful CLI music player.
Gomu is intuitive, powerful CLI music player.

Gomu (Go Music Player) Gomu is intuitive, powerful CLI music player. It has embedded scripting language and event hook to enable user to customize the

Dec 25, 2022
Kwed-dl - A tool to download latest music files from remix.kwed.org

kwed-dl A small program to download latest tracks from remix.kwed.org. Keeps a counter in your home-folder (_kwedrc on windows and .kwedrc on linux).

May 24, 2022
Muclean - A simple music file renamer

Muclean A simple music file renamer Installation go install github.com/CJ-Jackso

Jan 23, 2022
MIDI tunneling through BGP, for times when you want to broadcast your music instead of your IP packets.

BGPiano MIDI tunneling through BGP, for times when you want to broadcast your music instead of your IP packets. Usage bgpiano-send and bgpiano-recv Po

Jun 9, 2022
Pigiron is a MIDI routing utility with an extensive OSC interface.

Pigiron README (c) 2021 Steven Jones Pigiron is a fully configurable MIDI routing utility written in Go. It includes a MIDI file player and has a comp

Nov 24, 2022
Local-audio - Web walking audio tour platform proof-of-concept

Goal: Proof of concept for a Web Audio walk platform Data retention dynamdo db "time to live" expires in 1 day from creation of record set in add.go s

Jan 9, 2022
网易云音乐 API Golang 实现

网易云音乐 API-Go 网易云音乐 Golang API 实现 灵感来自 Binaryify/NeteaseCloudMusicApi 说明 与 Binaryify/NeteaseCloudMusicApi 不同的是,本项目将全部采用 Eapi(即网易云音乐客户端使用的API) 本项目可能会很咕,

Oct 26, 2022
? ID3 decoding and encoding library for Go

id3v2 Supported ID3 versions: 2.3, 2.4 Installation go get -u github.com/bogem/id3v2 Usage example package main import ( "fmt" "log" "github.com

Dec 31, 2022
Go models of Note, Scale, Chord and Key

gopkg.in/music-theory.v0 Music theory models in Go There's an example command-line utility music-theory.go to demo the libraries, with a bin/ wrapper.

Dec 10, 2022
EasyMidi is a simple and reliable library for working with standard midi file (SMF)

EasyMidi EasyMidi is a simple and reliable library for working with standard midi file (SMF). Installing A step by step series of examples that tell y

Sep 21, 2022
A yet to be voice call application in terminal. with the power of go and webRTC (pion).

A yet to be voice call application in terminal. with the power of go and webRTC (pion).

Dec 2, 2022
A utility for sending and listening for OSC messages.

A simple utility to send and listen for OSC messages. It can also be used to send MIDI messages.

Mar 5, 2022
Like tar but different. PitCH is an archive file format that aims for high performance and minimal bloat.

Like tar but different. PitCH is an archive file format that aims for high performance and minimal bloat.

Feb 17, 2022