parent
d2e9e4faeb
commit
763a5aa59d
|
|
@ -28,8 +28,8 @@
|
|||
* [x] 支持设置代理
|
||||
* [x] 增加openwrt路由器的mipsle二进制
|
||||
* [x] 支持从curl命令解析出需要的信息,正如 https://github.com/cxjava/m3u8-downloader 一样
|
||||
* [x] 显示下载速度、合并ts的速度
|
||||
* [ ] 支持从一个txt里读取下载列表,批量下载
|
||||
* [ ] 显示下载速度、合并ts的速度
|
||||
* [ ] 支持多国语言
|
||||
## 二次开发操作手册:
|
||||
* 如果只开发命令行版本, 则只需要修改*.go文件, 然后编译 cmd/main.go 即可
|
||||
|
|
|
|||
30
download.go
30
download.go
|
|
@ -31,13 +31,15 @@ type TsInfo struct {
|
|||
}
|
||||
|
||||
type GetProgress_Resp struct {
|
||||
Percent int
|
||||
Title string
|
||||
SleepTh string
|
||||
Percent int
|
||||
Title string
|
||||
StatusBar string
|
||||
}
|
||||
|
||||
func GetProgress() (resp GetProgress_Resp) {
|
||||
var sleepTh int32
|
||||
var speedV string
|
||||
|
||||
gOldEnvLocker.Lock()
|
||||
if gOldEnv != nil {
|
||||
sleepTh = atomic.LoadInt32(&gOldEnv.sleepTh)
|
||||
|
|
@ -48,10 +50,15 @@ func GetProgress() (resp GetProgress_Resp) {
|
|||
if resp.Title == "" {
|
||||
resp.Title = "正在下载"
|
||||
}
|
||||
speedV = gOldEnv.speedRecent5sGetAndUpdate()
|
||||
}
|
||||
gOldEnvLocker.Unlock()
|
||||
resp.StatusBar = speedV
|
||||
if sleepTh > 0 {
|
||||
resp.SleepTh = "有 " + strconv.Itoa(int(sleepTh)) + "个线程正在休眠."
|
||||
if resp.StatusBar != "" {
|
||||
resp.StatusBar += ", "
|
||||
}
|
||||
resp.StatusBar += "有 " + strconv.Itoa(int(sleepTh)) + "个线程正在休眠."
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
|
@ -90,6 +97,9 @@ type downloadEnv struct {
|
|||
progressBarTitle string
|
||||
progressPercent int
|
||||
progressBarShow bool
|
||||
speedBytesLocker sync.Mutex
|
||||
speedBeginTime time.Time
|
||||
speedBytesMap map[time.Time]int64
|
||||
}
|
||||
|
||||
func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp) {
|
||||
|
|
@ -183,7 +193,9 @@ func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp
|
|||
tsList = tsList[req.SkipTsCountFromHead:]
|
||||
// 下载ts
|
||||
this.SetProgressBarTitle("[4/6]下载ts")
|
||||
this.speedSetBegin()
|
||||
err = this.downloader(tsList, downloadDir, tsKey)
|
||||
this.speedClearBytes()
|
||||
if err != nil {
|
||||
resp.ErrMsg = "下载ts文件错误: " + err.Error()
|
||||
resp.IsCancel = this.GetIsCancel()
|
||||
|
|
@ -199,11 +211,13 @@ func (this *downloadEnv) RunDownload(req RunDownload_Req) (resp RunDownload_Resp
|
|||
tmpOutputName = filepath.Join(downloadDir, "all.merge.mp4")
|
||||
|
||||
this.SetProgressBarTitle("[5/6]合并ts为mp4")
|
||||
this.speedSetBegin()
|
||||
err = MergeTsFileListToSingleMp4(MergeTsFileListToSingleMp4_Req{
|
||||
TsFileList: tsFileList,
|
||||
OutputMp4: tmpOutputName,
|
||||
Ctx: this.ctx,
|
||||
})
|
||||
this.speedClearBytes()
|
||||
if err != nil {
|
||||
resp.ErrMsg = "合并错误: " + err.Error()
|
||||
return resp
|
||||
|
|
@ -272,6 +286,7 @@ func RunDownload(req RunDownload_Req) (resp RunDownload_Resp) {
|
|||
},
|
||||
Timeout: time.Second * 10,
|
||||
},
|
||||
speedBytesMap: map[time.Time]int64{},
|
||||
}
|
||||
env.ctx, env.cancelFn = context.WithCancel(context.Background())
|
||||
|
||||
|
|
@ -411,7 +426,12 @@ func (this *downloadEnv) downloadTsFile(ts TsInfo, download_dir, key string) (er
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Rename(tmpPath, currPath)
|
||||
err = os.Rename(tmpPath, currPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
this.speedAddBytes(len(origData))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (this *downloadEnv) SleepDur(d time.Duration) {
|
||||
|
|
|
|||
2
go.mod
2
go.mod
|
|
@ -7,7 +7,7 @@ require (
|
|||
github.com/orestonce/go2cpp v0.0.0-20220730064838-feb9dd043919
|
||||
github.com/orestonce/gopool v0.0.0-20220508090328-d7d56d45b171
|
||||
github.com/spf13/cobra v1.4.0
|
||||
github.com/yapingcat/gomedia v0.0.0-20220721095559-a283c87d8a0b
|
||||
github.com/yapingcat/gomedia v0.0.0-20220731053213-04782526c441
|
||||
golang.org/x/net v0.0.0-20220617184016-355a448f1bc9
|
||||
golang.org/x/text v0.3.7
|
||||
)
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -16,6 +16,8 @@ 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/yapingcat/gomedia v0.0.0-20220721095559-a283c87d8a0b h1:ugQfEkchgCe+MBtP/Ih+ypTr1WhlcTHahnIDrS1GXoo=
|
||||
github.com/yapingcat/gomedia v0.0.0-20220721095559-a283c87d8a0b/go.mod h1:WSZ59bidJOO40JSJmLqlkBJrjZCtjbKKkygEMfzY/kc=
|
||||
github.com/yapingcat/gomedia v0.0.0-20220731053213-04782526c441 h1:SAohYbjWwtDtpjW9GmV6IFDou2CW4MvUXxJtz3FiuR0=
|
||||
github.com/yapingcat/gomedia v0.0.0-20220731053213-04782526c441/go.mod h1:WSZ59bidJOO40JSJmLqlkBJrjZCtjbKKkygEMfzY/kc=
|
||||
golang.org/x/net v0.0.0-20220617184016-355a448f1bc9 h1:Yqz/iviulwKwAREEeUd3nbBFn0XuyJqkoft2IlrvOhc=
|
||||
golang.org/x/net v0.0.0-20220617184016-355a448f1bc9/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ GetProgress_Resp GetProgress(){
|
|||
uint32_t tmp17 = uint32_t(uint8_t(out[outIdx+3]) << 0);
|
||||
tmp13 = tmp14 | tmp15 | tmp16 | tmp17;
|
||||
outIdx+=4;
|
||||
retValue.SleepTh = std::string(out+outIdx, out+outIdx+tmp13);
|
||||
retValue.StatusBar = std::string(out+outIdx, out+outIdx+tmp13);
|
||||
outIdx+=tmp13;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ void CloseOldEnv();
|
|||
struct GetProgress_Resp{
|
||||
int32_t Percent;
|
||||
std::string Title;
|
||||
std::string SleepTh;
|
||||
std::string StatusBar;
|
||||
GetProgress_Resp(): Percent(0){}
|
||||
};
|
||||
GetProgress_Resp GetProgress();
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||
GetProgress_Resp resp = GetProgress();
|
||||
ui->progressBar->setValue(resp.Percent);
|
||||
ui->label_progressBar->setText(QString::fromStdString(resp.Title));
|
||||
ui->statusBar->showMessage(QString::fromStdString(resp.SleepTh), 5*1000);
|
||||
ui->statusBar->showMessage(QString::fromStdString(resp.StatusBar), 5*1000);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
21
merge.go
21
merge.go
|
|
@ -4,9 +4,9 @@ import (
|
|||
"bytes"
|
||||
"context"
|
||||
"errors"
|
||||
"github.com/yapingcat/gomedia/codec"
|
||||
"github.com/yapingcat/gomedia/mp4"
|
||||
"github.com/yapingcat/gomedia/mpeg2"
|
||||
"github.com/yapingcat/gomedia/go-codec"
|
||||
"github.com/yapingcat/gomedia/go-mp4"
|
||||
"github.com/yapingcat/gomedia/go-mpeg2"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strconv"
|
||||
|
|
@ -66,16 +66,14 @@ func MergeTsFileListToSingleMp4(req MergeTsFileListToSingleMp4_Req) (err error)
|
|||
}
|
||||
}
|
||||
|
||||
env := getOldEnv()
|
||||
|
||||
for idx, tsFile := range req.TsFileList {
|
||||
select {
|
||||
case <-req.Ctx.Done():
|
||||
return req.Ctx.Err()
|
||||
default:
|
||||
}
|
||||
tmp := getOldEnv()
|
||||
if tmp != nil {
|
||||
tmp.DrawProgressBar(len(req.TsFileList), idx)
|
||||
}
|
||||
var buf []byte
|
||||
buf, err = ioutil.ReadFile(tsFile)
|
||||
if err != nil {
|
||||
|
|
@ -88,6 +86,10 @@ func MergeTsFileListToSingleMp4(req MergeTsFileListToSingleMp4_Req) (err error)
|
|||
if OnFrameErr != nil {
|
||||
return OnFrameErr
|
||||
}
|
||||
if env != nil {
|
||||
env.DrawProgressBar(len(req.TsFileList), idx)
|
||||
env.speedAddBytes(len(buf))
|
||||
}
|
||||
}
|
||||
|
||||
err = muxer.WriteTrailer()
|
||||
|
|
@ -98,9 +100,8 @@ func MergeTsFileListToSingleMp4(req MergeTsFileListToSingleMp4_Req) (err error)
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
tmp := getOldEnv()
|
||||
if tmp != nil {
|
||||
tmp.DrawProgressBar(1, 1)
|
||||
if env != nil {
|
||||
env.DrawProgressBar(1, 1)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
package m3u8d
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (this *downloadEnv) speedSetBegin() {
|
||||
this.speedBytesLocker.Lock()
|
||||
defer this.speedBytesLocker.Unlock()
|
||||
|
||||
this.speedBeginTime = time.Now()
|
||||
}
|
||||
|
||||
func (this *downloadEnv) speedAddBytes(a int) {
|
||||
this.speedBytesLocker.Lock()
|
||||
defer this.speedBytesLocker.Unlock()
|
||||
|
||||
now := time.Now()
|
||||
this.speedBytesMap[now] += int64(a)
|
||||
}
|
||||
|
||||
func (this *downloadEnv) speedClearBytes() {
|
||||
this.speedBytesLocker.Lock()
|
||||
defer this.speedBytesLocker.Unlock()
|
||||
|
||||
this.speedBytesMap = map[time.Time]int64{}
|
||||
}
|
||||
|
||||
func (this *downloadEnv) speedRecent5sGetAndUpdate() string {
|
||||
this.speedBytesLocker.Lock()
|
||||
defer this.speedBytesLocker.Unlock()
|
||||
|
||||
now := time.Now()
|
||||
if this.GetIsCancel() || this.speedBeginTime.IsZero() || now.Sub(this.speedBeginTime) < time.Second { // 1s以内, 暂时不计算速度
|
||||
return ""
|
||||
}
|
||||
|
||||
const secondCount = 5
|
||||
|
||||
expireTime := now.Add(-secondCount * time.Second)
|
||||
var total int64
|
||||
for ct, v := range this.speedBytesMap {
|
||||
if ct.Before(expireTime) {
|
||||
delete(this.speedBytesMap, ct)
|
||||
continue
|
||||
}
|
||||
total += v
|
||||
}
|
||||
realSecond := now.Sub(this.speedBeginTime).Seconds()
|
||||
if realSecond > secondCount {
|
||||
realSecond = secondCount
|
||||
}
|
||||
v := float64(total) / realSecond
|
||||
|
||||
if v < 1024 {
|
||||
return strconv.Itoa(int(v)) + " B/s"
|
||||
}
|
||||
v = v / 1024
|
||||
if v < 1024 {
|
||||
return strconv.Itoa(int(v)) + " KB/s"
|
||||
}
|
||||
|
||||
v = v / 1024
|
||||
return strconv.FormatFloat(v, 'f', 2, 64) + " MB/s"
|
||||
}
|
||||
Loading…
Reference in New Issue