From 5e543f875686427412ac67506207fdfa03c45faa Mon Sep 17 00:00:00 2001 From: speauty Date: Sun, 2 Apr 2023 12:14:42 +0800 Subject: [PATCH] =?UTF-8?q?feat(srt):=20=E5=BC=80=E5=90=AF=E5=AD=97?= =?UTF-8?q?=E5=B9=95=E5=BC=82=E6=AD=A5=E5=A4=84=E7=90=86,=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E6=B6=88=E6=81=AF=E5=9B=9E=E6=98=BE;?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app.go | 1 + cron/detector/srt_detector.go | 158 ++++++++++++++++++++++++++++++ cron/reader/srt_reader.go | 34 ++++--- cron/translator/srt_translator.go | 27 +++-- cron/writer/srt_writer.go | 32 +++--- page/subrip_translate.go | 41 ++++---- tst/tt_srt/block.go | 4 +- 7 files changed, 238 insertions(+), 59 deletions(-) diff --git a/app.go b/app.go index e8d9ee2..6324335 100644 --- a/app.go +++ b/app.go @@ -13,6 +13,7 @@ import ( ) func main() { + //var ctx = context.Background() if err := cfg.GetInstance().Load(""); err != nil { panic(err) diff --git a/cron/detector/srt_detector.go b/cron/detector/srt_detector.go index 4d0f4ed..818d344 100644 --- a/cron/detector/srt_detector.go +++ b/cron/detector/srt_detector.go @@ -1,2 +1,160 @@ // Package detector 检测器 package detector + +import ( + "context" + "fmt" + "github.com/golang-module/carbon" + "io/fs" + "path/filepath" + "runtime" + "sync" + "translator/cron/reader" + "translator/cron/translator" + "translator/tst/tt_log" + "translator/tst/tt_translator" + _type "translator/type" + "translator/util" +) + +var ( + apiSrtDetector *SrtDetector + onceSrtDetector sync.Once +) + +func GetInstance() *SrtDetector { + onceSrtDetector.Do(func() { + apiSrtDetector = new(SrtDetector) + apiSrtDetector.init() + }) + return apiSrtDetector +} + +type StrDetectorData struct { + Translator tt_translator.ITranslator + FromLang string + ToLang string + TranslateMode _type.TranslateMode + MainTrackReport _type.LangDirection + SrtFile string + SrtDir string +} + +func (customSDD StrDetectorData) toReaderData(filePath string) *reader.SrtReaderData { + return &reader.SrtReaderData{ + FilePath: filePath, + PtrTranslatorOpts: &translator.SrtTranslatorOpts{ + Translator: customSDD.Translator, + FromLang: customSDD.FromLang, + ToLang: customSDD.ToLang, + TranslateMode: customSDD.TranslateMode, + MainTrackReport: customSDD.MainTrackReport, + }, + } +} + +type SrtDetector struct { + ctx context.Context + chanDetector chan *StrDetectorData + chanMsgDetector chan string + chanMsgRedirect chan string + maxChanDetector int +} + +func (customSD *SrtDetector) SetMsgRedirect(chanMsg chan string) { + customSD.chanMsgRedirect = chanMsg +} + +func (customSD *SrtDetector) Push(data *StrDetectorData) { + customSD.chanDetector <- data +} + +func (customSD *SrtDetector) Run(ctx context.Context) { + customSD.ctx = ctx + customSD.jobDetector() + customSD.jobMsg() + +} + +func (customSD *SrtDetector) jobDetector() { + if customSD.maxChanDetector <= 0 { + customSD.log().Warn(fmt.Sprintf("%s-%s通道的最大数量(%d)无效, 重置为5", customSD.getName(), "chanDetector", customSD.maxChanDetector)) + customSD.maxChanDetector = 5 + } + + for idx := 0; idx < customSD.maxChanDetector; idx++ { + go func(ctx context.Context, chanDetector chan *StrDetectorData, chanMsg chan string, idx int) { + coroutineName := fmt.Sprintf("检测协程(%d)", idx) + chanName := "chanDetector" + for true { + select { + case <-ctx.Done(): + customSD.log().Info(fmt.Sprintf("%s关闭(ctx.done), %s被迫退出", customSD.getName(), coroutineName)) + runtime.Goexit() + case currentData, isOpen := <-chanDetector: + timeStart := carbon.Now() + if isOpen == false && currentData == nil { + customSD.log().Info(fmt.Sprintf("%s-%s通道关闭, %s被迫退出", customSD.getName(), chanName, coroutineName)) + runtime.Goexit() + } + if currentData.SrtFile != "" { + if len(currentData.SrtFile) > 4 && currentData.SrtFile[len(currentData.SrtFile)-4:] == ".srt" { + reader.GetInstance().Push(currentData.toReaderData(currentData.SrtFile)) + chanMsg <- fmt.Sprintf("检测到文件: %s, 耗时: %d", currentData.SrtFile, carbon.Now().DiffAbsInSeconds(timeStart)) + } + } + if currentData.SrtDir != "" { + _ = filepath.Walk(currentData.SrtDir, func(path string, info fs.FileInfo, err error) error { + if info.IsDir() || !util.IsSrtFile(path) || info.Size() == 0 { // 过掉目录 或非srt文件 + return nil + } + if len(path) > 4 && path[len(path)-4:] == ".srt" { + reader.GetInstance().Push(currentData.toReaderData(path)) + chanMsg <- fmt.Sprintf("检测到文件: %s, 耗时: %d", path, carbon.Now().DiffAbsInSeconds(timeStart)) + } + return nil + }) + } + } + } + }(customSD.ctx, customSD.chanDetector, customSD.chanMsgDetector, idx) + } +} + +func (customSD *SrtDetector) jobMsg() { + go func(ctx context.Context, chanMsgDetector, chanMsgRedirect chan string) { + coroutineName := "消息协程" + chanName := "chanMsgDetector" + + for true { + select { + case <-ctx.Done(): + customSD.log().Info(fmt.Sprintf("%s关闭(ctx.done), %s被迫退出", customSD.getName(), coroutineName)) + runtime.Goexit() + case currentMsg, isOpen := <-chanMsgDetector: + if isOpen == false && currentMsg == "" { + customSD.log().Info(fmt.Sprintf("%s-%s通道关闭, %s被迫退出", customSD.getName(), chanName, coroutineName)) + runtime.Goexit() + } + if chanMsgRedirect != nil { + chanMsgRedirect <- fmt.Sprintf("当前时间: %s, 来源: %s, 信息: [%s]", carbon.Now().Layout(carbon.ShortDateTimeLayout), customSD.getName(), currentMsg) + } + customSD.log().Info(fmt.Sprintf("来源: %s, 信息: %s", customSD.getName(), currentMsg)) + } + } + }(customSD.ctx, customSD.chanMsgDetector, customSD.chanMsgRedirect) +} + +func (customSD *SrtDetector) getName() string { + return "SRT检测程序" +} + +func (customSD *SrtDetector) init() { + customSD.chanDetector = make(chan *StrDetectorData, 10) + customSD.chanMsgDetector = make(chan string, 20) + customSD.maxChanDetector = 10 +} + +func (customSD *SrtDetector) log() *tt_log.TTLog { + return tt_log.GetInstance() +} diff --git a/cron/reader/srt_reader.go b/cron/reader/srt_reader.go index 092bd63..1a6d4f6 100644 --- a/cron/reader/srt_reader.go +++ b/cron/reader/srt_reader.go @@ -5,7 +5,6 @@ import ( "context" "fmt" "github.com/golang-module/carbon" - "go.uber.org/zap" "io" "os" "runtime" @@ -42,14 +41,21 @@ func (customSRD *SrtReaderData) toTranslatorData() *translator.SrtTranslatorData } type SrtReader struct { - ctx context.Context - chanReader chan *SrtReaderData - chanMsgReader chan string - maxChanReader int + ctx context.Context + chanReader chan *SrtReaderData + chanMsgReader chan string + chanMsgRedirect chan string + maxChanReader int +} + +func (customSR *SrtReader) SetMsgRedirect(chanMsg chan string) { + customSR.chanMsgRedirect = chanMsg } func (customSR *SrtReader) Run(ctx context.Context) { customSR.ctx = ctx + customSR.jobReader() + customSR.jobMsg() } func (customSR *SrtReader) Push(data *SrtReaderData) { @@ -107,7 +113,7 @@ func (customSR *SrtReader) jobReader() { chanMsg <- fmt.Sprintf("解析文件(%s)异常, 错误: %s, 即将丢弃", currentData.FilePath, err) continue } - + currentData.PrtSrt.CntBlock = len(currentData.PrtSrt.Blocks) translator.GetInstance().Push(currentData.toTranslatorData()) chanMsg <- fmt.Sprintf( "读取文件(%s)成功, 文件名: %s, 字幕块: %d, 文件大小: %d, 耗时: %d", @@ -120,9 +126,9 @@ func (customSR *SrtReader) jobReader() { } } -func (customSR *SrtReader) RedirectMsgTo(targetChan chan string) { - go func(ctx context.Context, chanMsgReader, targetChan chan string) { - coroutineName := "消息定向协程" +func (customSR *SrtReader) jobMsg() { + go func(ctx context.Context, chanMsgReader, chanMsgRedirect chan string) { + coroutineName := "消息协程" chanName := "chanMsgReader" for true { @@ -135,17 +141,17 @@ func (customSR *SrtReader) RedirectMsgTo(targetChan chan string) { customSR.log().Info(fmt.Sprintf("%s-%s通道关闭, %s被迫退出", customSR.getName(), chanName, coroutineName)) runtime.Goexit() } - if targetChan == nil { - customSR.log().Info(fmt.Sprintf("%s未设置通道(%s)接管, 定向输出到日志", customSR.getName(), chanName), zap.String("msg", currentMsg)) + if chanMsgRedirect != nil { + chanMsgRedirect <- fmt.Sprintf("当前时间: %s, 来源: %s, 信息: [%s]", carbon.Now().Layout(carbon.ShortDateTimeLayout), customSR.getName(), currentMsg) } - targetChan <- fmt.Sprintf("当前时间: %s, 来源: %s, 信息: [%s]", carbon.Now().Layout(carbon.ShortDateTimeLayout), customSR.getName(), currentMsg) + customSR.log().Info(fmt.Sprintf("来源: %s, 信息: %s", customSR.getName(), currentMsg)) } } - }(customSR.ctx, customSR.chanMsgReader, targetChan) + }(customSR.ctx, customSR.chanMsgReader, customSR.chanMsgRedirect) } func (customSR *SrtReader) getName() string { - return "SRT写入程序" + return "SRT读取程序" } func (customSR *SrtReader) init() { diff --git a/cron/translator/srt_translator.go b/cron/translator/srt_translator.go index 8699df8..6dfa28e 100644 --- a/cron/translator/srt_translator.go +++ b/cron/translator/srt_translator.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "github.com/golang-module/carbon" - "go.uber.org/zap" "runtime" "sync" "translator/cron/writer" @@ -61,11 +60,18 @@ type SrtTranslator struct { ctx context.Context chanTranslator chan *SrtTranslatorData chanMsgTranslator chan string + chanMsgRedirect chan string maxChanTranslator int } +func (customST *SrtTranslator) SetMsgRedirect(chanMsg chan string) { + customST.chanMsgRedirect = chanMsg +} + func (customST *SrtTranslator) Run(ctx context.Context) { customST.ctx = ctx + customST.jobTranslator() + customST.jobMsg() } func (customST *SrtTranslator) Push(data *SrtTranslatorData) { @@ -132,6 +138,7 @@ func (customST *SrtTranslator) jobTranslator() { blockChunked = append(blockChunked, tmpBlockStr) tmpBlockStr = "" } + if len(blockChunked) == 0 { chanMsg <- fmt.Sprintf("字幕文件(%s)未解析到需要翻译的字幕块, 疑似增量翻译模式", currentData.PrtSrt.FileName) continue @@ -158,7 +165,7 @@ func (customST *SrtTranslator) jobTranslator() { } } } - + currentData.PrtSrt.FlagTranslated = flagTranslated if flagTranslated == false { chanMsg <- fmt.Sprintf("字幕文件(%s)未进行翻译", currentData.PrtSrt.FileName) continue @@ -174,9 +181,9 @@ func (customST *SrtTranslator) jobTranslator() { } } -func (customST *SrtTranslator) RedirectMsgTo(targetChan chan string) { - go func(ctx context.Context, chanMsgWriter, targetChan chan string) { - coroutineName := "消息定向协程" +func (customST *SrtTranslator) jobMsg() { + go func(ctx context.Context, chanMsgTranslator, chanMsgRedirect chan string) { + coroutineName := "消息协程" chanName := "chanMsgTranslator" for true { @@ -184,18 +191,18 @@ func (customST *SrtTranslator) RedirectMsgTo(targetChan chan string) { case <-ctx.Done(): customST.log().Info(fmt.Sprintf("%s关闭(ctx.done), %s被迫退出", customST.getName(), coroutineName)) runtime.Goexit() - case currentMsg, isOpen := <-chanMsgWriter: + case currentMsg, isOpen := <-chanMsgTranslator: if isOpen == false && currentMsg == "" { customST.log().Info(fmt.Sprintf("%s-%s通道关闭, %s被迫退出", customST.getName(), chanName, coroutineName)) runtime.Goexit() } - if targetChan == nil { - customST.log().Info(fmt.Sprintf("%s未设置通道(%s)接管, 定向输出到日志", customST.getName(), chanName), zap.String("msg", currentMsg)) + if chanMsgRedirect != nil { + chanMsgRedirect <- fmt.Sprintf("当前时间: %s, 来源: %s, 信息: [%s]", carbon.Now().Layout(carbon.ShortDateTimeLayout), customST.getName(), currentMsg) } - targetChan <- fmt.Sprintf("当前时间: %s, 来源: %s, 信息: [%s]", carbon.Now().Layout(carbon.ShortDateTimeLayout), customST.getName(), currentMsg) + customST.log().Info(fmt.Sprintf("来源: %s, 信息: %s", customST.getName(), currentMsg)) } } - }(customST.ctx, customST.chanMsgTranslator, targetChan) + }(customST.ctx, customST.chanMsgTranslator, customST.chanMsgRedirect) } func (customST *SrtTranslator) getName() string { diff --git a/cron/writer/srt_writer.go b/cron/writer/srt_writer.go index 149dbd6..234994f 100644 --- a/cron/writer/srt_writer.go +++ b/cron/writer/srt_writer.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "github.com/golang-module/carbon" - "go.uber.org/zap" "os" "runtime" "sync" @@ -32,14 +31,21 @@ type SrtWriterData struct { } type SrtWriter struct { - ctx context.Context - chanWriter chan *SrtWriterData - chanMsgWriter chan string - maxChanWriter int + ctx context.Context + chanWriter chan *SrtWriterData + chanMsgWriter chan string + chanMsgRedirect chan string + maxChanWriter int +} + +func (customSW *SrtWriter) SetMsgRedirect(chanMsg chan string) { + customSW.chanMsgRedirect = chanMsg } func (customSW *SrtWriter) Run(ctx context.Context) { customSW.ctx = ctx + customSW.jobWriter() + customSW.jobMsg() } func (customSW *SrtWriter) Push(data *SrtWriterData) { @@ -96,10 +102,10 @@ func (customSW *SrtWriter) jobWriter() { } } -func (customSW *SrtWriter) RedirectMsgTo(targetChan chan string) { - go func(ctx context.Context, chanMsgWriter, targetChan chan string) { - coroutineName := "消息定向协程" - chanName := "chanWriter" +func (customSW *SrtWriter) jobMsg() { + go func(ctx context.Context, chanMsgWriter, chanMsgRedirect chan string) { + coroutineName := "消息协程" + chanName := "chanMsgWriter" for true { select { @@ -111,13 +117,13 @@ func (customSW *SrtWriter) RedirectMsgTo(targetChan chan string) { customSW.log().Info(fmt.Sprintf("%s-%s通道关闭, %s被迫退出", customSW.getName(), chanName, coroutineName)) runtime.Goexit() } - if targetChan == nil { - customSW.log().Info(fmt.Sprintf("%s未设置通道(%s)接管, 定向输出到日志", customSW.getName(), chanName), zap.String("msg", currentMsg)) + if chanMsgRedirect != nil { + chanMsgRedirect <- fmt.Sprintf("当前时间: %s, 来源: %s, 信息: [%s]", carbon.Now().Layout(carbon.ShortDateTimeLayout), customSW.getName(), currentMsg) } - targetChan <- fmt.Sprintf("当前时间: %s, 来源: %s, 信息: [%s]", carbon.Now().Layout(carbon.ShortDateTimeLayout), customSW.getName(), currentMsg) + customSW.log().Info(fmt.Sprintf("来源: %s, 信息: %s", customSW.getName(), currentMsg)) } } - }(customSW.ctx, customSW.chanMsgWriter, targetChan) + }(customSW.ctx, customSW.chanMsgWriter, customSW.chanMsgRedirect) } func (customSW *SrtWriter) getName() string { diff --git a/page/subrip_translate.go b/page/subrip_translate.go index 483a7fb..5da809a 100644 --- a/page/subrip_translate.go +++ b/page/subrip_translate.go @@ -1,14 +1,17 @@ package page import ( + "context" "errors" "fmt" - "github.com/golang-module/carbon" "github.com/lxn/walk" . "github.com/lxn/walk/declarative" "sync" + "translator/cron/detector" + "translator/cron/reader" + "translator/cron/translator" + "translator/cron/writer" "translator/domain" - "translator/task" "translator/tst/tt_translator/ling_va" "translator/tst/tt_ui/handle" "translator/tst/tt_ui/msg" @@ -30,6 +33,15 @@ func GetSubripTranslate() *SubripTranslate { apiSubripTranslate.name = "字幕翻译" apiSubripTranslate.engines = domain.GetTranslators().GetNames() apiSubripTranslate.chanLog = make(chan string, 128) + detector.GetInstance().SetMsgRedirect(apiSubripTranslate.chanLog) + translator.GetInstance().SetMsgRedirect(apiSubripTranslate.chanLog) + + ctx := context.Background() + detector.GetInstance().Run(ctx) + reader.GetInstance().Run(ctx) + translator.GetInstance().Run(ctx) + writer.GetInstance().Run(ctx) + apiSubripTranslate.cronSyncLog() }) @@ -207,14 +219,13 @@ func (customPage *SubripTranslate) eventBtnTranslate() { msg.Err(customPage.mainWindow, errors.New("请选择字幕文件或目录, 优先使用字幕文件")) return } - no := util.Uid() - tTranslate := new(task.Translate). - SetTaskNo(no). - SetTranslator(currentEngine). - SetFromLang(fromLang).SetToLang(toLang). - SetTranslateMode(_type.TranslateMode(mode)).SetMainTrackReport(_type.LangDirection(mainTrackExport)). - SetSrtFile(strFile).SetSrtDir(strDir). - SetChanLog(customPage.chanLog) + + detector.GetInstance().Push(&detector.StrDetectorData{ + Translator: currentEngine, FromLang: fromLang, ToLang: toLang, + TranslateMode: _type.TranslateMode(mode), MainTrackReport: _type.LangDirection(mainTrackExport), + SrtFile: strFile, SrtDir: strDir, + }) + if customPage.ptrSrtFile != nil { _ = customPage.ptrSrtFile.SetText("") } @@ -223,17 +234,7 @@ func (customPage *SubripTranslate) eventBtnTranslate() { _ = customPage.ptrSrtDir.SetText("") } msg.Info(customPage.mainWindow, "投递任务成功") - customPage.appendToLog(fmt.Sprintf( - "[%s] 投递任务[编号: %s]成功[引擎: %s, 来源语种: %s, 目标语种: %s, 翻译模式: %s, 导出主轨道: %s, 字幕文件: %s, 字幕目录: %s]", - carbon.Now().Layout(carbon.DateTimeLayout), no, currentEngine.GetName(), - currentEngine.GetLangSupported()[customPage.ptrFromLang.CurrentIndex()].Name, - currentEngine.GetLangSupported()[customPage.ptrToLang.CurrentIndex()].Name, - mode, mainTrackExport, strFile, strDir, - )) - go func() { - tTranslate.Run() - }() return } diff --git a/tst/tt_srt/block.go b/tst/tt_srt/block.go index b33ee3b..8c418ce 100644 --- a/tst/tt_srt/block.go +++ b/tst/tt_srt/block.go @@ -84,10 +84,10 @@ func (customB *SrtBlock) encode(flagInverse bool) []byte { blockStr := fmt.Sprintf("%d\n%s %s %s\n", customB.SeqNo, customB.TimeStart, customB.TimeSep, customB.TimeEnd) if flagInverse == false || customB.SubTrack == "" { - blockStr = fmt.Sprintf("%s%s\n%s", blockStr, customB.MainTrack, customB.SubTrack) + blockStr = fmt.Sprintf("%s%s\n%s\n", blockStr, customB.MainTrack, customB.SubTrack) return []byte(blockStr) } - blockStr = fmt.Sprintf("%s%s\n%s", blockStr, customB.SubTrack, customB.MainTrack) + blockStr = fmt.Sprintf("%s%s\n%s\n", blockStr, customB.SubTrack, customB.MainTrack) return []byte(blockStr) }