Simple personal server to serve audiofiles files from folders.

Overview

Audioserve

Build Status Docker Pulls

[DEMO AVAILABLE - shared secret: mypass]

Simple personal server to serve audio files from directories. Intended primarily for audio books, but anything with decent directories structure will do. Focus here is on simplicity and minimalistic design.

Server is written in Rust, default web client (HTML5 + Javascript) is intended for modern browsers (latest Firefox or Chrome) and is integrated with the server. There is also Android client and API for custom clients.

For some background and video demo check this article Audioserve Audiobooks Server - Stupidly Simple or Simply Stupid?

If you will install audioserve and make it available on Internet do not underestimate security.

Like audioserve and want to start quickly and easily and securely? Try this simple guide to have audioserve up and running for free in no time.

Media Library

Audioserve is intended to serve files from directory in exactly same structure (recently with some support for .m4b and similar single file audiobooks), audio tags are not considered. So recommended structure is:

Author Last Name, First Name/Audio Book Name
Author Last Name, First Name/Series Name/Audio Book Name

Files should be named so they are in right alphabetical order - ideal is:

001 - First Chapter Name.opus
002 - Second Chapter Name.opus

But this structure is not mandatory - you will just see whatever directories and files you have, so use anything that will suite you.

The characters $$ and | are used for internal usage of audioserve, so you should not use then in file names.

In folders you can have additional metadata files - first available image (jpeg or png) is taken as a cover picture and first text file (html, txt, md) is taken as description of the folder.

Search is done for folder names only (not individual files, neither audio metadata tags).

You can have several libraries/ collections - just use several root directories as audioserve start parameters. In client you can switch between collections in the client. Typical usage will be to have separate collections for different languages.

By default symbolic(soft) links are not followed in the collections directory (because if incorrectly used it can have quite negative impact on search and browse), but they can be enabled by --allow-symlinks program argument.

Single file audiobooks and chapters

Recently better support for .m4b (one big file with chapters metadata) and similar was added. Such file is presented as a folder, which contains chapters (if you do not like this feature you can disable with --ignore-chapters-meta argument).

Also long audiofile without chapters metadata, can be split into equaly sized parts/chapters (this has a slight disadvantage as split can be in middle of word). To enable later use --chapters-from-duration to set a limit, from which it should be used, and chapters-duration to set a duration of a part. Also for large files, which do not have chapters metadata, you can easily supply them in a separate file, with same name as the audio file but with additional extension .chapters - so it looks like your_audiobook.mp3.chapters. This file is simple CSV file (with header), where first column is chapter title, second is chapter start time, third (and last) is the chapter end time. Time is either in seconds (like 23.836) or in HH:MM:SS.mmm format (like 02:35:23.386).

There are some small glitches with this approach - search still works on directories only and cover and description metadata are yet not working (plan is to extract them from the audio file metadata). Apart of that chapters behaves like other audio files - can be transcoded to lower bitrates, seeked within etc.

If chaptered file is a single file in a directory (and there are no other subdirectories), then chapters are presented within this directory, as if they were files in this directory. This can help overcome above mentioned limitations - as search will work on directory name and also cover and description is shown from this directory - so this would be preferred way of placing .m4b files. If you do not like this new feature you can disable by --no-dir-collaps option.

Also beware that web client will often load same part of chapter again if you're seeking within it (especially Firefox with m4b), so it's definitely not bandwidth optimal (similar issue appears when often seeking in transcoded file).

Sharing playback positions between clients

Recently (from version 0.10) audioserve supports sharing playback positions between clients. This is basically used to continue listening on next client, from where you left on previous one. It's supported in the included web client and in the recent Android client (from version 0.8). In order to enable position sharing you'll need to define 'device group' in the client (on login dialog in web client and in settings in Android client) - group is just an arbitrary name and devices within same group will share playback position.

After you have several active devices with same group name, you'll be notified when you click play and there is more recent playback position in the group and you can choose if jump to this latest position or continue with current position. There is also option to check latest position directly (in web client it's icon in the folder header, in Android client it's in options menu).

Proper functioning is (indeed) dependent on good connectivity - as position is shared during playback via web socket connection. If connection is unstable this can be unreliable or behave bit strangely.

Security

Audioserve is not writing anything to your media library, so read only access is OK. However you should assume that any file in published media directories can be accessible via audioserve API (thought recently name starting with . (hidden files/directories) are blocked) so basically to anybody who can obtain shared secret (or in case you use --no-authentication then to anybody).

Write access is need to file were it keeps its secret key for authentication (by default in ~/.audioserve/audioserve.secret, its locations can be changed by command line argument --secret-file) - this file should have exclusive rw access for user running audioserve (this is how file is created, so no special action is needed). Another file, which requires write access, is positions file (used for shared position synchronization, if not needed compile audioserve without shared-positions feature) by default in ~/.audioserve/audioserve.positions. Optionally, if feature transcoding-cache (see below) is enabled (during compilation) cache directory (by default in ~/.audioserve/audioserve-cache) has to have write rights too. As you can see by default write access is needed to directory ~/.audioserve/. This directory for all writeable files can be changed by --data-dir argument (which can be quite useful if you run audioserve in docker container with a specified user).

Authentication is done by shared secret phrase (supplied to server on command line or more securely via environment variable), which clients must know. Shared secret phrase is never sent in plain (it's sent as salted hash). If correct shared secret hash is provided by client, sever generates a token, using its secret key, which is then used for individual requests authentication. Token then can be used in cookie or HTTP Authorization header (Bearer method). Token validity period is one year by default, but can be set with command line argument, but system generally expects token validity to be at least 10 days. As the token can be used to steal the session, https is recommended (TLS support is build in, but reverse proxy is probably better solution). If you want to change shared secret also delete server secret (it will invalidate all issued tokens) - stop audioserve, delete ~/.audioserve/audioserve.secret and restart audioserve with new shared secret.

Authentication is used to access all URLs except web client static files (/index.html and /bundle.js).

TLS/SSL

Audioserve supports TLS/SSL - to enable it you need to provide your private server key as PKCS#12 file (in --ssl-key argument). Here is quick tip how to create private key with self-signed certificate (for testing purposed only):

openssl req -newkey rsa:2048 -nodes -keyout key.pem -x509 -days 365 -out certificate.pem \
    -subj "/C=CZ/ST=Prague/L=Prague/O=Ivan/CN=audioserve"
openssl pkcs12 -inkey key.pem -in certificate.pem -export  -passout pass:mypass -out audioserve.p12
rm key.pem certificate.pem

You can also run audioserve behind reverse proxy like nginx or ha-proxy and terminate SSL there (in that case you can compile audioserve without TLS support see compilation without default features below)

Reverse proxy

Often best way how to deploy audioserve is behind reverse proxy, which terminates TLS/SSL and connects to backend audioserve. Reverse proxy can serve also other backend servers on same domain, in this case audioserve server should be determined by URL path prefix - so external address is like https://yourdomain.com/audioserve and it's map to http://local_name_or_ip:3000 (or whatever port you are using). Decent proxy can do such mapping, but I've heard about setups (shared seedbox), when this is not possible and URL path prefix is automatically forwarded to backend. For that case audioserve has argument --url-path-prefix, which contains prefix (without final slash) and audioserve accepts this prefix as root path.

Another gotcha for reverse proxy might be usage of last playback position feature, which requires websocket connection and some special configuration for that might be needed in reverse proxy.

Also there is optional feature behind-proxy, which enables argument --behind-proxy, is used only for logging real client ip address - if used client ip address is taken from Forwarded (preferred) or X-Forwarded-For HTTP headers provided by reverse proxy.

You can check some reverse proxy configurations in reverse_proxy.md (If you have successful configuration of reverse proxy please share via PR).

Limit Requests Rate

Normally you'd allow audioserve to serve as much requests as it can handle, but if you like to protect yourself against DDoS (Distributed Denial of Service) attack (consider now much it's probable and serious in your case) you should consider limiting rate of requests handling.

