Merge branch 'dbms'

This commit is contained in:
2022-07-22 15:32:41 +08:00
67 changed files with 5090 additions and 825 deletions

387
README.md
View File

@@ -2,75 +2,98 @@
[![CI](https://github.com/heimoshuiyu/msw-open-music/actions/workflows/build.yml/badge.svg)](https://github.com/heimoshuiyu/msw-open-music/actions/workflows/build.yml)
> The best way to search for a music is to load up a huge playlist and shuffle until you find it.
A 💪 light weight ⚡️ blazingly fast 🖥️ cross platform personal music streaming platform. Manage your existing music files and enjoy them on any devices.
Front-end web application build with `react.js` and `water.css`, back-end build with `golang` and `sqlite`.
## Introduction
A light weight personal music streaming platform.
Screenshot
![demo1](demo1.jpg)
[toc]
### Features
## How to build
- 🔎 Index your existing music files, and record file name and folder information.
### Build the back-end server
- 📕 Use folder 📁 tag 🏷️ review 💬 to manage your music.
`make linux` or `make windows`
- 🌐 Provide a light weight web application with multi-language support.
The executable file is named `msw-open-music` or `msw-open-music.exe`
- 👥 Multi-user support.
### Build the font-end web pages
- 🔥 Call `ffmpeg` with customizable preset to stream your music.
To build production web page `make web`
- 🔗 Share music with others!
This command will go into `web` directory and install `node_modules`. Then execute `npm run build` command. The built web pages is under `web/build` directory.
### Try it if you...
To start the development, run `cd web` and `npm start`
- Already saved a lot of music files on disk. 🖴
- Downloaded tons of huge lossless music. 🎵
- Wants to stream your music files from PC/Server to PC/phone. 😋
- Wants to share your stored music. 😘
## Usage
Start back-end server. Server will listen on 8080 port.
1. Modify the `secret` in `config.json`
Build the font-end web page, then go to <http://127.0.0.1:8080>
2. Run back-end server `msw-open-music.exe` or `msw-open-music`. Server will listen on 8080 port by default. Then open <http://127.0.0.1:8080> to setup first admin account.
By default:
The front-end HTML files are under `web/build`
- URL matched `/api/*` will process by back-end server.
- Others URL matched `/*` will be served files under `web/build/`
### Setup first admin account
### Run back-end server
The first administrator account will be active automatically, other administrator accounts need active manually.
Configuration file is `config.json` **Please modify your `token`**
Go to register page, select the role to admin, and register the first admin account.
Default `ffmpeg_threads` is 1. Seems value larger than 1 will not increase the audio encode speed.
#### config.json
#### config.json description
- `secret` string type. Secret to encrypt the session.
- `database_name` string type. The filename of `sqlite3` database. Will create if that file doesn't exist.
- `addr` string type. The listen address and port.
- `token` string type. Password.
- `ffmpeg_config_list` list type, include `ffmpegConfig` object.
- `file_life_time` integer type (second). Life time for temporary file. If the temporary file is not accessed for more than this time, back-end server will delete this file.
- `cleaner_internal` integer type (second). Interval for `tmpfs` checking temporary file.
- `root` string type. Directory to store temporary files. Default is `/tmp`, **please modify this directory if you are using Windows.**
- `root` string type. Directory to store temporary files. Default is `/tmp`, **please modify this directory if you are using Windows.** Directory will be created if not exists.
### Run font-end web page
For windows user, make sure you have `ffmpeg` installed.
Open your web browser to <http://127.0.0.1:8080> you will see the web pages.
## Development
## About tmpfs
Any issues or pull requests are welcome.
If the `Prepare` mode is enabled in the font-wed player, back-end server will convert the whole file into the temporary folder, then serve file using native method. This can avoid ffmpeg pipe break problem cause by unstable network connection while streaming audio.
### Major changes log
- `v1.0.0` First version. Implement the core streaming function.
- `v1.1.0` Use `React` to rewrite the font-end web pages.
- `v1.2.0` Add user, tag, review and other functions for DBMS course project.
### ER Diagram
Database Entities Relationship Diagram
![ER Diagram](erdiagram.png)
- `avatar` is not using currently
- The first time you run the program, the server will create an anonymous user with id `1`. All users who are not logged in will be automatically logged in to this account.
- `tmpfs` is store in memory, which will be empty everytime server restart.
### About tmpfs
If the `Prepare` mode is enabled in the font-wed player, back-end server will convert the whole file into the temporary folder, then serve file. This can avoid `ffmpeg` pipe break problem cause by unstable network connection while streaming audio.
The default temporary folder is `/tmp`, which is a `tmpfs` file system in Linux operating system. Default life time for temporary files is 600 seconds (10 minutes). If the temporary file is not accessed for more than this time, back-end server will delete this file.
## Change log
- `v1.0.0` First version. Ready to use in production environment.
- `v1.1.0` Use `React` to rewrite the font-end web pages (Previous using `Vue`).
## Back-end API references
API named `stream` means it transfer data using `io.Copy`, which **DO NOT** support continue getting a partially-downloaded audio.
### Back-end API design
API does not need to respond any data will return the following JSON object.
@@ -80,296 +103,22 @@ API does not need to respond any data will return the following JSON object.
}
```
### Anonymous API
Sometime errors happen, server will return the following JSON object, which `error` is the detailed error message.
Anonymous API can be called by anonymous.
```json
{
"error": "Wrong password"
}
```
- `/api/v1/hello` Just for test purpose.
API does not need to send any data should use `GET` method, otherwise use `POST` method.
- `/api/v1/get_file` Get a file with `stream` mode.
Server use cookies to authenticate a user. Any request without cookies will be consider from an anonymous user (aka. user with ID `1`).
- Request example
Some important source code files:
```json
{
"id": 123
}
```
- `pkg/api/api.go` define URL
- `/api/v1/get_file_direct` Get a file with standart `http` methods, implement by `http.ServeFile` method.
- `pkg/database/sql_stmt.go` define SQL queries and do the init job.
- Request example
`/api/v1/get_file_direct?id=30`
- `/api/v1/search_files` Search files by filename.
- Request example
```json
{
"filename": "miku",
"limit": 10,
"offset" 0
}
```
Search all files' name like `%miku%`. `%` is the wildcard in SQL. For example, `"filename": "miku%hatsune"` can match `hatsune miku`.
`limit` Numbers of files in the respond. Should be within 1 - 10;
`offset` It is the offset of the result, related to the page turning function.
- Respond example
```json
{
"files": [
{
"id": 30,
"folder_id": 100,
"folder_name": "wonderful",
"filename": "memories.flac",
"filesize": 1048576
},
{
"id": 31,
"folder_id": 100,
"folder_name": "wonderful",
"filename": "memories (instrunment).flac",
"filesize": 1248531
}
]
}
```
`id` Identification of file.
`folder_id` Identification of folder.
`foldername` Folder name where the file in.
`filename` File name.
`filesize` File size, unit is byte.
- `/api/v1/search_folders` Search folders.
- Request example.
```json
{
"foldername": "miku",
"limit": 10,
"offset": 0,
}
```
Search all folders' name like `%miku%`. `%` is the wildcard in SQL. For example, `"filename": "miku%hatsune"` can match `hatsune miku`.
`limit` Numbers of files in the respond. Should be within 1 - 10;
`offset` It is the offset of the result, related to the page turning function.
- Respond example
```json
{
"folders": [
{
"id": 100,
"foldername": "folder name"
},
{
"id": 101,
"foldername": "folder name (another)"
}
]
}
```
`id` Identification of folder.
`foldername` Folder name.
- `/api/v1/get_files_in_folder` Get files in a specify folder.
- Request example.
```json
{
"folder_id": 123,
"limit": 10,
"offset": 0
}
```
- Respond example.
Same with `/api/v1/search_files`
- `/api/v1/get_random_files` Randomly get 10 files.
- Request example.
GET `/api/v1/get_random_files`
- Respond example.
Same with `/api/v1/search_files`
- `/api/v1/get_file_stream`
Stream file with a ffmpeg config name.
- Request example.
GET `/api/v1/get_file_stream?id=123&config=OPUS%20128k`
- `/api/v1/get_ffmpeg_config_list`
Get ffmpeg config list
- Request example
GET `/api/v1/get_ffmpeg_config_list`
- Respond example
```json
{
"ffmpeg_config_list": [
{"name": "OPUS 256k", "args": "-c:a libopus -ab 256k"},
{"name": "WAV", "args": "-c:a wav"}
]
}
```
- `/api/v1/feedback` Send a feedback.
- Request example
```json
{
"feedback": "some suggestions..."
}
```
- Respond OK.
- `/api/v1/get_file_info` Get information of a specify file.
- Request example.
```json
{
"ID": 123
}
```
- Respond example.
```json
{
"id": 30,
"folder_id": 100,
"folder_name": "wonderful",
"filename": "memories.flac",
"filesize": 1048576
},
```
- `/api/v1/get_file_stream_direct` Get a ffmpeg converted file with native http method. This API support continue getting a partially-downloaded audio. Note, you should call `/api/v1/prepare_file_stream_direct` first and wait for its respond, then call this API.
- Request example
GET `/api/v1/get_file_stream_direct?id=123&config=OPUS%20128k`
- `/api/v1/prepare_file_stream_direct` Ask server to convert a file with specific ffmpeg config name. When the conver process is finished, server will reply with the converted file size.
- Request example
```json
{
"id": 123,
"config_name": "OPUS 128k"
}
```
- Respond example
```json
{
"filesize": 1973241
}
```
### API needs token
- `/api/v1/walk` Walk directory, add all files and folders to database.
- Request example
```json
{
"token": "your token",
"root": "/path/to/root",
"pattern": [".wav", ".flac"]
}
```
`token` The token in `config.json` file.
`root` Root directory server will walk throught
`pattern` A list of pattern that files ends with. Only files matched a pattern in list will be add to database.
- Respond OK
- `/api/v1/reset` Rest the **files and folders table**
- Request example
```json
{
"token": "your token"
}
```
- Respond OK
- `/api/v1/add_ffmpeg_config` Add ffmpeg config.
Will be changed in future.
- Request example
```json
{
"token": "your token",
"name": "OPUS",
"ffmpeg_config": {
"args": "-c:a libopus -ab 256k"
}
}
```
`name` Name of the ffmpeg config.
`ffmpeg_config`
`args`
- Respond OK
## Font-end API references
Currently only few APIs in font-end.
- `/#/files/39/share`
Share a specific file.
- `/#/folders/2614`
Show files in a specific folder.
- `pkg/database/struct.go` define JSON structures for database entities.