diff --git a/config/config.go b/config/config.go index ed9f14a..28617cb 100755 --- a/config/config.go +++ b/config/config.go @@ -74,6 +74,8 @@ type Config struct { FFmpegVp9Width int64 FFmpegH264Height int64 FFmpegH264Width int64 + + PluginPgsServer string } type PublicConfig struct { diff --git a/configdb/configdb.go b/configdb/configdb.go index 7fa2a32..266feca 100644 --- a/configdb/configdb.go +++ b/configdb/configdb.go @@ -79,6 +79,8 @@ func Setup() { config.ENV.FFmpegH264Height = getEnvDb_int64(&setting.FFmpegH264Height, 480) config.ENV.FFmpegH264Width = getEnvDb_int64(&setting.FFmpegH264Width, 854) + config.ENV.PluginPgsServer = getEnvDb(&setting.PluginPgsServer, "http://127.0.0.1:5000") + // validate config before saving validate := validator.New(validator.WithRequiredStructEnabled()) err := validate.Struct(&setting) diff --git a/logic/CreateFile.go b/logic/CreateFile.go index 14ef812..c08f1a2 100755 --- a/logic/CreateFile.go +++ b/logic/CreateFile.go @@ -100,9 +100,7 @@ func CreateFile(fromFile *string, toFolder uint, fileName string, fileId string, //loop over subtitles in file for _, streamInfo := range dataSubtitleStreams { - if streamInfo.CodecName != "hdmv_pgs_subtitle" { - subtitleStreams = append(subtitleStreams, streamInfo) - } + subtitleStreams = append(subtitleStreams, streamInfo) } //check if video stream exists @@ -220,7 +218,6 @@ func CreateFile(fromFile *string, toFolder uint, fileName string, fileId string, } // log.Printf("subtitleName: %s / subtitleLang: %s", subtitleStream.Tags.Title, subtitleStream.Tags.Language) - for _, subOpt := range models.AvailableSubtitles { // generate unique identifier for subtitle subtitleId := uuid.NewString() @@ -247,6 +244,7 @@ func CreateFile(fromFile *string, toFolder uint, fileName string, fileId string, return http.StatusInternalServerError, nil, false, echo.ErrInternalServerError } } + } // save audio data to database so they can be converted later diff --git a/models/Setting.go b/models/Setting.go index 5f2ef32..32803d4 100644 --- a/models/Setting.go +++ b/models/Setting.go @@ -68,4 +68,6 @@ type Setting struct { FFmpegVp9Width string `validate:"required,number,min=1"` FFmpegH264Height string `validate:"required,number,min=1"` FFmpegH264Width string `validate:"required,number,min=1"` + + PluginPgsServer string `validate:"required,http_url"` } diff --git a/services/Encoder.go b/services/Encoder.go index 149ef07..a2d872b 100755 --- a/services/Encoder.go +++ b/services/Encoder.go @@ -19,6 +19,7 @@ import ( "time" "github.com/google/uuid" + "github.com/imroc/req/v3" "gorm.io/gorm" ) @@ -359,7 +360,7 @@ func runEncodeQuality(encodingTask models.Quality) { encodingTask.Encoding = false encodingTask.Failed = true inits.DB.Save(&encodingTask) - log.Printf("Error happend while encoding: %v", err.Error()) + log.Printf("Error happend while encoding quality: %v", err.Error()) log.Println(ffmpegCommand) return } @@ -471,7 +472,7 @@ func runEncodeAudio(encodingTask models.Audio) { encodingTask.Encoding = false encodingTask.Failed = true inits.DB.Save(&encodingTask) - log.Printf("Error happend while encoding: %v", err.Error()) + log.Printf("Error happend while encoding audio: %v", err.Error()) log.Println(ffmpegCommand) return } @@ -502,33 +503,70 @@ func runEncodeSub(encodingTask models.Subtitle) { var ffmpegCommand string = "echo Subencoding type didnt match && exit 1" - switch encodingTask.Type { - case "ass": - ffmpegCommand = "ffmpeg " + - fmt.Sprintf("-i %s ", absFileInput) + // input file - "-an " + // disable audio - "-vn " + // disable video stream - fmt.Sprintf("-map 0:s:%d ", encodingTask.Index) + // mapping first audio stream - fmt.Sprintf("-c:s %s ", encodingTask.Codec) + // setting audio codec - fmt.Sprintf("%s/%s ", absFolderOutput, encodingTask.OutputFile) + // output file - fmt.Sprintf("-progress unix://%s -y", TempSock( - totalDuration, - fmt.Sprintf("%x", sha256.Sum256([]byte(uuid.NewString()))), - &encodingTask, - )) // progress tracking - case "vtt": - ffmpegCommand = "ffmpeg " + - fmt.Sprintf("-i %s ", absFileInput) + // input file - "-an " + // disable audio - "-vn " + // disable video stream - fmt.Sprintf("-map 0:s:%d ", encodingTask.Index) + // mapping first audio stream - fmt.Sprintf("-c:s %s ", encodingTask.Codec) + // setting audio codec - fmt.Sprintf("%s/%s ", absFolderOutput, encodingTask.OutputFile) + // output file - fmt.Sprintf("-progress unix://%s -y", TempSock( - totalDuration, - fmt.Sprintf("%x", sha256.Sum256([]byte(uuid.NewString()))), - &encodingTask, - )) // progress tracking + if encodingTask.OriginalCodec == "hdmv_pgs_subtitle" { + // prepocess pgs + if err := prepocessPgs(encodingTask, absFolderOutput, &absFileInput); err != nil { + log.Printf("[Preprocess Error] %v", err) + encodingTask.Ready = false + encodingTask.Encoding = false + encodingTask.Failed = true + inits.DB.Save(&encodingTask) + return + } + defer os.Remove(absFileInput) // delete srt file after encode + + switch encodingTask.Type { + case "ass": + ffmpegCommand = "ffmpeg " + + fmt.Sprintf("-i %s ", absFileInput) + // input file + fmt.Sprintf("-c:s %s ", encodingTask.Codec) + // setting audio codec + fmt.Sprintf("%s/%s ", absFolderOutput, encodingTask.OutputFile) + // output file + fmt.Sprintf("-progress unix://%s -y", TempSock( + totalDuration, + fmt.Sprintf("%x", sha256.Sum256([]byte(uuid.NewString()))), + &encodingTask, + )) // progress tracking + case "vtt": + ffmpegCommand = "ffmpeg " + + fmt.Sprintf("-i %s ", absFileInput) + // input file + fmt.Sprintf("-c:s %s ", encodingTask.Codec) + // setting audio codec + fmt.Sprintf("%s/%s ", absFolderOutput, encodingTask.OutputFile) + // output file + fmt.Sprintf("-progress unix://%s -y", TempSock( + totalDuration, + fmt.Sprintf("%x", sha256.Sum256([]byte(uuid.NewString()))), + &encodingTask, + )) // progress tracking + } + } else { + // normal subtitles + switch encodingTask.Type { + case "ass": + ffmpegCommand = "ffmpeg " + + fmt.Sprintf("-i %s ", absFileInput) + // input file + "-an " + // disable audio + "-vn " + // disable video stream + fmt.Sprintf("-map 0:s:%d ", encodingTask.Index) + // mapping first audio stream + fmt.Sprintf("-c:s %s ", encodingTask.Codec) + // setting audio codec + fmt.Sprintf("%s/%s ", absFolderOutput, encodingTask.OutputFile) + // output file + fmt.Sprintf("-progress unix://%s -y", TempSock( + totalDuration, + fmt.Sprintf("%x", sha256.Sum256([]byte(uuid.NewString()))), + &encodingTask, + )) // progress tracking + case "vtt": + ffmpegCommand = "ffmpeg " + + fmt.Sprintf("-i %s ", absFileInput) + // input file + "-an " + // disable audio + "-vn " + // disable video stream + fmt.Sprintf("-map 0:s:%d ", encodingTask.Index) + // mapping first audio stream + fmt.Sprintf("-c:s %s ", encodingTask.Codec) + // setting audio codec + fmt.Sprintf("%s/%s ", absFolderOutput, encodingTask.OutputFile) + // output file + fmt.Sprintf("-progress unix://%s -y", TempSock( + totalDuration, + fmt.Sprintf("%x", sha256.Sum256([]byte(uuid.NewString()))), + &encodingTask, + )) // progress tracking + } } cmd := exec.Command( @@ -560,7 +598,7 @@ func runEncodeSub(encodingTask models.Subtitle) { encodingTask.Encoding = false encodingTask.Failed = true inits.DB.Save(&encodingTask) - log.Printf("Error happend while encoding: %v", err.Error()) + log.Printf("Error happend while encoding subtitle: %v", err.Error()) log.Println(ffmpegCommand) return } @@ -643,3 +681,51 @@ func deleteActiveEncoding(fileID uint, ID uint, Type string) { ActiveEncodings = helpers.RemoveFromArray(ActiveEncodings, foundIndex) } + +func prepocessPgs(encodingTask models.Subtitle, absFolderOutput string, absFileInput *string) error { + + ffmpegOutputFile := fmt.Sprintf("%s.sup", encodingTask.OutputFile) + ffmpegOutputFilePath := fmt.Sprintf("%s/%s", absFolderOutput, ffmpegOutputFile) + pgsOutputFilePath := fmt.Sprintf("%s/%s.srt", absFolderOutput, encodingTask.OutputFile) + defer os.Remove(ffmpegOutputFilePath) + + ffmpegCommand := "ffmpeg -y " + + fmt.Sprintf("-i %s ", *absFileInput) + // input file + "-an " + // disable audio + "-vn " + // disable video stream + fmt.Sprintf("-map 0:s:%d ", encodingTask.Index) + // mapping first audio stream + fmt.Sprintf("-c:s copy ") + // setting audio codec + ffmpegOutputFilePath // output file progress + + // convert to srt + cmd := exec.Command( + "bash", + "-c", + ffmpegCommand) + if err := cmd.Start(); err != nil { + log.Println(ffmpegCommand) + return fmt.Errorf("Error happend while encoding subtitle: %v", err.Error()) + } + + pgsFile, err := os.Open(ffmpegOutputFilePath) + if err != nil { + return fmt.Errorf("Error happend while opening pgs subtitle: %v", err.Error()) + } + + client := req.C() + res, err := client.R(). + SetFileReader("file", "subtitle.sup", pgsFile). + Post(config.ENV.PluginPgsServer) + if err != nil { + return fmt.Errorf("Error happend while scanning pgs subtitle: %v", err.Error()) + } + if !res.IsSuccessState() { + return fmt.Errorf("Error happend waiting for srt from pgs plugin: %v", err.Error()) + + } + if err := os.WriteFile(pgsOutputFilePath, res.Bytes(), 0644); err != nil { + return fmt.Errorf("Error happend while saving srt from pgs: %v", err.Error()) + } + *absFileInput = pgsOutputFilePath + return nil +}