Skip to content

Commit

Permalink
分析异常ts
Browse files Browse the repository at this point in the history
  • Loading branch information
orestonce committed Oct 12, 2024
1 parent cf9a441 commit e3970ac
Show file tree
Hide file tree
Showing 10 changed files with 406 additions and 368 deletions.
60 changes: 27 additions & 33 deletions api.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package m3u8d

import (
"bytes"
"context"
"crypto/sha256"
"crypto/tls"
Expand All @@ -19,7 +18,7 @@ import (
"time"
)

const logFileName = `skip_by_http_code.txt`
const logFileName = `skip.txt`

func (this *DownloadEnv) StartDownload(req StartDownload_Req) (errMsg string) {
this.status.Locker.Lock()
Expand Down Expand Up @@ -160,7 +159,7 @@ func (this *DownloadEnv) runDownload(req StartDownload_Req, skipInfo SkipTsInfo)
this.logToFile("origin m3u8 url: " + req.M3u8Url)
}

this.status.SetProgressBarTitle("[1/4]嗅探m3u8")
this.status.SetProgressBarTitle("[1/5]嗅探m3u8")
var info mformat.M3U8File
var errMsg string
req.M3u8Url, info, errMsg = this.sniffM3u8(req.M3u8Url)
Expand Down Expand Up @@ -195,7 +194,7 @@ func (this *DownloadEnv) runDownload(req StartDownload_Req, skipInfo SkipTsInfo)
this.logToFile("refresh m3u8 url: " + req.M3u8Url)
}

this.status.SetProgressBarTitle("[2/4]获取ts列表")
this.status.SetProgressBarTitle("[2/5]获取ts列表")
tsList := info.GetTsList()
tsList, skipTsList := skipApplyFilter(tsList, skipInfo)
if len(tsList) <= 0 {
Expand All @@ -214,7 +213,7 @@ func (this *DownloadEnv) runDownload(req StartDownload_Req, skipInfo SkipTsInfo)
}

