From 79f40d4f7bedf2554d072f6ded4eb73373dd7319 Mon Sep 17 00:00:00 2001 From: b5f0d6c3 Date: Fri, 6 May 2022 10:46:55 +0800 Subject: update --- mkvlib/c/exports.go | 26 +++++++++++ mkvlib/mkv.go | 128 +++++++++++++++++++++++++++++++++++----------------- mkvlib/shared.go | 13 +++++- mkvtool/main.go | 15 +++--- mkvtool/utils.go | 28 ------------ 5 files changed, 134 insertions(+), 76 deletions(-) diff --git a/mkvlib/c/exports.go b/mkvlib/c/exports.go index 1c12825..fc5965d 100644 --- a/mkvlib/c/exports.go +++ b/mkvlib/c/exports.go @@ -215,6 +215,32 @@ func GetFontInfo(p *C.char) *C.char { return cs(string(data)) } +//export Version +func Version() *C.char { + return cs(mkvlib.Version()) +} + +//export CreateBlankOrBurnVideo +func CreateBlankOrBurnVideo(t int64, s, enc, ass, fontdir, output *C.char) bool { + if !checkInstance() { + return false + } + return getter.GetProcessorInstance().CreateBlankOrBurnVideo(t, gs(s), gs(enc), gs(ass), gs(fontdir), gs(output)) +} + +//export CreateTestVideo +func CreateTestVideo(asses, s, fontdir, enc *C.char, burn bool, lcb C.logCallback) bool { + if !checkInstance() { + return false + } + obj := make([]string, 0) + if json.Unmarshal([]byte(gs(asses)), &obj) == nil { + _asses := obj + return getter.GetProcessorInstance().CreateTestVideo(_asses, gs(s), gs(fontdir), gs(enc), burn, _lcb(lcb)) + } + return false +} + func cs(gs string) *C.char { return C.CString(gs) } diff --git a/mkvlib/mkv.go b/mkvlib/mkv.go index 73a16fd..bd4ed00 100644 --- a/mkvlib/mkv.go +++ b/mkvlib/mkv.go @@ -15,6 +15,7 @@ const ( mkvmerge = `mkvmerge` mkvextract = `mkvextract` ass2bdnxml = `ass2bdnxml` + ffmpeg = `ffmpeg` ) type mkvInfo struct { @@ -43,6 +44,7 @@ type mkvProcessor struct { pf string caches []string ass2bdnxml bool + ffmpeg bool nrename bool check bool strict bool @@ -396,57 +398,101 @@ func (self *mkvProcessor) NRename(nrename bool) { self.nrename = nrename } -func (self *mkvProcessor) CreateTestVideo(asses []string, fonts, enc, output string, lcb logCallback) bool { - _obj := new(assProcessor) +func (self *mkvProcessor) CreateBlankOrBurnVideo(t int64, s, enc, ass, fontdir, output string) bool { + if !self.ffmpeg { + return false + } args := make([]string, 0) - args = append(args, "-hide_banner", "-loglevel", "quiet") - args = append(args, "-y", "-f", "lavfi") - args = append(args, "-i", fmt.Sprintf("color=c=0x000000:s=%s:r=%s", self.pr, self.pf)) - var t time.Duration - _s := len(asses) == 1 - if _s { - t = _obj.getLength(asses[0]) - fonts = strings.ReplaceAll(fonts, `\`, `/`) - fonts = strings.ReplaceAll(fonts, `:`, `\\:`) - asses[0] = strings.ReplaceAll(asses[0], `\`, `/`) - asses[0] = strings.ReplaceAll(asses[0], `:`, `\\:`) - args = append(args, "-vf", fmt.Sprintf("subtitles=%s:fontsdir=%s", asses[0], fonts)) + args = append(args, "-y", "-hide_banner", "-loglevel", "quiet") + if enc == "" { + enc = "libx264" + } + if s == "" { + args = append(args, "-f", "lavfi") + args = append(args, "-i", fmt.Sprintf("color=c=0x000000:s=%s:r=%s", self.pr, self.pf)) } else { - for _, v := range asses { - length := _obj.getLength(v) - if length > t { - t = length - } + args = append(args, "-i", s) + } + if ass != "" && fontdir != "" { + t = new(assProcessor).getLength(ass).Milliseconds() + fontdir = strings.ReplaceAll(fontdir, `\`, `/`) + fontdir = strings.ReplaceAll(fontdir, `:`, `\\:`) + ass = strings.ReplaceAll(ass, `\`, `/`) + ass = strings.ReplaceAll(ass, `:`, `\\:`) + args = append(args, "-vf", fmt.Sprintf("subtitles=%s:fontsdir=%s", ass, fontdir)) + } + if s == "" { + if t > 0 { + args = append(args, "-t", fmt.Sprintf("%dms", t)) + } else { + return false } } - if t == 0 { + args = append(args, "-pix_fmt", "nv12", "-crf", "18") + args = append(args, "-vcodec", enc) + args = append(args, output) + if p, err := newProcess(nil, nil, nil, "", ffmpeg, args...); err == nil { + s, err := p.Wait() + return err == nil && s.ExitCode() == 0 + } + return false +} + +func (self *mkvProcessor) CreateTestVideo(asses []string, s, fontdir, enc string, burn bool, lcb logCallback) bool { + if s == "-" { + s = "" + } + l := len(asses) + if l == 0 { return false } - args = append(args, "-t", fmt.Sprintf("%dms", t.Milliseconds())) - args = append(args, "-c:v", enc) - args = append(args, "-c:s", "copy") - d, _, _, ne := splitPath(output) - _output := path.Join(d, fmt.Sprintf("%s.mp4", ne)) - args = append(args, _output) - if p, err := newProcess(nil, os.Stdout, os.Stderr, "", "ffmpeg", args...); err == nil { - s, err := p.Wait() - ok := err == nil && s.ExitCode() == 0 - if ok && !_s { - _fonts := findFonts(fonts) - if len(_fonts) > 0 { - __output := path.Join(d, fmt.Sprintf("%s.mkv", ne)) - ok = self.CreateMKV(_output, asses, _fonts, __output, "", "", false) - } else { + if burn { + ec := 0 + for i, v := range asses { + d, _, _, ne := splitPath(v) + _output := path.Join(d, fmt.Sprintf("%s-test.mp4", ne)) + ok := self.CreateBlankOrBurnVideo(0, s, enc, v, fontdir, _output) + if !ok { + ec++ + printLog(lcb, `Failed to create the test video file: "%s"`, _output) + } + printLog(lcb, "CT (%d/%d) done.", i+1, l) + } + return ec == 0 + } + _obj := new(assProcessor) + var t time.Duration + for _, v := range asses { + _t := _obj.getLength(v) + if _t > t { + t = _t + } + } + ok := true + _fonts := findFonts(fontdir) + if len(_fonts) > 0 { + d, _, _, _ := splitPath(asses[0]) + n := randomStr(8) + _t := s == "" + if _t { + s = path.Join(d, fmt.Sprintf("%s.mp4", n)) + if !self.CreateBlankOrBurnVideo(t.Milliseconds(), "", enc, "", "", s) { ok = false + printLog(lcb, `Failed to create the temp video file: "%s".`, s) } } - if !ok || !_s { - _ = os.Remove(_output) + if ok { + output := path.Join(d, fmt.Sprintf("%s.mkv", n)) + if !self.CreateMKV(s, asses, _fonts, output, "", "", true) { + ok = false + printLog(lcb, `Failed to create the test video file: "%s".`, output) + } } - if !ok { - printLog(lcb, "Failed to create the test video file.") + if _t { + _ = os.Remove(s) } - return ok + } else { + ok = false } - return false + return ok } diff --git a/mkvlib/shared.go b/mkvlib/shared.go index 326577a..727a774 100644 --- a/mkvlib/shared.go +++ b/mkvlib/shared.go @@ -11,7 +11,7 @@ import ( ) const libName = "mkvlib" -const libVer = "v1.8.6" +const libVer = "v1.8.7" const LibFName = libName + " " + libVer @@ -52,6 +52,7 @@ func (self *processorGetter) InitProcessorInstance(lcb logCallback) bool { _, _mkvextract := exec.LookPath(mkvextract) _, _mkvmerge := exec.LookPath(mkvmerge) _, _ass2bdnxml := exec.LookPath(ass2bdnxml) + _, _ffmpeg := exec.LookPath(ffmpeg) if _ttx != nil || _pyftsubset != nil { printLog(lcb, `Missing dependency: fonttools (need "%s" & "%s").`, ttx, pyftsubset) ec++ @@ -66,11 +67,17 @@ func (self *processorGetter) InitProcessorInstance(lcb logCallback) bool { //ec++ } + if _ffmpeg != nil { + printLog(lcb, `Missing dependency: ffmpeg.`) + //ec++ + } + r := ec == 0 if r { self.checked = true self.instance = new(mkvProcessor) self.instance.ass2bdnxml = _ass2bdnxml == nil + self.instance.ffmpeg = _ffmpeg == nil } return r @@ -91,6 +98,10 @@ func printLog(lcb logCallback, f string, v ...interface{}) { } } +func Version() string { + return libVer +} + func init() { runtime.GOMAXPROCS(runtime.NumCPU()) } diff --git a/mkvtool/main.go b/mkvtool/main.go index 5ce6de8..2e2501a 100644 --- a/mkvtool/main.go +++ b/mkvtool/main.go @@ -17,7 +17,7 @@ import ( ) const appName = "MKV Tool" -const appVer = "v3.8.4" +const appVer = "v3.8.5" const tTitle = appName + " " + appVer var appFN = fmt.Sprintf("%s %s %s/%s", appName, appVer, runtime.GOOS, runtime.GOARCH) @@ -64,7 +64,9 @@ func main() { mks := false ck := false cks := false - t := false + b := false + t := "" + e := "" sl, st := "", "" af, ao := "", "" flog := "" @@ -103,6 +105,9 @@ func main() { flag.StringVar(&flog, "log", "", "Log file path.") flag.StringVar(&pf, "pf", "23.976", "PGS frame rate:23.976, 24, 25, 30, 29.97, 50, 59.94, 60 or custom fps like 15/1. (ass2pgs only)") flag.StringVar(&pr, "pr", "1920*1080", "PGS resolution:720p, 1080p, 2k, or with custom resolution like 720*480. (ass2pgs only)") + flag.StringVar(&t, "t", "", `Create test video source path(enter "-" for blank video).`) + flag.BoolVar(&b, "b", false, `Create test video with burn subtitle.`) + flag.StringVar(&e, "e", "libx264", `Create test video use encoder.`) flag.BoolVar(&v, "v", false, "Show app info.") flag.Parse() @@ -190,16 +195,14 @@ func main() { if len(*asses) > 0 { if !processer.ASSFontSubset(*asses, af, ao, !ans, nil) { ec++ - } else if t { + } else if t != "" { d, _, _, _ := splitPath((*asses)[0]) if ao == "" { ao = path.Join(d, "subsetted") } _asses, _ := findPath(ao, `\.ass$`) if len(_asses) > 0 { - p := fmt.Sprintf("test-%s.a", randomStr(8)) - p = path.Join(d, p) - processer.CreateTestVideo(_asses, ao, "nvenc_h264", p, nil) + processer.CreateTestVideo(_asses, t, ao, e, b, nil) } } return diff --git a/mkvtool/utils.go b/mkvtool/utils.go index 95bdbfb..e60afe8 100644 --- a/mkvtool/utils.go +++ b/mkvtool/utils.go @@ -2,12 +2,10 @@ package main import ( "errors" - "math/rand" "os" "path/filepath" "regexp" "strings" - "time" ) func queryPath(path string, cb func(string) bool) error { @@ -50,29 +48,3 @@ func splitPath(p string) (dir, name, ext, namewithoutext string) { } return } - -var r = rand.New(rand.NewSource(time.Now().UnixNano())) - -func randomN(n int) int { - return r.Intn(n) -} - -func randomNumber(min, max int) int { - sub := max - min + 1 - if sub <= 1 { - return min - } - return min + randomN(sub) -} - -func randomStr(l int) string { - str := "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" - bytes := []byte(str) - var result []byte - lstr := len(str) - 1 - for i := 0; i < l; i++ { - n := randomNumber(0, lstr) - result = append(result, bytes[n]) - } - return string(result) -} -- cgit v1.2.1