main
orestonce 2022-06-20 07:32:53 +08:00
parent 7558dae4a2
commit 34aa6764c3
11 changed files with 150 additions and 121 deletions

View File

@ -15,7 +15,7 @@
* downloading/ 目录, 用于存放正在下载的分段ts视频, 按照m3u8的url进行划分
* m3u8d_cache.cdb 文件, 用于存放以前的下载历史, 用于防止重复下载文件
* 重复下载文件的判定和跳过
* 将除了保存位置和保存文件名以外的参数进行hash, 得到文件下载id
* 将M3u8Url+SkipTsCountFromHead进行hash, 得到文件下载id
* 将文件下载id/文件大小/文件内容hash 储存在 m3u8_cache.cdb里面, 下载前搜索下载目录
如果发现某个文件大小/文件内容hash和以前的记录相相等,则认为这个文件是以前下载的文件, 跳过
此次下载.

View File

@ -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
}

View File

@ -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()

View File

@ -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)

10
go.mod
View File

@ -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
)

51
go.sum
View File

@ -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=

View File

@ -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);

View File

@ -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 <QObject>

View File

@ -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) {

View File

@ -114,7 +114,7 @@
<item>
<layout class="QHBoxLayout" name="horizontalLayout" stretch="0,1,0,0">
<item>
<widget class="QLabel" name="label_3">
<widget class="QLabel" name="label_progressBar">
<property name="text">
<string>下载进度</string>
</property>

66
merge.go Normal file
View File

@ -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
}