If audioserve is behind reverse proxy you can use rate limiting option of proxy server (like this one for nginx). Audioserve also has argument --limit-rate n, which turns on simple (it's global, not per remote address) rate limiting on all incoming HTTP requests to maximum of n request per second (approximately), for requests over the limit audioserve return 429 - Too Many Requests HTTP status code. As this is overall limit it will not protect legal users, as they will also see rejected requests, but it will just protect host from extensive use of resources.

Number of parallel transcodings (transcodings are most resource intensive tasks) is limited by --transcoding-max-parallel-processes, which is 2 * number of CPU cores by default. This is different then limit-rate, as it guards number of transcodings that run concurrently.

CORS

When web client is served from different host (or port) then audioserve API (this is mostly the case during web client development, when client is served from development server like webpack serve), browser CORS policies will prevent client from communicating with audioserve server API (as it is in different origing than client pages). In this case you can start audioserve with additional --cors option, which will add appropriate CORS headers to responses, thus enabling browser to accept responses from server. Responses' CORS headers are totally permissive, allowing access from all origins and with any additional headers, so this should be used rather in development. For production use web client served by audioserve server and avoid --cors option.

Security Best Practices

  • Always SSL/TLS - ideally behind well proven reverse proxy (I'm using nginx) (audioserve has support for SSL/TLS, but reverse proxy is probably more solid, plus can provide additional safeguards)
  • Set solid shared secret 10+ different character types ... (to prevent guessing and brute force attacks), do not run on Internet with no-authentication - it's for testing only
  • Never run audioserve as root
  • Keep audioserve updated - as I'm addressing found issues in new releases (definitely do not use older version v0.15.0, which addressed important fix)
  • in $HOME/.audoserve are couple of files that are writable by server - so they should have proper permissions - especially audioserve.secret should be be limited to user (running audioserve) access only
  • Never put any secret information into media directories - all content of these directories is potentially accessible via Web API.
  • Running in dedicated container also improves security
  • if using remote proxy limit listening (--listen argument) interface of audioserve to one reachable by remote proxy only (for instance if they are on same server use --listen 127.0.0.1:3000)
  • Optionally use your reverse proxy features like URL blocking, rate limiting etc. for additional security
  • It's good to check logs from time to time - audioserve by default logs errors (including invalid access attempt) to stderr (which can be easily redirected to file), access log of reverse proxy is also useful
  • Change shared secret (ideally in some larger (months) regular intervals, but it bit annoying), but for sure change in case you suspect it has been breached - always also delete server secret file.

Performance

Audioserve is intended to serve personal audio collections of moderate sizes. For sake of simplicity it does not provide any large scale performance optimizations. It's fine to serve couple of users from collections of couple of thousands audiobooks, if they are reasonably organized. That's it, if you're looking for solution for thousands or millions of users, look elsewhere. To compensate for this audioserve is very lightweight and by itself takes minimum of system resources.

Browsing of collections is limited by speed of the file system. As directory listing needs to read audio files metadata (duration and bitrate, eventually chapters), folders with too many files (> 200) will be slow to open. Search is done by walking through collection directory structure, it can be slow - especially the first search (subsequent searches are much, much faster, as directory structure from previous search is cached by OS for some time). Recent audioserve versions provide optional search cache, to speed up search significantly - see below.

But true limiting factor is transcoding - as it's quite CPU intensive. Normally you should run only a handful of transcodings in parallel, not much then 2x - 4x more then number of cores in the machine. For certain usage scenarios enabling of transcoding cache can help a bit.

Search Cache

For fast searches enable search cache with --search-cache, it will load directory structure of collections into memory, so searches will be blazingly fast (for price of more occupied memory). Search cache monitors directories and update itself upon changes (make take a while). Also after start of audioserve it takes some time before cache is filled (especially when large collections are used), so search might not work initially.

Transcoding Cache

Optionally you can enable transcoding cache (by compiling audioserve with transcoding-cache feature). Contribution of this cache to overall performance depends very much on usage scenarios. If there is only one user, which basically listens to audiobooks in linear order (chapter after chapter, not jumping back and forth), benefit will be minimal. If there are more users, listening to same audiobook (with same transcoding levels) and/or jumping often back and forth between chapters, then benefit of this cache can be significant. You should test to see the difference (when transcoding cache is compiled in it can be still disabled by --t-cache-disable option).

Transcoding

Audioserve offers possibility to transcode audio files to opus format (opus codec, ogg or webm container) or few other formats to save bandwidth and volume of transferred data. For transcoding to work ffmpeg program must be installed and available on system's PATH. Transcoding is provided in three variants and client can choose between them (using query parameter trans with value l,m or h):

  • low - (default 32 kbps opus with 12kHz cutoff mono)
  • medium - (default 48 kbps opus with 12kHz cutoff)
  • high - (default 64 kbps opus with 20kHz cutoff)

As already noted audioserve is intended primarily for audiobooks and believe me opus codec is excellent there even in low bitrates. However if you want to change parameters of these three transcodings you can easily do so by providing yaml confing file to argument --config. Here is sample file:

transcoding:
    low:
    opus-in-ogg:
        bitrate: 16
        compression_level: 3
        cutoff: WideBand
        mono: true
    medium:
    opus-in-ogg:
        bitrate: 24
        compression_level: 6
        cutoff: SuperWideBand
        mono: true
    high:
    opus-in-ogg:
        bitrate: 32
        compression_level: 9
        cutoff: SuperWideBand

In each key first you have specification of codec-container combination, currently it supports opus-in-ogg, opus-in-webm, mp3, aac-in-adts (but other containers or codecs can relatively easily be added, provided they are supported by ffmpeg and container creation does not require seekable output - like MP4 container).

I have good experiences with opus-in-ogg, which is also default. opus-in-webm works well in browsers (and is supported in browsers MSE API), but as it does not contain audio duration after trascoding, audio cannot be sought during playback in Android client, which is significant drawback. mp3 is classical MPEG-2 Audio Layer III audio stream. aac-in-adts is AAC encoded audio in ADTS stream, it also may have problems with seeking in Android client.

For opus transcodings there are 3 other parameters, where bitrate is desired bitrate in kbps, compression_level is determining audio quality and speed of transcoding with values 1-10 ( 1 - worst quality, but fastest, 10 - best quality, but slowest ) and cutoff is determining audio freq. bandwidth (NarrowBand => 4kHz, MediumBand => 6kHz, WideBand => 8kHz, SuperWideBand => 12kHz, FullBand => 20kHz).

For mp3 transcoding there are also 3 parameters: bitrate (in kbps), compression_level with values 0-9 (0 - best quality, slowest, 9-worst quality, fastest; so meaning is inverse then for opus codec) and abr (optional), which can be true or false (ABR = average bit rate - enables ABR, which is similar to VBR, so it can improve quality on same bitrate, however can cause problems, when seeking in audion stream).

aac-in-adts has one mandatory parameter bitrate (in kbps) and two optional parameters sr - which is sample rate of transcoded stream (8kHz, 12kHz, 16kHz, 24kHz, 32kHz, 48kHz, unlimited) and ltp (Long Term Prediction), which is true or false and can improve audio quality, especially for lower bitrates, but for significant performance costs ( abou 10x slower).

All encodings have optional parameter mono, if set to true audio will be down-mixed to mono.

Overall opus-in-ogg provides best results from both quality and functionality perspective, so I'd highly recommend to stick to it, unless you have some problem with it.

You can override one two or all three defaults, depending on what sections you have in this config file.

Command line

Audioserve can take parameters from command line, environment variables and config file. For command line arguments check them with audioserve -h. Generally you need to provide shared secrect (or option --no-authentication for public access) and root of media library (as noted above you can have severals libraries).

audioserve is server executable and it also needs web client files , which are index.html and bundle.js, which are defaultly in ./client/dist, but their location can by specified by argument -c.

For majority of command line arguments there is also appropriate environment variable, which starts with prefix AUDIOSERVE_ and then command line argument name (without leading dashes) transcribed from kebab-case to SCREAMING_SNAKE_CASE, so for instance argument --shared-secret has coresponding env. variable AUDIOSERVE_SHARED_SECRET.

All audioserve parameters can be also provided in configuration file via --config argument. Configuration file is in YAML format and somehow coresponds to command line arguments, but not exactly. Easiest way how to create config file is to use argument --print-config, which prints current configuration, including all used arguments to standard output.

Web client

Web client is bundled with server. It provides simple interface (using bootstrap 4 CSS framework and JQuery JS library). Web client will remember your last playback position in a folder, so you can easily continue listening, even after page reload. Use three vertical dots in top right corner to choose required transcoding and subfolder items ordering. Otherwise it's rather minimalistic (following KISS principle).

It's tested on Firefox and Chrome (on Linux and Android, should work on Windows, on OSX too on these browsers). On iOS default transcoding (opus+ogg) is not working - so switch transcoding off or try custom transcoding profile.

Web client is not working on MS Edge(this might be fixed in future) and IE (which will never be supported).

Android client

Android client code is available on github.

API

audioserve server provides very simple API (see api.md for documentation), so it's easy to write your own clients.

Installation

Docker Image

Easiest way how to test audioserve (but do not use --no-authentication in production) is to run it as docker container with prebuild Docker image (from Docker Hub):

docker run -d --name audioserve -p 3000:3000 -v /path/to/your/audiobooks:/audiobooks  izderadicka/audioserve --no-authentication /audiobooks

Then open http://localhost:3000 - and browse your collection. This is indeed the very minimal configuration of audioserve. For real deployment you'd like provide provide more command line parameters (or environment variables or your custom config file) - see more complex example below.

Of course you can build your own image very easily with provided Dockerfile, just run:

docker build --tag audioserve .

When building docker image you can use --build-arg CARGO_ARGS= to modify cargo build command and to add/or remove features (see below for details). For instance this command will build audioserve with transcoding cache docker build --tag audioserve --build-arg CARGO_ARGS="--features transcoding-cache" .

There is also one additional env. variable PORT - TCP port on which audioserve serves http(s) requests (defaults to: 3000) - this is useful for services like Heroku, where container must accept PORT variable from the service.

A more detailed example (audioserve is an entry point to this container, so you can use all command line arguments of the program, to get help for the program run this command docker run -it --rm izderadicka/audioserve --help):

docker run -d --name audioserve -p 3000:3000 \
    -v /path/to/your/audiobooks1:/collection1 \
    -v /path/to/your/audiobooks2:/collection2 \
    -v /path/for/audioserve-data:/home/audioserve/.audioserve \
    -e AUDIOSERVE_SHARED_SECRET=mypass \
    izderadicka/audioserve \
    --ssl-key /audioserve/ssl/audioserve.p12 --ssl-key-password mypass \
    --search-cache \
    /collection1 /collection2

In the above example, we are adding two different collections of audiobooks (collection1 and collection2). Both are made available to the container via -v option and then passed to audioserve on command line. Also we have maped with -v some folder to /home/audioserve/.audioserve, where runtime data of audioserve are stored (server secret, caches ...)

We set the shared secret via AUDIOSERVE_SHARED_SECRET env.variable and specify use of TLS via --ssl-key and ssl-key-password (the tests only self-signed key is already prebundled in the image, for real use you'll need to generate your own key, or use reverse proxy that terminates TLS). We also enable search cache with --search-cache argument.

Docker Compose Example

Here is a docker-compose example that enables search cache

---
version: "3"

services:
  audioserve:
    image: izderadicka/audioserve
    restart: unless-stopped
    command: --search-cache /audiobooks
    environment:
      - PUID=1000
      - PGID=1000
      - "AUDIOSERVE_SHARED_SECRET=VGM4oDS6wGKge9"
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - "./config:/home/audioserve/.audioserve"
      - "/path/to/Audio/Books:/audiobooks"

Static build (Linux)

Static build of audioserve is available (for rencent releases) at github releases page. You can can just download and extract locally and run on any modern x86_64 linux. You can also create your own static build with script build_static.sh (Docker is required for this)

Local build (Linux)

Now audioserve depends on ffmpeg's libavformat 4.3 (and its dependent libavutil and libavcodec libs), which is a complex beast. If you are building locally you need this dependence (plus couple of others). If you have available right version on your system you can dynamically link against it (remember it has to be correct version). Other option is to use feature partially-static, which will download right version of ffmpeg, compile it and statically link it into audioserve (but then binary will be indeed bigger).

Install required dependencies (some dependencies are optional, depending on features chosen in build):

# Ubuntu - for other distros look for equivalent packages
sudo apt-get install -y  openssl libssl-dev pkg-config\
    ffmpeg yasm build-essential wget libbz2-dev zlib1g-dev libavformat-dev

Clone repo with:

git clone https://github.com/izderadicka/audioserve

To install locally you need recent Rust and NodeJS installed.

Compile Rust code (it has optional system dependencies to openssl,zlib, bz2lib, and libavformat, as you'll not have exact correct version of libavformat around, it's better to build required version statically into binary with partially-static feature, beacause otherwise you might see problems like segfaults):

cargo build --release --features partially-static

Optionaly you can compile with/without other features (see below for details).

Build client in its directory (cd client):

npm install
npm run build

Windows build

WARNING: Windows are not officially supported - windows build instructions are contributed and resulting executable has some limitations (no features) and issues.

Clone the repository with:

git clone https://github.com/izderadicka/audioserve

or download the ZIP archive.

Download the x86_64-pc-windows-msvc version of Rust compiler from rust-lang.org. Also download and perform the default installation of the Build tools for Visual Studio. You may ignore the request to reboot the system after the installation.

Download the 4.1 "development" version of Windows 64-bit binaries of FFmpeg from the official website. Extract all /lib/*.lib files such as avcodec.lib from the archive to the C:\Program Files\Rust stable MSVC 1.43\lib\rustlib\x86_64-pc-windows-msvc\lib folder.

Open a Command prompt or a PowerShell window, change to the directory where you have previously extracted the contents of audioserve-master and run:

cargo build --release --no-default-features

After compilation, you will find the compiled binary, audioserve.exe, in the target\release sub-folder.

Next, switch to the client folder under \target\release. Install the NPM software from https://nodejs.org/en/download/ and build the client using:

npm install
npm run build

Transfer the resulting audioserve.exe with the entire contents of the client folder to the preferred location.

Known issues:

  • compilation with the --features partially-static option does not work (instead, use the shared FFmpeg libraries as described above).
  • Audioserve doesn't recognize the paths that contain drive letters (i.e. C:\) and paths with symlinks or directory junctions. Put the audioserve.exe to the same disk drive as the folder with audio files and use it with paths relative to the root of the drive. For example, if the path to the program is d:\Audioserve\audioserve.exe, its data folder is D:\Audioserve\data and your audio files are located in C:\Audiobooks\, launch the program as D:\Audioserve\audioserve.exe --no-authentication --data-dir \Audioserve\data \Audiobooks.
  • As the result of the above, you can not use the multiple folders with audio files across the different disks with Audioserve.
  • Audioserve.exe does not have an application icon.
  • The program keeps the terminal window open while it is running. To hide it, use any Windows utility that allows launching terminal programs as "Windows services" in the background.
  • Above instructions were only tested on a 64-bit Windows 10 platform.

Other platforms

Theoretically audioserve can work on MacOS (probably with only few changes in the code and building process (of libavformat)), but I never tried to build it there. Any help in this area is welcomed.

Compiling without default features or with non-default features

TLS support (feature tls), symbolic links (feature symlinks) and search cache (feature search-cache) and folder download (feature folder-download) are default features, but you can compile without them - just add --no-default-features option to cargo build command. And then evetually choose only features you need. To add non-default features (like transcoding-cache) compile with this option --features transcoding-cache in cargo build command.

Available features:

Feature Description Default Program options
tls Enables TLS support (e.g https) (requires openssl and libssl-dev) Yes --ssl-key --ssl-key-password to define server key
symlinks Enables to use symbolic links in media folders Yes Use --allow-symlinks to follow symbolic links
search-cache Caches structure of media directories for fast search Yes Use --search-cache to enable this cache
folder-download Enables API endpoint to download content of a folder in tar archive Yes Can be disabled with argument --disable-folder-download
shared-positions Clients can share recent playback positions via simple websocket API Yes
transcoding-cache Cache to save transcoded files for fast next use No Can be disabled by --t-cache-disable and modified by --t-cache-dir --t-cache-size --t-cache-max-files
behind-proxy Enable logging of client address from proxy headers No Enables argument --behind-proxy which should be use to log client address from headers provided by reverse proxy
static Enables fully static build of audioserve. Check above notes for static build No
partially-static Statically links libavformat (and related).Enables to run audioserve on systems, which do not have required version of libavformat No
folder-download-default-tar Default folder download format is tar (instead of zip) No

License

MIT

Comments
  • Disable loading meta info when open filder

    Disable loading meta info when open filder

    Thanks for your audio server. This is exactly what I am looking for: a file based stream server for audio books.

    However, I have some folders contains more than 500 files. It takes over 1 min to open that folder and Android app just timeout and make it useless.

    Is it possible to disable the loading meta code when I open the folder? I think for folder based approach, the meta data can be totally ignored until the open time.

    Thanks

    enhancement 
    opened by jiatao99 27
  • Enhancements to the API

    Enhancements to the API

    Aggregated info Book name Book author Total time sha256 hash of folder contents

    Group details Such as

    {
      "Kode": {
        "playback_speed": "1.5",
        "active_books": [
          {
            "name": "Artemis Fowl",
            "author": "Eoin Colfer",
            "folder": "Eoin Colfer/Artemis Fowl/AF01 - Artemis Fowl",
            "cover": "cover/Eoin Colfer/Artemis Fowl/AF01 - Artemis Fowl/Artemis Fowl 1 - Artemis Fowl.jpg",
            "current_position": "19827",
            "total_time": "60481",
            "hash": "263bc4f19f5e291fce24e6d4a6e4442e6f893cbabbcc737f105dff8d2cf8d845"
          },
          {
            "name": "Billionaire Boy",
            "author": "David Walliams",
            "folder": "David Walliams/Billionaire Boy",
            "cover": "cover/David Walliams/Billionaire Boy/Billionaire Boy.jpg",
            "current_position": "19827",
            "total_time": "60481",
            "hash": "123bc4f19f5e291fce24e6d4a6e4442e6f893cbabbcc737f105dff8d2cf8d375"
          }
        ],
        "finished_books": [
          "961bc4f19f5e291fce24e6d4a6e4442e6f893cbabbcc737f105dff8d2cf8d219",
          "66fc3b5726ad08f34ec7e6f9952e889d1eec1efc9180c8c48fc2e8c35373efc7"
        ]
      },
      "Bob": {
        "playback_speed": "1.2",
        "active_books": [
          {
            "name": "Artemis Fowl",
            "author": "Eoin Colfer",
            "folder": "Eoin Colfer/Artemis Fowl/AF01 - Artemis Fowl",
            "cover": "cover/Eoin Colfer/Artemis Fowl/AF01 - Artemis Fowl/Artemis Fowl 1 - Artemis Fowl.jpg",
            "current_position": "19827",
            "total_time": "60481",
            "hash": "263bc4f19f5e291fce24e6d4a6e4442e6f893cbabbcc737f105dff8d2cf8d845"
          }
        ],
        "finished_books": [
          "961bc4f19f5e291fce24e6d4a6e4442e6f893cbabbcc737f105dff8d2cf8d219",
          "66fc3b5726ad08f34ec7e6f9952e889d1eec1efc9180c8c48fc2e8c35373efc7",
          "8e5fe3893ab85cdaa606ef27061cba04238ed49e05431018fe7d6f47711f734e"
        ]
      }
    }
    

    Folder playback status Grouped by API endpoints for start and stop that log to a history, something like:

    {
      "Kode": {
        "current_position": "19827",
        "history": [
          {
            "start": "1631086131",
            "startSeek": "19327"
            "finish": "1631586131",
            "finishSeek": "19827"
          },
          {
            "start": "1633086131",
            "startSeek": "19827"
            "finish": "1633586131",
            "finishSeek": "20327"
          }
        ]
      },
      "Bob": {
        "current_position": "19827",
        "history": [
          {
            "start": "1631086131",
            "startSeek": "19327"
            "finish": "1631586131",
            "finishSeek": "19827"
          },
          {
            "start": "1633086131",
            "startSeek": "19827"
            "finish": "1633586131",
            "finishSeek": "20327"
          }
        ]
      }
    }
    

    This would work for playback on other devices as well, rather than relying on websockets, just record the latest position, then on another device load up the group information and continue from the position. Having the history is useful for situations where playback has started accidentally, you can go to your history and start playback from the last location.

    enhancement 
    opened by KodeStar 20
  • Secret not working and Android unable to connect

    Secret not working and Android unable to connect

    Firstly, I really like what's being done with this tool, and especially the app. If I can get it up and running I think it'll be perfect for me. So, thanks for making it!

    My setup is running in docker with a reverse proxy, which works fine to serve up the site, but the shared secret seems to be ignored entirely. The audioserve.secret key is being created and there is nothing in the logs to indicate any issues.

    I tried opening the port to the web and it still ignores the shared secret so it seems like it's not an issue with the reverse proxy.

    Additionally, and perhaps this is somewhat unrelated, when trying to connect to the server through the Android app I get a generic server error message, whether or not I have set a shared secret.

    If I go to the site to test out the response from the API manually, I get expected responses except where I go to /authentication and simply get 'Not Found'.

    As an aside it would be super useful to serve the API requests from a shared sub-directory such as /api so I could easily add different auth settings for the API. :)

    opened by danfickling 14
  • Preflight CORS requests are not hadled correctly

    Preflight CORS requests are not hadled correctly

    When using with --cors header and other web client, served from different location then API, and which sends preflight requests , then OPTIONS preflight for /authenticate return 401 status, thus client/web browser cannot access the endpoint

    OPTIONS requests handling has to be fixed in audioserve - especially when --cors switch is on.

    bug 
    opened by izderadicka 12
  • iOS devices - playback error

    iOS devices - playback error

    Hi,

    I'm trying to access AudioServe using iOS Safari on a 2017 IPad (latest iOS release) and get a playback error. The logs in docker show this, though I am not sure it's directly related:

    WARN audioserve::services::transcode > Transconding of file "/audiobooks/file.mp3" failed with code Some(1)

    The same file plays on android and MacOS desktop as well as Windows.

    Any help would be very appreciated.

    opened by paulmorabito 12
  • Docker image shutting down after a few days

    Docker image shutting down after a few days

    I'm running the service inside the official docker image and proxy it via nginx + let's encrypt. After a few days the process exits with status code 0 and no log output, making nginx shut down (for domain name reasons with docker-compose; but that's not the issue here).

    Is there some way I can try to debug this problem? I'm pretty confident in Rust, but it's also running on a server with limited hardware, so recompiling constantly is probably not going to work for me.

    It's happened four times now, so I'm now turning on restart: unless-stopped to work around it, but getting to the cause of the issue would be preferred by me.

    The little information I can give:

    1. Process had no output. Exit status 0.
    2. The most I've been able to have the container running at a time: Around 3 days.
    3. Service works well when it's running (although it emits a lot of warnings about upgrading websockets.
    4. Memory pressure on the server is fine. It was not killed by OOM killer according to docker inspect either.
    5. CPU usage has been low up until the service died.
    6. No problem with disk space.
    7. Server has had no network interruptions during this time.
    8. No other container (I run around 11 of them) has any similar issues.
    9. Server is my own hardware at home, not a cloud host or a VM. No hardware issues that I know of, and it's pretty new.

    I'm sorry I cannot give any more information. This "issue" is literally me asking for ideas on what to look for so I can give you better information.

    opened by Mange 11
  • Leaner Docker Image

    Leaner Docker Image

    Still a WIP. Planning to switch this to a 2-stage docker build, similar to what https://github.com/fornwall/rust-static-builder/ suggests.

    Need help with converting this to a completely static binary.

    Ideally, the ssl certs should not be built into the image. With Docker based setups, either of these two is the norm:

    1. TLS termination is handled by another service, which proxies over HTTP. You can use something like https://gilyes.com/docker-nginx-letsencrypt/ to proxy across.
    2. Terminate TLS, but instead of using insecure certificate, rely on a volume mount for administrators to mount the SSL key and certificate.
    opened by captn3m0 11
  • Getting 404 for bundle.js when behind reverse proxy with non-root path

    Getting 404 for bundle.js when behind reverse proxy with non-root path

    Using caddy as https reverse proxy. Example URL: https://my.dns.name/audioserve Browser's console: audioserve:208 | GET https://my.dns.name/bundle.js net::ERR_ABORTED 404 Though android client works ok via same reverse proxy.

    opened by zais 10
  • Don't work with docker-compose

    Don't work with docker-compose

    Hello, I install with docker-compose:

    ---
    version: "3"
    
    services:
      audioserve:
        image: izderadicka/audioserve
        restart: unless-stopped
        command: --tags /audiobooks
        environment:
          - PUID=1000
          - PGID=1000
          - "AUDIOSERVE_SHARED_SECRET=VGM4oDS6wGKge9"
        volumes:
          - /etc/localtime:/etc/localtime:ro
          - "./config:/home/audioserve/.audioserve"
          - "/mint/Seagate/Audiobooks:/audiobooks"
    

    and after enter browser I have that error:

    {"status":"OK","version":{"major":2,"minor":9,"revision":16}}
    

    Regards.

    opened by PrzemekSkw 9
  • Building for Windows 10 - 'cannot run ffmpeg build script'

    Building for Windows 10 - 'cannot run ffmpeg build script'

    Hi. I've tried to build the project on Windows.

    I've downloaded 64-bit distribution of Rust and installed it. I've also downloaded and installed Build Tools for Visual Studio 2019 (to obtain link.exe).

    I've also downloaded an FFmpeg build with shared libraries and saved its contents straight to the Windows folder.

    Build process breaks at media_info (audioserve builds just fine):

    C:\Users\sanja\Downloads\audioserve-master\audioserve-master>cargo build --release --features partially-static
       Compiling winapi v0.3.8
       Compiling proc-macro2 v1.0.9
       Compiling syn v1.0.16
       Compiling memchr v2.3.3
       Compiling fnv v1.0.6
       Compiling winapi-build v0.1.1
       Compiling log v0.4.8
       Compiling libc v0.2.67
       Compiling lazy_static v1.4.0
       Compiling bytes v0.5.4
       Compiling slab v0.4.2
       Compiling winapi v0.2.8
       Compiling futures-core v0.3.4
       Compiling byteorder v1.3.4
       Compiling itoa v0.4.5
       Compiling proc-macro-nested v0.1.3
       Compiling typenum v1.11.2
       Compiling futures-sink v0.3.4
       Compiling iovec v0.1.4
       Compiling serde v1.0.104
       Compiling pin-project-lite v0.1.4
       Compiling pin-utils v0.1.0-alpha.4
       Compiling futures-io v0.3.4
       Compiling futures-task v0.3.4
       Compiling getrandom v0.1.14
       Compiling byte-tools v0.3.1
       Compiling bitflags v1.2.1
       Compiling version_check v0.9.1
       Compiling ident_case v1.0.1
       Compiling strsim v0.9.3
       Compiling autocfg v1.0.0
       Compiling matches v0.1.8
       Compiling httparse v1.3.4
       Compiling smallvec v1.2.0
       Compiling ppv-lite86 v0.2.6
       Compiling fake-simd v0.1.2
       Compiling opaque-debug v0.2.3
       Compiling base64 v0.11.0
       Compiling quick-error v1.2.3
       Compiling ryu v1.0.2
       Compiling percent-encoding v2.1.0
       Compiling cc v1.0.50
       Compiling utf-8 v0.7.5
       Compiling derive_builder v0.9.0
       Compiling try-lock v0.2.2
       Compiling native-tls v0.2.3
       Compiling mime v0.3.16
       Compiling unicode-width v0.1.7
       Compiling linked-hash-map v0.5.2
       Compiling media_info v0.1.4 (C:\Users\sanja\Downloads\audioserve-master\audioserve-master\crates\media_info)
       Compiling tower-service v0.3.0
       Compiling regex-syntax v0.6.14
       Compiling dtoa v0.4.5
       Compiling vec_map v0.8.1
       Compiling strsim v0.8.0
       Compiling ego-tree v0.6.2
       Compiling untrusted v0.7.0
       Compiling spin v0.5.2
       Compiling bit-vec v0.6.1
       Compiling audioserve v0.12.1 (C:\Users\sanja\Downloads\audioserve-master\audioserve-master)
       Compiling data-encoding v2.2.0
       Compiling kernel32-sys v0.2.2
       Compiling ws2_32-sys v0.2.1
       Compiling thread_local v1.0.1
       Compiling input_buffer v0.3.1
       Compiling http v0.2.0
       Compiling futures-channel v0.3.4
       Compiling block-padding v0.1.5
       Compiling unicase v2.6.0
       Compiling unicode-bidi v0.3.4
       Compiling indexmap v1.3.2
       Compiling unicode-normalization v0.1.12
       Compiling humantime v1.3.0
       Compiling c2-chacha v0.2.3
       Compiling textwrap v0.11.0
       Compiling yaml-rust v0.4.3
    error: failed to run custom build command for `media_info v0.1.4 (C:\Users\sanja\Downloads\audioserve-master\audioserve-master\crates\media_info)`
    
    Caused by:
      process didn't exit successfully: `C:\Users\sanja\Downloads\audioserve-master\audioserve-master\target\release\build\media_info-8e411d9664ae1e6e\build-script-build` (exit code: 101)
    --- stderr
    thread 'main' panicked at 'cannot run ffmpeg build script: Os { code: 193, kind: Other, message: "%1 is not a valid Win32 application." }', crates\media_info\build.rs:17:23
    note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
    
    warning: build failed, waiting for other jobs to finish...
    error: build failed
    

    Unfortunately, I have zero experience with Rust, so I can only help with details but not with fixes. Any ideas on how to solve this? Thanks.

    bug help wanted windows 
    opened by Bougakov 8
  • Error creating secret permission denied -- docker linux

    Error creating secret permission denied -- docker linux

    Trying to create a docker container based on the izderadicka/audioserve:latest I continually run into a permission denied error for creating/reading the secret. I have about 8 other containers that right to similar directories using the same PGID+PUID without error (everything being under a directory for the docker user each service having it's own "config" folder). I've tried using the synology GUI updating all the info and command, I've tried sudo and nonsudo docker run commands via SSH, and tried creating the run-audioserve.sh file in the setup guide all to no avail. Does the container setup accept PUID/PGID as environment inputs or does a hardcoded PUID have to be changed somewhere to the correct value for access to said directories?

    opened by mattlev 7
  • Feature request: Mark audio files as

    Feature request: Mark audio files as "listened"/"completed"

    I want to use Audioserve for listening to podcast episodes offline (simply audio files in a directory, previously downloaded with another tool). Unlike audiobooks, podcast episodes are usually intended to be listened to only once; they are more in the nature of news, not literature.

    For this reason, Audioserve would definitely need the function not only to save the playback status, but also to mark files as completely "played"/"finished" (if necessary, with adjustable remaining time, after which an episode is considered to be completely played). Firstly, so that you know which episodes of a podcast you haven't heard yet, and secondly, so that you can remove the old, already known episodes.

    A visual marker in the web interface (✓) or a note in the title would be very helpful. The possibility of deleting the already completely played episodes directly from the application would be outstanding. Of course, a deletion function entails many risks, so a renaming function is also sufficient, i.e. played episodes should optionally receive the file name extension e.g. "_finished". In this way, you can easily delete listened episodes manually or automatically.

    Of course, these are all advanced functions and should therefore be deactivated by default so as not to confuse users. A technical implementation similar to the "Sharing playback positions" feature should be feasible, right?

    Since I have already tried out and searched a lot, I know that this function is hardly available in the self-hosting sector, so I would be all the more grateful if the super useful Audioserve could get this feature.

    For background information, see this current discussion on Reddit.

    enhancement 
    opened by WolfgangDpunkt 2
  • [Suggestion] Moving guide and use from shell and run towards compose.

    [Suggestion] Moving guide and use from shell and run towards compose.

    Hi,

    Since both docker and podman are now using compose files I think it would be nice to do the same. The benefits are:

    1. Easier deployment and auto-update solo or with other services
    2. Easier guides and support (We can see and help users adjust their compose files.) As well as the opportunity to restructure the README.md file.

    Turning something like this:

    # Security risk: Loading JSON from a remote share.
    docker run -d --name audioserve_nfs -p 3000:3000 \
            --user 1099:3000 \
            -v /mnt/share/audiobooks/cz:/audiobooks/cz \
            -v /mnt/share/audiobooks/en:/audiobooks/en \
            -v /mnt/share/audiobooks/digest:/audiobooks/digest \
            -v /mnt/share/audiobooks/audioserve/:/home/audioserve/.audioserve \
            -e AUDIOSERVE_SHARED_SECRET=yourpassword \
            izderadicka/audioserve \
                    --tags \
                    --behind-proxy \
                    --transcoding-max-parallel-processes 24 \
                    --positions-backup-file /home/audioserve/.audioserve/positions-backup.json \
                    --positions-backup-schedule "0 3 * * *" \
            /audiobooks/cz \
            /audiobooks/en \
            audiobooks/digest
    

    Into something compatible with compose. I am not versed well with docker so I am still trying to write it. Any suggestions?

    version: '3'
    services:
      audioserve:
        image: izderadicka/audioserve
        restart: always
        ser: "1099:3000"
        ports:
          - "3000:3000/tcp"
        volumes:
          - /mnt/share/audiobooks/audioserve/:/home/audioserve/.audioserve:Z
          - /mnt/share/audiobooks/en:/audiobooks/en:Z
          - /mnt/share/audiobooks/digest:/audiobooks/digest:Z
          - /mnt/share/audiobooks/cz:/audiobooks/cz:Z
        environment:
          - PUID=1099
          - GUID=3000
          - "AUDIOSERVE_SHARED_SECRET=yourpassword"
        command:
          #      - --no-authentication
          - --tags
          - --behind-proxy
          - --transcoding-max-parallel-processes
          - 24
          - --positions-backup-file
          - /home/audioserve/.audioserve/positions-backup.json
          - --positions-backup-schedule
          - "0 3 * * *"
          - /audiobooks/cz
          - /audiobooks/en
          - /audiobooks/digest
    

    Unfortunately I am stuck at:

    podman create --name=audioserve_audioserve_1 --label io.podman.compose.config-hash=123 --label io.podman.compose.project=audioserve --label io.podman.compose.version=0.0.1 --label com.docker.compose.project=audioserve --label com.docker.compose.project.working_dir=/containers/audioserve --label com.docker.compose.project.config_files=docker-compose.yml --label com.docker.compose.container-number=1 --label com.docker.compose.service=audioserve -e PUID=1099 -e GUID=3000 -e AUDIOSERVE_SHARED_SECRET=yourpassword -v /mnt/share/audiobooks/audioserve:/home/audioserve/.audioserve:Z -v /mnt/share/audiobooks/en:/audiobooks/en:Z -v /mnt/share/audiobooks/digest:/audiobooks/digest:Z -v /mnt/share/audiobooks/cz:/audiobooks/cz:Z --net audioserve_default --network-alias audioserve -p 3000:3000/tcp --restart always izderadicka/audioserve --tags --behind-proxy --transcoding-max-parallel-processes 24 --positions-backup-file /home/audioserve/.audioserve/positions-backup.json --positions-backup-schedule 0 3 * * * /audiobooks/cz /audiobooks/en /audiobooks/digest
    4acde37a155beda4fd5f111c5bb42de414cabf857b23429519de374ab15e32b0
    exit code: 0
    podman start -a audioserve_audioserve_1
    Error: unable to start container 4acde37a155beda4fd5f111c5bb42de414cabf857b23429519de374ab15e32b0: lsetxattr /mnt/share/audiobooks/digest/Discworld: operation not permitted
    exit code: 125
    

    Moving away from command-line syntax should be great for the project and systems that support compose are growing. (and CLI is still functional on docker and podman)

    What do you think?

    documentation 
    opened by BansheeHero 1
  • Raspbian 64-bit compilation failed

    Raspbian 64-bit compilation failed

    The compilation on 64-bit Rapbian took unreasonably long time and failed at the end. I didn't found any cross-compile build scripts for arm/arm64 in the repo, is it supposed to be built on Raspberry Pi? On my Raspberry Pi 3 it took more than 5 hours and didn't even succeed

    cargo build --release --features partially-static
    warning: field is never read: max_size
      --> crates/collection/src/legacy_pos.rs:30:5
       |
    30 |     pub max_size: usize,
       |     ^^^^^^^^^^^^^^^^^^^
       |
       = note: #[warn(dead_code)] on by default
    
    warning: field is never read: max_groups
      --> crates/collection/src/legacy_pos.rs:31:5
       |
    31 |     pub max_groups: usize,
       |     ^^^^^^^^^^^^^^^^^^^^^
    
    warning: collection (lib) generated 2 warnings
       Compiling audioserve v0.17.1 (/home/ivan/audioserve)
    error: could not compile audioserve
    
    Caused by:
      process didn't exit successfully: rustc --crate-name audioserve --edition=2018 src/main.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C opt-level=3 -C lto -C codegen-units=1 --cfg 'feature="async-tar"' --cfg 'feature="async-zip"' --cfg 'feature="behind-proxy"' --cfg 'feature="chrono"' --cfg 'feature="cron"' --cfg 'feature="default"' --cfg 'feature="folder-download"' --cfg 'feature="native-tls"' --cfg 'feature="partially-static"' --cfg 'feature="proxy-headers"' --cfg 'feature="shared-positions"' --cfg 'feature="symlinks"' --cfg 'feature="tls"' --cfg 'feature="tokio-native-tls"' --cfg 'feature="websock"' -C metadata=2860120b6c7e0d81 -C extra-filename=-2860120b6c7e0d81 --out-dir /home/ivan/audioserve/target/release/deps -L dependency=/home/ivan/audioserve/target/release/deps --extern anyhow=/home/ivan/audioserve/target/release/deps/libanyhow-276d9a184d92698e.rlib --extern async_tar=/home/ivan/audioserve/target/release/deps/libasync_tar-26aef9e92db5a10d.rlib --extern async_zip=/home/ivan/audioserve/target/release/deps/libasync_zip-7ec3ab6e2fe25ce1.rlib --extern bytes=/home/ivan/audioserve/target/release/deps/libbytes-d572020dcfc4a0d1.rlib --extern chrono=/home/ivan/audioserve/target/release/deps/libchrono-7c7ad26673f6b4d3.rlib --extern clap=/home/ivan/audioserve/target/release/deps/libclap-692117982c8be36a.rlib --extern collection=/home/ivan/audioserve/target/release/deps/libcollection-9957c1a2f34624a2.rlib --extern cron=/home/ivan/audioserve/target/release/deps/libcron-c18e01a37ccec476.rlib --extern csv=/home/ivan/audioserve/target/release/deps/libcsv-450d8a493eae1e7a.rlib --extern data_encoding=/home/ivan/audioserve/target/release/deps/libdata_encoding-cd76fc69adea8480.rlib --extern dirs=/home/ivan/audioserve/target/release/deps/libdirs-30268afa9bf8e5d9.rlib --extern env_logger=/home/ivan/audioserve/target/release/deps/libenv_logger-78c6c188506f9942.rlib --extern futures=/home/ivan/audioserve/target/release/deps/libfutures-71cb610fd6583228.rlib --extern headers=/home/ivan/audioserve/target/release/deps/libheaders-8ecd14bb7e80f308.rlib --extern hyper=/home/ivan/audioserve/target/release/deps/libhyper-80c35cce8602948a.rlib --extern lazy_static=/home/ivan/audioserve/target/release/deps/liblazy_static-aac7bb76c0b45d97.rlib --extern leaky_cauldron=/home/ivan/audioserve/target/release/deps/libleaky_cauldron-afb0808268331cc6.rlib --extern linked_hash_map=/home/ivan/audioserve/target/release/deps/liblinked_hash_map-b20bb9d09a3a1102.rlib --extern log=/home/ivan/audioserve/target/release/deps/liblog-a96e95a01537cd9a.rlib --extern mime=/home/ivan/audioserve/target/release/deps/libmime-0a24e1ba103da365.rlib --extern native_tls=/home/ivan/audioserve/target/release/deps/libnative_tls-947cc697e9b50567.rlib --extern nix=/home/ivan/audioserve/target/release/deps/libnix-932ff677bca8fb44.rlib --extern num_cpus=/home/ivan/audioserve/target/release/deps/libnum_cpus-9f0183789de366f7.rlib --extern percent_encoding=/home/ivan/audioserve/target/release/deps/libpercent_encoding-09aeb25ecc82db7a.rlib --extern proxy_headers=/home/ivan/audioserve/target/release/deps/libproxy_headers-3c9f1b157b8b2850.rlib --extern regex=/home/ivan/audioserve/target/release/deps/libregex-d77ad295ad8f8d89.rlib --extern ring=/home/ivan/audioserve/target/release/deps/libring-f3f5186f23cc4e03.rlib --extern serde=/home/ivan/audioserve/target/release/deps/libserde-a02a3102c02d4866.rlib --externserde_derive=/home/ivan/audioserve/target/release/deps/libserde_derive-6d8720efd22c01ee.so --extern serde_json=/home/ivan/audioserve/target/release/deps/libserde_json-ba65da9ba45ed3c5.rlib --extern serde_yaml=/home/ivan/audioserve/target/release/deps/libserde_yaml-852e4018d8048dbf.rlib --extern thiserror=/home/ivan/audioserve/target/release/deps/libthiserror-5535ecf4a0571022.rlib --extern tokio=/home/ivan/audioserve/target/release/deps/libtokio-200be3e5139c8cc3.rlib --extern tokio_native_tls=/home/ivan/audioserve/target/release/deps/libtokio_native_tls-8504518167cfa7e1.rlib --extern url=/home/ivan/audioserve/target/release/deps/liburl-b6246dc0d4296906.rlib --extern websock=/home/ivan/audioserve/target/release/deps/libwebsock-8d8824e157d7a948.rlib -L native=/home/ivan/audioserve/target/release/build/media_info-d1c5f237918ea69f/out/ffmpeg-4.3.1/libavformat -L native=/home/ivan/audioserve/target/release/build/media_info-d1c5f237918ea69f/out/ffmpeg-4.3.1/libavutil -L native=/home/ivan/audioserve/target/release/build/media_info-d1c5f237918ea69f/out/ffmpeg-4.3.1/libavcodec -L native=/home/ivan/audioserve/target/release/build/ring-50386abfa8df3669/out -L native=/home/ivan/audioserve/target/release/build/zstd-sys-3dbadd08fbb3d768/out (signal: 9, SIGKILL: kill)
    
    opened by 174n 11
  • Implement DASH support

    Implement DASH support

    I have seen other some audiobooks servers supporting HLS, it looked quite interesting, because it provides new possibilities for streaming.

    So I was thinking about DASH as more standard alternative to HLS and possibly have adaptive streams with OPUS codec,.
    There has been few articles about OPUS support in DASH, but unfortunately it does not seem to be widely available option yet, so it'll require more research

    enhancement 
    opened by izderadicka 0
  • M4B files with AAC using

    M4B files with AAC using "scalable configurations" cannot be played without transcoding

    Without transcoding, just remuxing audio stream ffmpeg fails with

    [adts @ 0x562cb448d440] Scalable configurations are not allowed in ADTS
    Could not write header for output file #0 (incorrect codec parameters ?): Invalid data found when processing input
    

    Also some information about similar problem is here https://rentry.co/n4ost From there:

    FWIW, I've got to the bottom of the problem with those specific files .. they're de-DRMed Audible AAX files, and for some reason those sampled at 44.1kHz have a bit flipped in the ESDS atom's Audio Specific Config section .. it's referred to as "dependsOnCoreCoder" in most OSS code. Flipping it back makes the file playable without transcoding.

    So question is now - is it a problem of file - incorrectly prepared? Or can we somehow fix with some additional ffmpeg params?

    Does not look as easy to fix - as for now WA is play them transcoded.

    bug 
    opened by izderadicka 2
  • Implement Subsonic API for audioserve

    Implement Subsonic API for audioserve

    This can help with limited clients - especially mobile clients - as there are already couple of Subsonic API clients. Not sure if we can match Subsonic API to audioserve, but at least it worth to research.

    enhancement low priority 
    opened by izderadicka 4
Releases(v0.22.0)
Owner
Ivan Zderadicka
Ivan Zderadicka
Program to check if stereo wav files have identical channels (faux-stereo) and convert them to mono.

zrtstr Command line application for checking WAV-files for identical channels, detecting faux-stereo files generated by some audio-editing software an

Kirill 22 Nov 6, 2022
Tools for working with MIDI files - written by All the Music LLC for musicians.

Tools for Generating and Working with MIDI Files NOTICE: This repo is under construction and is not ready for use. Once it is ready, and the other rep

null 9 Nov 17, 2022
Encrypt and decrypt files by playing melodies on your MIDI keyboard.

midicrypt Encrypt and decrypt files by playing melodies on your MIDI keyboard. Written in Rust. ❯ ./midicrypt -h midicrypt 0.1.0 NINNiT Encrypts and D

null 2 Jun 24, 2022
A small program that converts midi files to RPE (Re: Phigros Edit) Charts

Midi to RPE(Re: Phigros Edit) chart converter $ mid2json --help Usage: mid2json [OPTIONS] <MIDI_PATH> Arguments: <MIDI_PATH> Name of the input fil

液氦 4 Jun 8, 2023
Build custom songs for Pokémon Mystery Dungeon: Explorers of Sky from Soundfonts and MIDI files

skysongbuilder A tool to build custom songs for Pokémon Mystery Dungeon: Explorers of Sky from Soundfonts and MIDI files Features: Optimizations down

Adakite 3 Sep 23, 2023
envelope - a command line utility and tool to help you manage your .env files

envelope envelope is a command line utility and tool to help you manage your .env files. How it works envelope is basically a command line utility tha

Mattia Righetti 6 Oct 14, 2023
A free file hosting server that focuses on speed, reliability and security.

Triox Next Generation cloud storage server that is secure, fast, and reliable. Why Triox? ☘️ Open Source - We strongly believe in collaboration and tr

Triox 81 Nov 16, 2022
musify is a simple discord bot to play music within a voice channel, written in the rust programming language.

musify-rs musify is a simple discord bot to play music within a voice channel, written in the rust programming language. Features A simple song queue

NV6 5 Aug 14, 2022
A simple CLI audio player with strange features.

legacylisten legacylisten is a simple CLI audio player I wrote because no existing one fulfilled my needs. The main feature is that you can change how

Matthias Kaak 3 Jun 8, 2022
Simple examples to demonstrate full-stack Rust audio plugin dev with baseplug and iced_audio

iced baseplug examples Simple examples to demonstrate full-stack Rust audio plugin dev with baseplug and iced_audio WIP (The GUI knobs do nothing curr

Billy Messenger 10 Sep 12, 2022
A very simple audio synthesizer with a tuix gui

In this tutorial we'll create a very simple audio synthesiser application from scratch with a ui using tuix. The finished code for this tutorial can b

George Atkinson 24 Jan 6, 2023
🎵 A super simple VST written in Rust

DigiDist This is a simple little VST plugin, developed in Rust using the vst2 crate. It doesn't sound particularly great, but it demonstrates just how

Joe Clay 34 May 29, 2022
A simple GUI audio player written in Rust with egui. Inspired by foobar2000.

Music Player A simple GUI music player inspired by foobar2000 written in Rust using egui. The goal of this project is to learn about making gui/ nativ

Ryan Blecher 5 Sep 16, 2022
ears is a simple library to play Sounds and Musics in Rust

ears ears is a simple library to play Sounds and Musics in Rust. ears is build on the top of OpenAL and libsndfile. Provides an access to the OpenAL s

Jeremy Letang 56 Dec 1, 2022
A simple GUI rust application that keeps track of how much time you spend on each application.

TimeSpent A simple GUI rust application that keeps track of how much time you spend on each application. Installation Click here to download the Setup

Slacked Lime 4 Sep 23, 2022
🎹 Simple MIDI note repeater plugin (VST3/CLAP).

⏱️ Clockwork A simple MIDI note repeater plugin, written in Rust. ?? Showcase: (turn on audio) clockwork-showcase.mp4 ?? Manual: The user manual can b

Alexander Weichart 13 Nov 30, 2022
Drumsthesia is a simple software that helps you to learn how to play the drums (or midi controllers).

Drumsthesia A shameless copy of Neothesia adapted for e-Drums. Youtube Video Binaries for MacOS, Linux (untested) and Windows (untested). Download Scr

Rodrigo Watanabe 4 Mar 20, 2023
A very simple synth with 3 waveforms and configurable oscillators.

simple-synth This is an experimental project that implements a basic software synthesizer in Rust using the CPAL library. The synthesizer can generate

Juanma López G 6 Mar 8, 2023
Very simple, efficient, task oriented, low cognitive, Midi player and jukebox for midi instruments

Midi and Virtual Book jukebox Player A cross-platform MIDI and virtual book jukebox player. It only includes the necessary functionalities to play MID

Barrel Organ Discovery 4 Jun 29, 2023