From 34aa6764c3beffccc8da783ddf9240bfbcec60a8 Mon Sep 17 00:00:00 2001 From: orestonce Date: Mon, 20 Jun 2022 07:32:53 +0800 Subject: [PATCH] save --- README.md | 2 +- cache.go | 22 ++----------- download.go | 68 ++++++++++++++++++++++++++--------------- export/main.go | 4 +-- go.mod | 10 +----- go.sum | 51 ++----------------------------- m3u8d-qt/m3u8d.cpp | 29 +++++++++++++----- m3u8d-qt/m3u8d.h | 6 +++- m3u8d-qt/mainwindow.cpp | 11 ++++--- m3u8d-qt/mainwindow.ui | 2 +- merge.go | 66 +++++++++++++++++++++++++++++++++++++++ 11 files changed, 150 insertions(+), 121 deletions(-) create mode 100644 merge.go diff --git a/README.md b/README.md index cc08f58..6977679 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ * downloading/ 目录, 用于存放正在下载的分段ts视频, 按照m3u8的url进行划分 * m3u8d_cache.cdb 文件, 用于存放以前的下载历史, 用于防止重复下载文件 * 重复下载文件的判定和跳过 - * 将除了保存位置和保存文件名以外的参数进行hash, 得到文件下载id + * 将M3u8Url+SkipTsCountFromHead进行hash, 得到文件下载id * 将文件下载id/文件大小/文件内容hash 储存在 m3u8_cache.cdb里面, 下载前搜索下载目录 如果发现某个文件大小/文件内容hash和以前的记录相相等,则认为这个文件是以前下载的文件, 跳过 此次下载. diff --git a/cache.go b/cache.go index fe07490..4aff965 100644 --- a/cache.go +++ b/cache.go @@ -8,6 +8,7 @@ import ( "io/ioutil" "os" "path/filepath" + "strconv" ) type DbVideoInfo struct { @@ -18,7 +19,7 @@ type DbVideoInfo struct { } func (this *RunDownload_Req) getVideoId() (id string, err error) { - b, err := json.Marshal(this) + b, err := json.Marshal([]string{this.M3u8Url, strconv.Itoa(this.SkipTsCountFromHead)}) if err != nil { return "", err } @@ -78,22 +79,3 @@ func cacheWrite(dir string, id string, originReq RunDownload_Req, videoNameFullP } return cdb.FileRewriteKeyValue(filepath.Join(dir, "m3u8d_cache.cdb"), id, string(content)) } - -func dbRead(dir string, key string) (content []byte, err error) { - db, err := cdb.OpenFile(filepath.Join(dir, "m3u8d_cache.cdb")) - if err != nil { - if os.IsNotExist(err) { - return nil, nil - } - return nil, err - } - defer db.Close() - content, err = db.GetValue([]byte(key)) - if err != nil { - if err == cdb.ErrNoData { - return nil, nil - } - return nil, err - } - return content, nil -} diff --git a/download.go b/download.go index 6aad685..1e0d507 100644 --- a/download.go +++ b/download.go @@ -9,7 +9,6 @@ import ( "encoding/hex" "errors" "fmt" - "github.com/orestonce/goffmpeg" "github.com/orestonce/gopool" "io" "io/ioutil" @@ -30,14 +29,30 @@ type TsInfo struct { Url string } +var gProgressBarTitle string var gProgressPercent int var gProgressPercentLocker sync.Mutex -func GetProgress() int { +type GetProgress_Resp struct { + Percent int + Title string +} + +func GetProgress() (resp GetProgress_Resp) { gProgressPercentLocker.Lock() - tmp := gProgressPercent + resp.Percent = gProgressPercent + resp.Title = gProgressBarTitle gProgressPercentLocker.Unlock() - return tmp + if resp.Title == "" { + resp.Title = "正在下载" + } + return resp +} + +func SetProgressBarTitle(title string) { + gProgressPercentLocker.Lock() + defer gProgressPercentLocker.Unlock() + gProgressBarTitle = title } type RunDownload_Resp struct { @@ -48,12 +63,12 @@ type RunDownload_Resp struct { } type RunDownload_Req struct { - M3u8Url string `json:",omitempty"` - HostType string `json:",omitempty"` // "设置getHost的方式(apiv1: `http(s):// + url.Host + filepath.Dir(url.Path)`; apiv2: `http(s)://+ u.Host`" - Insecure bool `json:"-"` // "是否允许不安全的请求(默认为false)" - SaveDir string `json:"-"` // "文件保存路径(默认为当前路径)" - FileName string `json:"-"` // 文件名 - SkipTsCountFromHead int `json:",omitempty"` // 跳过前面几个ts + M3u8Url string + HostType string // "设置getHost的方式(apiv1: `http(s):// + url.Host + filepath.Dir(url.Path)`; apiv2: `http(s)://+ u.Host`" + Insecure bool // "是否允许不安全的请求(默认为false)" + SaveDir string // "文件保存路径(默认为当前路径)" + FileName string // 文件名 + SkipTsCountFromHead int // 跳过前面几个ts } type downloadEnv struct { @@ -64,7 +79,6 @@ type downloadEnv struct { } func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp) { - if req.HostType == "" { req.HostType = "apiv1" } @@ -95,6 +109,7 @@ func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp "Accept-Language": []string{"zh-CN,zh;q=0.9, en;q=0.8, de;q=0.7, *;q=0.5"}, "Referer": []string{host}, } + SetProgressBarTitle("嗅探m3u8") req.M3u8Url, err = this.sniffM3u8(req.M3u8Url) if err != nil { resp.ErrMsg = "sniffM3u8: " + err.Error() @@ -112,6 +127,7 @@ func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp return resp } if info != nil { + SetProgressBarTitle("检查是否已下载") latestNameFullPath, found := info.SearchVideoInDir(req.SaveDir) if found { resp.IsSkipped = true @@ -119,12 +135,6 @@ func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp return resp } } - var ffmpegExe string - ffmpegExe, err = goffmpeg.SetupFfmpeg() - if err != nil { - resp.ErrMsg = "SetupFfmpeg error: " + err.Error() - return resp - } if !strings.HasPrefix(req.M3u8Url, "http") || req.M3u8Url == "" { resp.ErrMsg = "M3u8Url not valid " + strconv.Quote(req.M3u8Url) return resp @@ -156,6 +166,7 @@ func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp resp.IsCancel = this.GetIsCancel() return resp } + SetProgressBarTitle("获取ts列表") tsList := getTsList(m3u8Host, string(m3u8Body)) if len(tsList) <= req.SkipTsCountFromHead { resp.ErrMsg = "需要下载的文件为空" @@ -163,13 +174,14 @@ func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp } tsList = tsList[req.SkipTsCountFromHead:] // 下载ts + SetProgressBarTitle("下载ts") err = this.downloader(tsList, downloadDir, ts_key) if err != nil { resp.ErrMsg = "下载ts文件错误: " + err.Error() resp.IsCancel = this.GetIsCancel() return resp } - DrawProgressBar(1) + DrawProgressBar(1, 1) var tsFileList []string for _, one := range tsList { tsFileList = append(tsFileList, filepath.Join(downloadDir, one.Name)) @@ -177,16 +189,17 @@ func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp var tmpOutputName string var contentHash string tmpOutputName = filepath.Join(downloadDir, "all.merge.mp4") - err = goffmpeg.MergeMultiToSingleMp4(goffmpeg.MergeMultiToSingleMp4_Req{ - FfmpegExePath: ffmpegExe, - TsFileList: tsFileList, - OutputMp4: tmpOutputName, - ProgressCh: nil, + + SetProgressBarTitle("合并ts为mp4") + err = MergeTsFileListToSingleMp4(MergeTsFileListToSingleMp4_Req{ + TsFileList: tsFileList, + OutputMp4: tmpOutputName, }) if err != nil { resp.ErrMsg = "合并错误: " + err.Error() return resp } + SetProgressBarTitle("计算文件hash") contentHash = getFileSha256(tmpOutputName) if contentHash == "" { resp.ErrMsg = "无法计算摘要信息: " + tmpOutputName @@ -228,6 +241,7 @@ func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp resp.ErrMsg = "删除下载目录失败: " + err.Error() return resp } + SetProgressBarTitle("下载进度") return resp } @@ -423,7 +437,7 @@ func (this *downloadEnv) downloader(tsList []TsInfo, downloadDir string, key str } locker.Lock() downloadCount++ - DrawProgressBar(float32(downloadCount) / float32(tsLen)) + DrawProgressBar(tsLen, downloadCount) locker.Unlock() }) } @@ -442,7 +456,11 @@ func SetShowProgressBar() { } // 进度条 -func DrawProgressBar(proportion float32) { +func DrawProgressBar(total int, current int) { + if total == 0 { + return + } + proportion := float32(current) / float32(total) gProgressPercentLocker.Lock() gProgressPercent = int(proportion * 100) gProgressPercentLocker.Unlock() diff --git a/export/main.go b/export/main.go index f266093..28c7852 100644 --- a/export/main.go +++ b/export/main.go @@ -10,7 +10,7 @@ import ( ) func main() { - BuildCliBinary() // 编译二进制 + //BuildCliBinary() // 编译二进制 CreateLibForQtUi() // 创建Qt需要使用的.a库文件 } @@ -39,7 +39,7 @@ func BuildCliBinary() { }, } for _, cfg := range list { - name := "m3u8d_cli_v1.2_" + cfg.GOOS + "_" + cfg.GOARCH + cfg.Ext + name := "m3u8d_cli_v1.3_" + cfg.GOOS + "_" + cfg.GOARCH + cfg.Ext cmd := exec.Command("go", "build", "-o", filepath.Join(wd, "bin", name)) cmd.Dir = filepath.Join(wd, "cmd") cmd.Env = append(os.Environ(), "GOOS="+cfg.GOOS) diff --git a/go.mod b/go.mod index 704c6bd..aff05d4 100644 --- a/go.mod +++ b/go.mod @@ -3,22 +3,14 @@ module m3u8d go 1.17 require ( - github.com/levigross/grequests v0.0.0-20190908174114-253788527a1a github.com/orestonce/cdb v0.0.0-20220528005855-d187c22240e2 github.com/orestonce/go2cpp v0.0.0-20220507123906-b66d3600c123 - github.com/orestonce/goffmpeg v0.0.0-20220528011920-92f3449b6c15 github.com/orestonce/gopool v0.0.0-20220508090328-d7d56d45b171 - github.com/saracen/go7z v0.0.0-20191010121135-9c09b6bd7fda github.com/spf13/cobra v1.4.0 + github.com/yapingcat/gomedia v0.0.0-20220619163023-5a5544262ef6 ) require ( - github.com/google/go-querystring v1.0.0 // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect - github.com/saracen/go7z-fixtures v0.0.0-20190623165746-aa6b8fba1d2f // indirect - github.com/saracen/solidblock v0.0.0-20190426153529-45df20abab6f // indirect github.com/spf13/pflag v1.0.5 // indirect - github.com/ulikunitz/xz v0.5.10 // indirect - golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f // indirect - golang.org/x/tools v0.1.10 // indirect ) diff --git a/go.sum b/go.sum index fd803ec..9b88a76 100644 --- a/go.sum +++ b/go.sum @@ -1,65 +1,18 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/levigross/grequests v0.0.0-20190908174114-253788527a1a h1:DGFy/362j92vQRE3ThU1yqg9TuJS8YJOSbQuB7BP9cA= -github.com/levigross/grequests v0.0.0-20190908174114-253788527a1a/go.mod h1:jVntzcUU+2BtVohZBQmSHWUmh8B55LCNfPhcNCIvvIg= -github.com/orestonce/cdb v0.0.0-20210317131130-99d93d11de21 h1:kFAgzquHOv3dmVU2HoUUzu1586bd1DKHfAz6dd5do+I= -github.com/orestonce/cdb v0.0.0-20210317131130-99d93d11de21/go.mod h1:HMNNdA1LMQFJRwobtCzVevWcInFSo9rfs1fYeVYwU+c= github.com/orestonce/cdb v0.0.0-20220528005855-d187c22240e2 h1:AmGkuxSIOW0gA/jetY8d1DVV0cyQ08FMCxa1arkI6HQ= github.com/orestonce/cdb v0.0.0-20220528005855-d187c22240e2/go.mod h1:HMNNdA1LMQFJRwobtCzVevWcInFSo9rfs1fYeVYwU+c= github.com/orestonce/go2cpp v0.0.0-20220507123906-b66d3600c123 h1:AyAKqO7kC68OKiZk9GV4bUG+xMe1VQCy2CPbS9hvdY4= github.com/orestonce/go2cpp v0.0.0-20220507123906-b66d3600c123/go.mod h1:1fsOAZftk08/dOTRqlp6f/MVwaEKOhrnPUg0RtWiSdY= -github.com/orestonce/goffmpeg v0.0.0-20220519233347-2266c9b171d9 h1:ki+QkZANpELM4WJjjcFwwFmt6r9ni53QxIYeS6OX77Y= -github.com/orestonce/goffmpeg v0.0.0-20220519233347-2266c9b171d9/go.mod h1:QHZrzI4ewo7pYfEo8+QzrPxsCixua/TS0aE505m/nBU= -github.com/orestonce/goffmpeg v0.0.0-20220528011920-92f3449b6c15 h1:Ix2AmnSHlA2hrI1NkpmXnFeOcxtdCj66fj1KoGFq9tI= -github.com/orestonce/goffmpeg v0.0.0-20220528011920-92f3449b6c15/go.mod h1:QHZrzI4ewo7pYfEo8+QzrPxsCixua/TS0aE505m/nBU= github.com/orestonce/gopool v0.0.0-20220508090328-d7d56d45b171 h1:NnOl6HTrhrlTT7aaAybVOtq+fEztGFMoQtegckgwLdk= github.com/orestonce/gopool v0.0.0-20220508090328-d7d56d45b171/go.mod h1:MCQUrAPiG9/PTjHJuGqWLasKbIaG6z62KO6kfp90byM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/saracen/go7z v0.0.0-20191010121135-9c09b6bd7fda h1:h+YpzUB/bGVJcLqW+d5GghcCmE/A25KbzjXvWJQi/+o= -github.com/saracen/go7z v0.0.0-20191010121135-9c09b6bd7fda/go.mod h1:MSotTrCv1PwoR8QgU1JurEx+lNNbtr25I+m0zbLyAGw= -github.com/saracen/go7z-fixtures v0.0.0-20190623165746-aa6b8fba1d2f h1:PF9WV5j/x6MT+x/sauUHd4objCvJbZb0wdxZkHSdd5A= -github.com/saracen/go7z-fixtures v0.0.0-20190623165746-aa6b8fba1d2f/go.mod h1:6Ff0ADODZ6S3gYepgZ2w7OqFrTqtFcfwDUhmm8jsUhs= -github.com/saracen/solidblock v0.0.0-20190426153529-45df20abab6f h1:1cJITU3JUI8qNS5T0BlXwANsVdyoJQHQ4hvOxbunPCw= -github.com/saracen/solidblock v0.0.0-20190426153529-45df20abab6f/go.mod h1:LyBTue+RWeyIfN3ZJ4wVxvDuvlGJtDgCLgCb6HCPgps= github.com/spf13/cobra v1.4.0 h1:y+wJpx64xcgO1V+RcnwW0LEHxTKRi2ZDPSBjWnrg88Q= github.com/spf13/cobra v1.4.0/go.mod h1:Wo4iy3BUC+X2Fybo0PDqwJIv3dNRiZLHQymsfxlB84g= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8= -github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= -golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= -golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f h1:OfiFi4JbukWwe3lzw+xunroH1mnC1e2Gy5cxNJApiSY= -golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654 h1:id054HUawV2/6IGm2IV8KZQjqtwAOo2CYlOToYqa0d0= -golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= -golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +github.com/yapingcat/gomedia v0.0.0-20220619163023-5a5544262ef6 h1:d9MplS5tlYkVzS20zFz47Hg82wvTnTk4Oafwo6j9Eb0= +github.com/yapingcat/gomedia v0.0.0-20220619163023-5a5544262ef6/go.mod h1:WSZ59bidJOO40JSJmLqlkBJrjZCtjbKKkygEMfzY/kc= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= diff --git a/m3u8d-qt/m3u8d.cpp b/m3u8d-qt/m3u8d.cpp index 06bf9f2..abe945b 100644 --- a/m3u8d-qt/m3u8d.cpp +++ b/m3u8d-qt/m3u8d.cpp @@ -181,20 +181,33 @@ void CloseOldEnv(){ } } -int32_t GetProgress(){ +GetProgress_Resp GetProgress(){ std::string in; char *out = NULL; int outLen = 0; Go2cppFn_GetProgress((char *)in.data(), in.length(), &out, &outLen); - int32_t retValue; + GetProgress_Resp retValue; int outIdx = 0; { - uint32_t tmp2 = uint32_t(uint8_t(out[outIdx+0]) << 24); - uint32_t tmp3 = uint32_t(uint8_t(out[outIdx+1]) << 16); - uint32_t tmp4 = uint32_t(uint8_t(out[outIdx+2]) << 8); - uint32_t tmp5 = uint32_t(uint8_t(out[outIdx+3]) << 0); - retValue = tmp2 | tmp3 | tmp4 | tmp5; - outIdx+=4; + { + uint32_t tmp3 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp4 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp5 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp6 = uint32_t(uint8_t(out[outIdx+3]) << 0); + retValue.Percent = tmp3 | tmp4 | tmp5 | tmp6; + outIdx+=4; + } + { + uint32_t tmp7 = 0; + uint32_t tmp8 = uint32_t(uint8_t(out[outIdx+0]) << 24); + uint32_t tmp9 = uint32_t(uint8_t(out[outIdx+1]) << 16); + uint32_t tmp10 = uint32_t(uint8_t(out[outIdx+2]) << 8); + uint32_t tmp11 = uint32_t(uint8_t(out[outIdx+3]) << 0); + tmp7 = tmp8 | tmp9 | tmp10 | tmp11; + outIdx+=4; + retValue.Title = std::string(out+outIdx, out+outIdx+tmp7); + outIdx+=tmp7; + } } if (out != NULL) { free(out); diff --git a/m3u8d-qt/m3u8d.h b/m3u8d-qt/m3u8d.h index 18f687a..082b91b 100644 --- a/m3u8d-qt/m3u8d.h +++ b/m3u8d-qt/m3u8d.h @@ -22,7 +22,11 @@ struct RunDownload_Resp{ }; RunDownload_Resp RunDownload(RunDownload_Req in0); void CloseOldEnv(); -int32_t GetProgress(); +struct GetProgress_Resp{ + int32_t Percent; + std::string Title; +}; +GetProgress_Resp GetProgress(); std::string GetWd(); #include diff --git a/m3u8d-qt/mainwindow.cpp b/m3u8d-qt/mainwindow.cpp index 2fac900..f04f7b3 100644 --- a/m3u8d-qt/mainwindow.cpp +++ b/m3u8d-qt/mainwindow.cpp @@ -35,7 +35,7 @@ void MainWindow::on_pushButton_RunDownload_clicked() ui->pushButton_RunDownload->setEnabled(false); ui->checkBox_Insecure->setEnabled(false); ui->progressBar->setValue(0); - ui->pushButton_RunDownload->setText("正在下载..."); +// ui->pushButton_RunDownload->setText("正在下载..."); ui->pushButton_StopDownload->setEnabled(true); m_syncUi.AddRunFnOn_OtherThread([this](){ @@ -45,10 +45,11 @@ void MainWindow::on_pushButton_RunDownload_clicked() while(isFinished->load() == false) { QThread::msleep(50); - int value = GetProgress(); + GetProgress_Resp resp = GetProgress(); // 可能以下闭包在运行前, other thread已经退出了, 所以isFinished需要使用shared_ptr - m_syncUi.AddRunFnOn_UiThread([value, this, isFinished](){ - ui->progressBar->setValue(value); + m_syncUi.AddRunFnOn_UiThread([resp, this, isFinished](){ + ui->progressBar->setValue(resp.Percent); + ui->label_progressBar->setText(QString::fromStdString(resp.Title)); if (ui->pushButton_RunDownload->isEnabled()) { isFinished->store(true); } @@ -73,7 +74,7 @@ void MainWindow::on_pushButton_RunDownload_clicked() ui->lineEdit_SkipTsCountFromHead->setEnabled(true); ui->comboBox_HostType->setEnabled(true); ui->pushButton_RunDownload->setEnabled(true); - ui->checkBox_Insecure->setEnabled(false); + ui->checkBox_Insecure->setEnabled(true); ui->pushButton_RunDownload->setText("开始下载"); ui->pushButton_StopDownload->setEnabled(false); if (resp.IsCancel) { diff --git a/m3u8d-qt/mainwindow.ui b/m3u8d-qt/mainwindow.ui index a3e77c0..3db0f42 100644 --- a/m3u8d-qt/mainwindow.ui +++ b/m3u8d-qt/mainwindow.ui @@ -114,7 +114,7 @@ - + 下载进度 diff --git a/merge.go b/merge.go new file mode 100644 index 0000000..be11b91 --- /dev/null +++ b/merge.go @@ -0,0 +1,66 @@ +package m3u8d + +import ( + "bytes" + "errors" + "github.com/yapingcat/gomedia/mp4" + "github.com/yapingcat/gomedia/mpeg2" + "io/ioutil" + "os" + "strconv" +) + +type MergeTsFileListToSingleMp4_Req struct { + TsFileList []string + OutputMp4 string +} + +func MergeTsFileListToSingleMp4(req MergeTsFileListToSingleMp4_Req) (err error) { + mp4file, err := os.OpenFile(req.OutputMp4, os.O_CREATE|os.O_RDWR|os.O_TRUNC, 0666) + if err != nil { + return err + } + defer mp4file.Close() + + muxer := mp4.CreateMp4Muxer(mp4file) + vtid := muxer.AddVideoTrack(mp4.MP4_CODEC_H264) + atid := muxer.AddAudioTrack(mp4.MP4_CODEC_AAC, 0, 16, 44100) + + demuxer := mpeg2.NewTSDemuxer() + var OnFrameErr error + demuxer.OnFrame = func(cid mpeg2.TS_STREAM_TYPE, frame []byte, pts uint64, dts uint64) { + if OnFrameErr != nil { + return + } + if cid == mpeg2.TS_STREAM_AAC { + OnFrameErr = muxer.Write(atid, frame, pts, dts) + } else if cid == mpeg2.TS_STREAM_H264 { + OnFrameErr = muxer.Write(vtid, frame, pts, dts) + } else { + OnFrameErr = errors.New("unknown cid " + strconv.Itoa(int(cid))) + } + } + + for idx, tsFile := range req.TsFileList { + DrawProgressBar(len(req.TsFileList), idx) + var buf []byte + buf, err = ioutil.ReadFile(tsFile) + if err != nil { + return err + } + err = demuxer.Input(bytes.NewReader(buf)) + if err != nil { + return err + } + if OnFrameErr != nil { + return OnFrameErr + } + } + + err = muxer.WriteTrailer() + if err != nil { + return err + } + DrawProgressBar(1, 1) + return err +}