From c3fa8763c1575f9f0c083595721a0676e8ecedc0 Mon Sep 17 00:00:00 2001 From: orestonce Date: Thu, 23 May 2024 21:44:12 +0800 Subject: [PATCH] =?UTF-8?q?=E6=94=AF=E6=8C=81=E5=97=85=E6=8E=A2m3u8?= =?UTF-8?q?=E8=B0=83=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api.go | 87 +++++++++++++++++++++++++++++++---------------------- download.go | 15 ++++++--- 2 files changed, 61 insertions(+), 41 deletions(-) diff --git a/api.go b/api.go index 429622b..828897a 100644 --- a/api.go +++ b/api.go @@ -5,8 +5,7 @@ import ( "crypto/sha256" "crypto/tls" "encoding/hex" - "encoding/json" - "io/ioutil" + "fmt" "net/http" "net/url" "os" @@ -198,6 +197,10 @@ func (this *DownloadEnv) setErrMsg(errMsg string) { this.status.Locker.Lock() this.status.errMsg = errMsg this.status.Locker.Unlock() + + if errMsg != "" { + this.logToFile("errMsg " + errMsg) + } } func (this *DownloadEnv) setSaveFileTo(to string, isSkipped bool) { @@ -207,7 +210,33 @@ func (this *DownloadEnv) setSaveFileTo(to string, isSkipped bool) { this.status.Locker.Unlock() } +var debugLogNo uint32 + func (this *DownloadEnv) runDownload(req StartDownload_Req, skipList []SkipTsUnit) { + if !strings.HasPrefix(req.M3u8Url, "http") || req.M3u8Url == "" { + this.setErrMsg("M3u8Url not valid " + strconv.Quote(req.M3u8Url)) + return + } + var err error + downloadingDir := filepath.Join(req.SaveDir, "downloading") + if !isDirExists(downloadingDir) { + err = os.MkdirAll(downloadingDir, os.ModePerm) + if err != nil { + this.setErrMsg("os.MkdirAll error0: " + err.Error()) + return + } + } + var tempDebugFilePath string + if req.DebugLog { + tempDebugFilePath = filepath.Join(downloadingDir, fmt.Sprintf("temp_debuglog_%08d-%05d.txt", os.Getpid(), atomic.AddUint32(&debugLogNo, 1))) + this.logFile, err = os.OpenFile(tempDebugFilePath, os.O_APPEND|os.O_CREATE, 0666) + if err != nil { + this.setErrMsg("os.WriteUrl error: " + err.Error()) + return + } + this.logToFile("origin m3u8 url: " + req.M3u8Url) + } + this.status.SetProgressBarTitle("[1/4]嗅探m3u8") var m3u8Body []byte var errMsg string @@ -216,41 +245,31 @@ func (this *DownloadEnv) runDownload(req StartDownload_Req, skipList []SkipTsUni this.setErrMsg("sniffM3u8: " + errMsg) return } - videoId, err := req.getVideoId() - if err != nil { - this.setErrMsg("getVideoId: " + err.Error()) - return - } - - if !strings.HasPrefix(req.M3u8Url, "http") || req.M3u8Url == "" { - this.setErrMsg("M3u8Url not valid " + strconv.Quote(req.M3u8Url)) - return - } - downloadDir := filepath.Join(req.SaveDir, "downloading", videoId) - if !isDirExists(downloadDir) { - err = os.MkdirAll(downloadDir, os.ModePerm) + videoId := req.getVideoId() + videoDownloadDir := filepath.Join(req.SaveDir, "downloading", videoId) + if !isDirExists(videoDownloadDir) { + err = os.MkdirAll(videoDownloadDir, os.ModePerm) if err != nil { this.setErrMsg("os.MkdirAll error: " + err.Error()) return } } - downloadingFilePath := filepath.Join(downloadDir, "downloading.txt") - if !isFileExists(downloadingFilePath) { - err = ioutil.WriteFile(downloadingFilePath, []byte(req.M3u8Url), 0666) + if this.logFile != nil { + this.logFile.Sync() + this.logFile.Close() + persistDebugFilePath := filepath.Join(videoDownloadDir, "debuglog.txt") + err = os.Rename(tempDebugFilePath, persistDebugFilePath) if err != nil { - this.setErrMsg("os.WriteUrl error: " + err.Error()) + this.setErrMsg("os.Rename set persistDebugFilePath " + strconv.Quote(persistDebugFilePath) + " error : " + err.Error()) return } - } - - if req.DebugLog { - this.logFile, err = os.OpenFile(filepath.Join(downloadDir, "debug.txt"), os.O_APPEND|os.O_CREATE, 0666) + this.logFile, err = os.OpenFile(persistDebugFilePath, os.O_APPEND|os.O_CREATE, 0666) if err != nil { - this.setErrMsg("os.WriteUrl error: " + err.Error()) + this.setErrMsg("os.Open persistDebugFilePath " + strconv.Quote(persistDebugFilePath) + " error: " + err.Error()) return } - this.logToFile("m3u8 url: " + req.M3u8Url) + this.logToFile("refresh m3u8 url: " + req.M3u8Url) } beginSeq := parseBeginSeq(m3u8Body) @@ -274,7 +293,7 @@ func (this *DownloadEnv) runDownload(req StartDownload_Req, skipList []SkipTsUni // 下载ts this.status.SetProgressBarTitle("[3/4]下载ts") this.status.SpeedResetBytes() - err = this.downloader(tsList, downloadDir, encInfo, req.ThreadCount) + err = this.downloader(tsList, videoDownloadDir, encInfo, req.ThreadCount) this.status.SpeedResetBytes() if err != nil { this.setErrMsg("下载ts文件错误: " + err.Error()) @@ -286,10 +305,10 @@ func (this *DownloadEnv) runDownload(req StartDownload_Req, skipList []SkipTsUni } var tsFileList []string for _, one := range tsList { - tsFileList = append(tsFileList, filepath.Join(downloadDir, one.Name)) + tsFileList = append(tsFileList, filepath.Join(videoDownloadDir, one.Name)) } var tmpOutputName string - tmpOutputName = filepath.Join(downloadDir, "all.merge.mp4") + tmpOutputName = filepath.Join(videoDownloadDir, "all.merge.mp4") this.status.SetProgressBarTitle("[4/4]合并ts为mp4") err = MergeTsFileListToSingleMp4(MergeTsFileListToSingleMp4_Req{ @@ -329,7 +348,7 @@ func (this *DownloadEnv) runDownload(req StartDownload_Req, skipList []SkipTsUni return } if req.SkipRemoveTs == false { - err = os.RemoveAll(downloadDir) + err = os.RemoveAll(videoDownloadDir) if err != nil { this.setErrMsg("删除下载目录失败: " + err.Error()) return @@ -413,11 +432,7 @@ func (this *DownloadEnv) prepareReqAndHeader(req *StartDownload_Req) (errMsg str return "" } -func (this *StartDownload_Req) getVideoId() (id string, err error) { - b, err := json.Marshal(this.M3u8Url) - if err != nil { - return "", err - } - tmp1 := sha256.Sum256(b) - return hex.EncodeToString(tmp1[:]), nil +func (this *StartDownload_Req) getVideoId() (id string) { + tmp1 := sha256.Sum256([]byte(this.M3u8Url)) + return hex.EncodeToString(tmp1[:]) } diff --git a/download.go b/download.go index dc88708..06c546e 100644 --- a/download.go +++ b/download.go @@ -110,7 +110,7 @@ func (this *DownloadEnv) getEncryptInfo(m3u8Url string, html string) (info *Encr return nil, errors.New(errMsg) } var res []byte - res, err = this.doGetRequest(keyUrl) + res, err = this.doGetRequest(keyUrl, true) if err != nil { return nil, err } @@ -180,7 +180,7 @@ func (this *DownloadEnv) downloadTsFile(ts TsInfo, downloadDir string, encInfo * this.status.SpeedAdd1Block(int(stat.Size())) return nil } - data, err := this.doGetRequest(ts.Url) + data, err := this.doGetRequest(ts.Url, false) if err != nil { return err } @@ -322,7 +322,7 @@ func AesDecrypt(seq uint64, encrypted []byte, encInfo *EncryptInfo) ([]byte, err func (this *DownloadEnv) sniffM3u8(urlS string) (afterUrl string, content []byte, errMsg string) { for idx := 0; idx < 5; idx++ { var err error - content, err = this.doGetRequest(urlS) + content, err = this.doGetRequest(urlS, true) if err != nil { return "", nil, err.Error() } @@ -389,7 +389,7 @@ func UrlHasSuffix(urlS string, suff string) bool { return strings.HasSuffix(strings.ToLower(urlObj.Path), suff) } -func (this *DownloadEnv) doGetRequest(urlS string) (data []byte, err error) { +func (this *DownloadEnv) doGetRequest(urlS string, dumpRespBody bool) (data []byte, err error) { req, err := http.NewRequest(http.MethodGet, urlS, nil) if err != nil { return nil, err @@ -402,6 +402,7 @@ func (this *DownloadEnv) doGetRequest(urlS string) (data []byte, err error) { this.logFileLocker.Lock() if this.logFile != nil { logBuf = bytes.NewBuffer(nil) + logBuf.WriteString("http get url " + strconv.Quote(urlS) + "\n") reqBytes, _ := httputil.DumpRequest(req, false) logBuf.WriteString("httpReq:\n" + string(reqBytes) + "\n") } @@ -430,6 +431,9 @@ func (this *DownloadEnv) doGetRequest(urlS string) (data []byte, err error) { } return nil, err } + if logBuf != nil && dumpRespBody { + logBuf.WriteString("httpRespBody:\n" + string(content)) + } if resp.StatusCode != 200 { if logBuf != nil { logBuf.WriteString("error3\n") @@ -452,7 +456,8 @@ func (this *DownloadEnv) logToFile(body string) { } timeStr := time.Now().Format("2006-01-02_15:04:05") - fmt.Fprintf(this.logFile, "===>time: %s\n%s\n", timeStr, body) + this.logFile.WriteString("===>time: " + timeStr + "\n") + this.logFile.WriteString(body + "\n") } func (this *DownloadEnv) GetIsCancel() bool {