diff --git a/config.json b/config.json index 367994a..0bb8b2d 100644 --- a/config.json +++ b/config.json @@ -6,16 +6,42 @@ "token": "!! config your very strong token here !!", "ffmpeg_threads": 1, "ffmpeg_config_list": [ - { "name": "OPUS 128k", "args": "-c:a libopus -ab 128k -vn" }, - { "name": "OPUS 96k", "args": "-c:a libopus -ab 96k -vn" }, - { "name": "OPUS 256k", "args": "-c:a libopus -ab 256k -vn" }, - { "name": "OPUS 320k", "args": "-c:a libopus -ab 320k -vn" }, - { "name": "OPUS 512k", "args": "-c:a libopus -ab 512k -vn" }, - { "name": "AAC 128k", "args": "-c:a aac -ab 128k -vn" }, - { "name": "AAC 256k", "args": "-c:a aac -ab 256k -vn" }, + { + "name": "WEBM OPUS 128k", + "args": "-c:a libopus -ab 128k -vn", + "format": "webm" + }, + { + "name": "WEBM OPUS 96k", + "args": "-c:a libopus -ab 96k -vn", + "format": "webm" + }, + { + "name": "WEBM OPUS 256k", + "args": "-c:a libopus -ab 256k -vn", + "format": "webm" + }, + { + "name": "WEBM OPUS 512k", + "args": "-c:a libopus -ab 512k -vn", + "format": "webm" + }, + { + "name": "AAC 128k", + "args": "-c:a aac -ab 128k -vn", + "format": "adts" + }, + { + "name": "AAC 256k", + "args": "-c:a aac -ab 256k -vn", + "format": "adts" + }, + { "name": "MP3 128k", "args": "-c:a mp3 -ab 128k -vn", "format": "mp3" }, + { "name": "MP3 320k", "args": "-c:a mp3 -ab 320k -vn", "format": "mp3" }, { "name": "全损音质 32k", "args": "-c:a libopus -ab 32k -vn" }, { "name": "video test", + "format": "webm", "args": "-c:a libopus -ab 128k -filter:v scale='min(640,iw)':min'(360,ih)':force_original_aspect_ratio=decrease -c:v libvpx -r 5" } ] diff --git a/main.go b/main.go index cd949f2..50fbe7f 100644 --- a/main.go +++ b/main.go @@ -5,6 +5,7 @@ import ( "flag" "log" "msw-open-music/pkg/api" + "msw-open-music/pkg/commonconfig" "os" ) @@ -14,12 +15,11 @@ func init() { flag.StringVar(&ConfigFilePath, "config", "config.json", "backend config file path") } - func main() { var err error flag.Parse() - config := api.Config{} + config := commonconfig.Config{} configFile, err := os.Open(ConfigFilePath) if err != nil { log.Fatal(err) diff --git a/pkg/api/api.go b/pkg/api/api.go index b2b0f1a..bdc6132 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -3,6 +3,7 @@ package api import ( "github.com/gorilla/sessions" "msw-open-music/pkg/database" + "msw-open-music/pkg/commonconfig" "msw-open-music/pkg/tmpfs" "net/http" "os" @@ -12,32 +13,13 @@ type API struct { Db *database.Database Server http.Server token string - APIConfig APIConfig + APIConfig commonconfig.APIConfig Tmpfs *tmpfs.Tmpfs store *sessions.CookieStore defaultSessionName string } -func NewAPIConfig() APIConfig { - apiConfig := APIConfig{} - return apiConfig -} - -type APIConfig struct { - DatabaseName string `json:"database_name"` - SingleThread bool `json:"single_thread,default=true"` - Addr string `json:"addr"` - Token string `json:"token"` - FfmpegThreads int64 `json:"ffmpeg_threads"` - FfmpegConfigList []FfmpegConfig `json:"ffmpeg_config_list"` -} - -type Config struct { - APIConfig APIConfig `json:"api"` - TmpfsConfig tmpfs.TmpfsConfig `json:"tmpfs"` -} - -func NewAPI(config Config) (*API, error) { +func NewAPI(config commonconfig.Config) (*API, error) { var err error apiConfig := config.APIConfig @@ -117,7 +99,6 @@ func NewAPI(config Config) (*API, error) { // below needs token apiMux.HandleFunc("/walk", api.HandleWalk) apiMux.HandleFunc("/reset", api.HandleReset) - apiMux.HandleFunc("/add_ffmpeg_config", api.HandleAddFfmpegConfig) mux.Handle("/api/v1/", http.StripPrefix("/api/v1", apiMux)) mux.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir("web/build")))) diff --git a/pkg/api/handle_ffmpeg_config.go b/pkg/api/handle_ffmpeg_config.go index 82b7a2e..2bfa735 100644 --- a/pkg/api/handle_ffmpeg_config.go +++ b/pkg/api/handle_ffmpeg_config.go @@ -3,20 +3,12 @@ package api import ( "encoding/json" "log" + "msw-open-music/pkg/commonconfig" "net/http" ) -type FfmpegConfig struct { - Name string `json:"name"` - Args string `json:"args"` -} - -type FfmpegConfigList struct { - FfmpegConfigList []FfmpegConfig `json:"ffmpeg_config_list"` -} - -func (api *API) GetFfmpegConfig(configName string) (FfmpegConfig, bool) { - ffmpegConfig := FfmpegConfig{} +func (api *API) GetFfmpegConfig(configName string) (commonconfig.FfmpegConfig, bool) { + ffmpegConfig := commonconfig.FfmpegConfig{} for _, f := range api.APIConfig.FfmpegConfigList { if f.Name == configName { ffmpegConfig = f @@ -30,45 +22,8 @@ func (api *API) GetFfmpegConfig(configName string) (FfmpegConfig, bool) { func (api *API) HandleGetFfmpegConfigs(w http.ResponseWriter, r *http.Request) { log.Println("[api] Get ffmpeg config list") - ffmpegConfigList := &FfmpegConfigList{ + ffmpegConfigList := &commonconfig.FfmpegConfigList{ FfmpegConfigList: api.APIConfig.FfmpegConfigList, } json.NewEncoder(w).Encode(&ffmpegConfigList) } - -type AddFfmpegConfigRequest struct { - Token string `json:"token"` - Name string `json:"name"` - FfmpegConfig FfmpegConfig `json:"ffmpeg_config"` -} - -func (api *API) HandleAddFfmpegConfig(w http.ResponseWriter, r *http.Request) { - addFfmpegConfigRequest := AddFfmpegConfigRequest{} - err := json.NewDecoder(r.Body).Decode(&addFfmpegConfigRequest) - if err != nil { - api.HandleError(w, r, err) - return - } - - // check token - err = api.CheckToken(w, r, addFfmpegConfigRequest.Token) - if err != nil { - return - } - - // check name and args not null - if addFfmpegConfigRequest.Name == "" { - api.HandleErrorString(w, r, `"ffmpeg_config.name" can't be empty`) - return - } - if addFfmpegConfigRequest.FfmpegConfig.Args == "" { - api.HandleErrorString(w, r, `"ffmpeg_config.args" can't be empty`) - return - } - - log.Println("[api] Add ffmpeg config") - - api.APIConfig.FfmpegConfigList = append(api.APIConfig.FfmpegConfigList, addFfmpegConfigRequest.FfmpegConfig) - - api.HandleOK(w, r) -} diff --git a/pkg/api/handle_stream.go b/pkg/api/handle_stream.go index d9b098d..f9d47bf 100644 --- a/pkg/api/handle_stream.go +++ b/pkg/api/handle_stream.go @@ -68,11 +68,12 @@ func (api *API) HandleGetFileStream(w http.ResponseWriter, r *http.Request) { } args := strings.Split(ffmpegConfig.Args, " ") startArgs := []string{"-threads", strconv.FormatInt(api.APIConfig.FfmpegThreads, 10), "-i", path} - endArgs := []string{"-f", "webm", "-"} + endArgs := []string{"-f", ffmpegConfig.Format, "-"} ffmpegArgs := append(startArgs, args...) ffmpegArgs = append(ffmpegArgs, endArgs...) cmd := exec.Command("ffmpeg", ffmpegArgs...) cmd.Stdout = w + // cmd.Stderr = os.Stderr err = cmd.Run() if err != nil { api.HandleError(w, r, err) @@ -127,7 +128,7 @@ func (api *API) HandlePrepareFileStreamDirect(w http.ResponseWriter, r *http.Req api.HandleErrorStringCode(w, r, `ffmpeg config not found`, 404) return } - objPath := api.Tmpfs.GetObjFilePath(prepareFileStreamDirectRequst.ID, prepareFileStreamDirectRequst.ConfigName) + objPath := api.Tmpfs.GetObjFilePath(prepareFileStreamDirectRequst.ID, ffmpegConfig) // check obj file exists exists := api.Tmpfs.Exits(objPath) @@ -179,7 +180,13 @@ func (api *API) HandleGetFileStreamDirect(w http.ResponseWriter, r *http.Request configs := q["config"] configName := configs[0] - path := api.Tmpfs.GetObjFilePath(int64(id), configName) + ffmpegConfig, ok := api.GetFfmpegConfig(configName) + if !ok { + api.HandleErrorStringCode(w, r, `ffmpeg config not found`, 404) + return + } + + path := api.Tmpfs.GetObjFilePath(int64(id), ffmpegConfig) if api.Tmpfs.Exits(path) { api.Tmpfs.Record(path) } diff --git a/pkg/commonconfig/config.go b/pkg/commonconfig/config.go new file mode 100644 index 0000000..3ffdf06 --- /dev/null +++ b/pkg/commonconfig/config.go @@ -0,0 +1,43 @@ +package commonconfig + +type Config struct { + APIConfig APIConfig `json:"api"` + TmpfsConfig TmpfsConfig `json:"tmpfs"` +} + +type APIConfig struct { + DatabaseName string `json:"database_name"` + SingleThread bool `json:"single_thread,default=true"` + Addr string `json:"addr"` + Token string `json:"token"` + FfmpegThreads int64 `json:"ffmpeg_threads"` + FfmpegConfigList []FfmpegConfig `json:"ffmpeg_config_list"` +} + +type FfmpegConfigList struct { + FfmpegConfigList []FfmpegConfig `json:"ffmpeg_config_list"` +} + +type FfmpegConfig struct { + Name string `json:"name"` + Args string `json:"args"` + Format string `json:"format"` +} + +type TmpfsConfig struct { + FileLifeTime int64 `json:"file_life_time"` + CleanerInternal int64 `json:"cleaner_internal"` + Root string `json:"root"` +} + +// Constructors for Config + +func NewAPIConfig() APIConfig { + apiConfig := APIConfig{} + return apiConfig +} + +func NewTmpfsConfig() *TmpfsConfig { + config := &TmpfsConfig{} + return config +} diff --git a/pkg/tmpfs/tmpfs.go b/pkg/tmpfs/tmpfs.go index 7551183..e4531dd 100644 --- a/pkg/tmpfs/tmpfs.go +++ b/pkg/tmpfs/tmpfs.go @@ -2,6 +2,7 @@ package tmpfs import ( "log" + "msw-open-music/pkg/commonconfig" "os" "path/filepath" "strconv" @@ -10,14 +11,14 @@ import ( ) type Tmpfs struct { - record map[string]int64 - Config TmpfsConfig - wg sync.WaitGroup + record map[string]int64 + Config commonconfig.TmpfsConfig + wg sync.WaitGroup recordLocks map[string]*sync.Mutex } -func (tmpfs *Tmpfs) GetObjFilePath(id int64, configName string) (string) { - return filepath.Join(tmpfs.Config.Root, strconv.FormatInt(id, 10) + "." + configName + ".webm") +func (tmpfs *Tmpfs) GetObjFilePath(id int64, ffmpegConfig commonconfig.FfmpegConfig) string { + return filepath.Join(tmpfs.Config.Root, strconv.FormatInt(id, 10)+"."+ffmpegConfig.Name+"."+ffmpegConfig.Format) } func (tmpfs *Tmpfs) GetLock(filename string) *sync.Mutex { @@ -35,21 +36,10 @@ func (tmpfs *Tmpfs) Unlock(filename string) { tmpfs.GetLock(filename).Unlock() } -type TmpfsConfig struct { - FileLifeTime int64 `json:"file_life_time"` - CleanerInternal int64 `json:"cleaner_internal"` - Root string `json:"root"` -} - -func NewTmpfsConfig() (*TmpfsConfig) { - config := &TmpfsConfig{} - return config -} - -func NewTmpfs(config TmpfsConfig) *Tmpfs { +func NewTmpfs(config commonconfig.TmpfsConfig) *Tmpfs { tmpfs := &Tmpfs{ - record: make(map[string]int64), - Config: config, + record: make(map[string]int64), + Config: config, recordLocks: make(map[string]*sync.Mutex), } tmpfs.wg.Add(1) @@ -61,7 +51,7 @@ func (tmpfs *Tmpfs) Record(filename string) { tmpfs.record[filename] = time.Now().Unix() } -func (tmpfs *Tmpfs) Exits(filename string) (bool) { +func (tmpfs *Tmpfs) Exits(filename string) bool { _, ok := tmpfs.record[filename] return ok } @@ -77,7 +67,7 @@ func (tmpfs *Tmpfs) Cleaner() { lock.Unlock() continue } - if now - recordTime > tmpfs.Config.FileLifeTime { + if now-recordTime > tmpfs.Config.FileLifeTime { err = os.Remove(path) if err != nil { log.Println("[tmpfs] Failed to remove file", err)