diff --git a/dl/dowloader.go b/dl/dowloader.go index 3d7ea7a..5fc06e7 100644 --- a/dl/dowloader.go +++ b/dl/dowloader.go @@ -10,8 +10,8 @@ import ( "sync" "sync/atomic" - "github.com/oopsguy/m3u8/parse" - "github.com/oopsguy/m3u8/tool" + "github.com/kolychen/m3u8/parse" + "github.com/kolychen/m3u8/tool" ) const ( @@ -23,19 +23,20 @@ const ( ) type Downloader struct { - lock sync.Mutex - queue []int - folder string - tsFolder string - finish int32 - segLen int + lock sync.Mutex + queue []int + folder string + outFileName string + tsFolder string + finish int32 + segLen int result *parse.Result } // NewTask returns a Task instance -func NewTask(output string, url string) (*Downloader, error) { - result, err := parse.FromURL(url) +func NewTask(output, fileName string, url string) (*Downloader, error) { + result, err := parse.FromURL(url, true) if err != nil { return nil, err } @@ -53,14 +54,15 @@ func NewTask(output string, url string) (*Downloader, error) { if err := os.MkdirAll(folder, os.ModePerm); err != nil { return nil, fmt.Errorf("create storage folder failed: %s", err.Error()) } - tsFolder := filepath.Join(folder, tsFolderName) - if err := os.MkdirAll(tsFolder, os.ModePerm); err != nil { - return nil, fmt.Errorf("create ts folder '[%s]' failed: %s", tsFolder, err.Error()) + tsFolder, err := ioutil.TempDir(folder, fileName) //解决并发下载的情况下,临时目录冲突的问题 + if err != nil { + return nil, fmt.Errorf("create ts folder '[%s]' failed: %s", fileName, err.Error()) } d := &Downloader{ - folder: folder, - tsFolder: tsFolder, - result: result, + folder: folder, + tsFolder: tsFolder, + result: result, + outFileName: fileName, } d.segLen = len(result.M3u8.Segments) d.queue = genSlice(d.segLen) @@ -187,8 +189,8 @@ func (d *Downloader) back(segIndex int) error { return nil } +// In fact, the number of downloaded segments should be equal to number of m3u8 segments func (d *Downloader) merge() error { - // In fact, the number of downloaded segments should be equal to number of m3u8 segments missingCount := 0 for idx := 0; idx < d.segLen; idx++ { tsFilename := tsFilename(idx) @@ -202,7 +204,7 @@ func (d *Downloader) merge() error { } // Create a TS file for merging, all segment files will be written to this file. - mFilePath := filepath.Join(d.folder, mergeTSFilename) + mFilePath := filepath.Join(d.folder, d.outFileName+".ts") mFile, err := os.Create(mFilePath) if err != nil { return fmt.Errorf("create main TS file failed:%s", err.Error()) diff --git a/parse/m3u8.go b/parse/m3u8.go index 8ef041a..dde6322 100644 --- a/parse/m3u8.go +++ b/parse/m3u8.go @@ -54,6 +54,9 @@ type MasterPlaylist struct { Resolution string Codecs string ProgramID uint32 + Duration float64 + Width int + Height int } // #EXT-X-KEY:METHOD=AES-128,URI="key.key" @@ -237,6 +240,9 @@ func parseMasterPlaylist(line string) (*MasterPlaylist, error) { mp.BandWidth = uint32(v) case k == "RESOLUTION": mp.Resolution = v + xPos := strings.Index(v, "x") + mp.Width, _ = strconv.Atoi(v[:xPos]) + mp.Height, _ = strconv.Atoi(v[xPos+1:]) case k == "PROGRAM-ID": v, err := strconv.ParseUint(v, 10, 32) if err != nil { @@ -245,6 +251,12 @@ func parseMasterPlaylist(line string) (*MasterPlaylist, error) { mp.ProgramID = uint32(v) case k == "CODECS": mp.Codecs = v + case k == "TAP-DURATION": + v, err := strconv.ParseFloat(v, 64) + if err != nil { + return nil, err + } + mp.Duration = v } } return mp, nil diff --git a/parse/parser.go b/parse/parser.go index b413da7..9f7f894 100644 --- a/parse/parser.go +++ b/parse/parser.go @@ -15,7 +15,7 @@ type Result struct { Keys map[int]string } -func FromURL(link string) (*Result, error) { +func FromURL(link string, isGetSubPlayerlist bool) (*Result, error) { u, err := url.Parse(link) if err != nil { return nil, err @@ -31,11 +31,11 @@ func FromURL(link string) (*Result, error) { if err != nil { return nil, err } - if len(m3u8.MasterPlaylist) != 0 { + if len(m3u8.MasterPlaylist) != 0 && isGetSubPlayerlist { sf := m3u8.MasterPlaylist[0] - return FromURL(tool.ResolveURL(u, sf.URI)) + return FromURL(tool.ResolveURL(u, sf.URI), isGetSubPlayerlist) } - if len(m3u8.Segments) == 0 { + if len(m3u8.Segments) == 0 && isGetSubPlayerlist { return nil, errors.New("can not found any TS file description") } result := &Result{