// 下载ts
this.status.SetProgressBarTitle("[3/4]下载ts")
this.status.SetProgressBarTitle("[3/5]下载ts")
this.status.SpeedResetBytes()
err = this.downloader(tsList, skipInfo, tsSaveDir, req)
this.status.SpeedResetBytes()
Expand All @@ -224,37 +223,32 @@ func (this *DownloadEnv) runDownload(req StartDownload_Req, skipInfo SkipTsInfo)
return
}
this.status.DrawProgressBar(1, 1)
var tsFileList []string
var skipByHttpCodeLog bytes.Buffer
var skipCount int
for _, one := range tsList {
if one.SkipByHttpCode {
skipCount++
fmt.Fprintf(&skipByHttpCodeLog, "http.code=%v,filename=%v,url=%v\n", one.HttpCode, one.Name, one.Url)
continue
}
fileNameFull := filepath.Join(tsSaveDir, one.Name)
tsFileList = append(tsFileList, fileNameFull)

this.status.SetProgressBarTitle("[4/5]分析ts列表")
resp, err := this.removeSkipList(tsSaveDir, tsList)
if err != nil {
this.setErrMsg("写入" + logFileName + "失败, " + err.Error())
return
}
// 写入ffmpeg合并命令
if this.writeFfmpegCmd(tsSaveDir, tsList) == false {

if resp.skipByHttpCodeCount > 0 && skipInfo.IfHttpCodeMergeTs == false {
this.setErrMsg("使用http.code跳过了" + strconv.Itoa(resp.skipByHttpCodeCount) + "条ts记录,请自行合并")
return
}
if skipByHttpCodeLog.Len() > 0 {
// 写入通过http.code跳过的ts文件列表
err = os.WriteFile(filepath.Join(tsSaveDir, logFileName), skipByHttpCodeLog.Bytes(), 0666)
if err != nil {
this.setErrMsg("写入" + logFileName + "失败, " + err.Error())
return
}
if skipInfo.IfHttpCodeMergeTs == false {
this.setErrMsg("使用http.code跳过了" + strconv.Itoa(skipCount) + "条ts记录,请自行合并")
return
}

if len(resp.mergeTsList) == 0 {
this.setErrMsg("ts文件列表为空")
return
}

if req.SkipMergeTs {
return
}

var tsFileList []string
for _, one := range resp.mergeTsList {
tsFileList = append(tsFileList, filepath.Join(tsSaveDir, one.Name))
}
var name string
var tmpOutputName string

Expand All @@ -278,7 +272,7 @@ func (this *DownloadEnv) runDownload(req StartDownload_Req, skipInfo SkipTsInfo)
return
}
}
this.status.SetProgressBarTitle("[4/4]合并ts为mp4")
this.status.SetProgressBarTitle("[5/5]合并ts为mp4")
err = MergeTsFileListToSingleMp4(MergeTsFileListToSingleMp4_Req{
TsFileList: tsFileList,
OutputMp4: tmpOutputName,
Expand All @@ -305,10 +299,10 @@ func (this *DownloadEnv) runDownload(req StartDownload_Req, skipInfo SkipTsInfo)
}
}

if skipByHttpCodeLog.Len() > 0 {
// 写入通过http.code跳过的ts文件列表
if len(resp.skipLogContent) > 0 {
saveFileName := name + "_" + logFileName
err = os.WriteFile(saveFileName, skipByHttpCodeLog.Bytes(), 0666)
this.logToFile("写入文件" + saveFileName)
err = os.WriteFile(saveFileName, resp.skipLogContent, 0666)
if err != nil {
this.setErrMsg("写入" + saveFileName + "失败, " + err.Error())
return
Expand Down
3 changes: 1 addition & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ var mergeCmd = &cobra.Command{
ProgressBarShow: true,
}
status.SetProgressBarTitle("合并ts")
status.ResetTotalBlockCount(len(tsFileList))
status.SpeedResetTotalBlockCount(len(tsFileList))
err = m3u8d.MergeTsFileListToSingleMp4(m3u8d.MergeTsFileListToSingleMp4_Req{
TsFileList: tsFileList,
OutputMp4: gMergeReq.OutputMp4Name,
Expand Down Expand Up @@ -136,7 +136,6 @@ func init() {
downloadCmd.Flags().BoolVarP(&gRunReq.SkipRemoveTs, "SkipRemoveTs", "", false, "不删除下载的ts文件")
downloadCmd.Flags().IntVarP(&gRunReq.ThreadCount, "ThreadCount", "", 8, "下载线程数")
downloadCmd.Flags().BoolVarP(&gRunReq.SkipMergeTs, "SkipMergeTs", "", false, "不合并ts为mp4")
downloadCmd.Flags().BoolVarP(&gRunReq.Skip_EXT_X_DISCONTINUITY, "Skip_EXT_X_DISCONTINUITY", "", false, "跳过 #EXT-X-DISCONTINUITY 标签包裹的ts")
downloadCmd.Flags().BoolVarP(&gRunReq.DebugLog, "DebugLog", "", false, "调试日志")
downloadCmd.Flags().StringVarP(&gRunReq.TsTempDir, "TsTempDir", "", "", "临时ts文件目录")
downloadCmd.Flags().BoolVarP(&gRunReq.UseServerSideTime, "UseServerSideTime", "", false, "使用服务端提供的文件时间")
Expand Down
62 changes: 29 additions & 33 deletions download.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,22 +53,21 @@ type GetStatus_Resp struct {
var PNG_SIGN = []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A}

type StartDownload_Req struct {
M3u8Url string
Insecure bool // "是否允许不安全的请求(默认为false)"
SaveDir string // "文件保存路径(默认为当前路径)"
FileName string // 文件名
SkipTsExpr string // 跳过ts信息,ts编号从1开始,可以以逗号","为分隔符跳过多部分ts,例如: 1,92-100 表示跳过第1号ts、跳过92到100号ts
SetProxy string //代理
HeaderMap map[string][]string // 自定义http头信息
SkipRemoveTs bool // 不删除ts文件
ProgressBarShow bool // 在控制台打印进度条
ThreadCount int // 线程数
SkipCacheCheck bool // 不缓存已下载的m3u8的文件信息
SkipMergeTs bool // 不合并ts为mp4
Skip_EXT_X_DISCONTINUITY bool // 跳过 #EXT-X-DISCONTINUITY 标签包裹的ts
DebugLog bool // 调试日志
TsTempDir string // 临时ts文件目录
UseServerSideTime bool // 使用服务端提供的文件时间
M3u8Url string
Insecure bool // "是否允许不安全的请求(默认为false)"
SaveDir string // "文件保存路径(默认为当前路径)"
FileName string // 文件名
SkipTsExpr string // 跳过ts信息,ts编号从1开始,可以以逗号","为分隔符跳过多部分ts,例如: 1,92-100 表示跳过第1号ts、跳过92到100号ts
SetProxy string //代理
HeaderMap map[string][]string // 自定义http头信息
SkipRemoveTs bool // 不删除ts文件
ProgressBarShow bool // 在控制台打印进度条
ThreadCount int // 线程数
SkipCacheCheck bool // 不缓存已下载的m3u8的文件信息
SkipMergeTs bool // 不合并ts为mp4
DebugLog bool // 调试日志
TsTempDir string // 临时ts文件目录
UseServerSideTime bool // 使用服务端提供的文件时间
}

type DownloadEnv struct {
Expand Down Expand Up @@ -131,15 +130,6 @@ func (this *DownloadEnv) updateMedia(m3u8Url string, tsList []mformat.TsInfo) (e
return nil
}

func splitLineWithTrimSpace(s string) []string {
tmp := strings.Split(s, "\n")
for idx, str := range tmp {
str = strings.TrimSpace(str)
tmp[idx] = str
}
return tmp
}

// 下载ts文件
// @modify: 2020-08-13 修复ts格式SyncByte合并不能播放问题
func (this *DownloadEnv) downloadTsFile(ts *mformat.TsInfo, skipInfo SkipTsInfo, downloadDir string, useServerSideTime bool) (err error) {
Expand Down Expand Up @@ -246,7 +236,7 @@ func (this *DownloadEnv) downloader(tsList []mformat.TsInfo, skipInfo SkipTsInfo
task := gopool.NewThreadPool(req.ThreadCount)
var locker sync.Mutex

this.status.ResetTotalBlockCount(len(tsList))
this.status.SpeedResetTotalBlockCount(len(tsList))

for idx := range tsList {
ts := &tsList[idx]
Expand Down Expand Up @@ -551,7 +541,7 @@ func (this *DownloadEnv) logFileClose() {
}
}

func (this *DownloadEnv) writeFfmpegCmd(downloadingDir string, list []mformat.TsInfo) bool {
func (this *DownloadEnv) writeFfmpegCmd(downloadingDir string, list []mformat.TsInfo) (err error) {
const listFileName = "filelist.txt"

var fileListLog bytes.Buffer
Expand All @@ -561,10 +551,9 @@ func (this *DownloadEnv) writeFfmpegCmd(downloadingDir string, list []mformat.Ts
}
fileListLog.WriteString("file " + one.Name + "\n")
}
err := os.WriteFile(filepath.Join(downloadingDir, listFileName), fileListLog.Bytes(), 0777)
err = os.WriteFile(filepath.Join(downloadingDir, listFileName), fileListLog.Bytes(), 0777)
if err != nil {
this.setErrMsg("写入" + listFileName + "失败, " + err.Error())
return false
return errors.New("写入" + listFileName + "失败, " + err.Error())
}

var ffmpegCmdContent = "ffmpeg -f concat -i " + listFileName + " -c copy -y output.mp4"
Expand All @@ -578,11 +567,18 @@ func (this *DownloadEnv) writeFfmpegCmd(downloadingDir string, list []mformat.Ts

err = os.WriteFile(filepath.Join(downloadingDir, ffmpegCmdFileName), []byte(ffmpegCmdContent), 0777)
if err != nil {
this.setErrMsg("写入" + ffmpegCmdFileName + "失败, " + err.Error())
return false
return errors.New("写入" + ffmpegCmdFileName + "失败, " + err.Error())
}

return true
return nil
}

func (this *DownloadEnv) writeSkipByHttpCodeInfoTxt(tsSaveDir string, list []mformat.TsInfo) error {
var skipByHttpCodeLog bytes.Buffer
for _, one := range list {
fmt.Fprintf(&skipByHttpCodeLog, "http.code=%v,filename=%v,url=%v\n", one.HttpCode, one.Name, one.Url)
}
return os.WriteFile(filepath.Join(tsSaveDir, logFileName), skipByHttpCodeLog.Bytes(), 0666)
}

func IsContextCancel(ctx context.Context) bool {
Expand Down
Loading

0 comments on commit e3970ac

Please sign in to comment.