| ) | ) | ||||
| const baseScheme = "http" | const baseScheme = "http" | ||||
| const MASTER = "master" | |||||
| const PLAYLIST = "playlist" | |||||
| type m3u8Json struct { | type m3u8Json struct { | ||||
| master *m3u8.MasterPlaylist | |||||
| playlist []*m3u8.MediaPlaylist | |||||
| URL string | |||||
| BaseUrl string | |||||
| Type string | |||||
| Manifest interface{} | |||||
| } | |||||
| func nilIndex(input []*m3u8.MediaSegment) int { | |||||
| output := -1 | |||||
| for i := range input { | |||||
| if input[i] == nil { | |||||
| return i | |||||
| } | |||||
| } | |||||
| return output | |||||
| } | } | ||||
| func main() { | func main() { | ||||
| isUrl := false | isUrl := false | ||||
| var data *bufio.Reader | var data *bufio.Reader | ||||
| var baseUrl string | |||||
| var outputJson m3u8Json | var outputJson m3u8Json | ||||
| recursive := flag.Bool("r", false, "Recursive download master and playlists") | |||||
| abs := flag.Bool("a", false, "make URI absolute") | |||||
| baseUrl := flag.String("b", "", "Base URL") | |||||
| flag.Parse() | flag.Parse() | ||||
| inputs := flag.Args() | inputs := flag.Args() | ||||
| if len(inputs) != 1 { | if len(inputs) != 1 { | ||||
| } | } | ||||
| if !isUrl { | if !isUrl { | ||||
| f, err := os.Open("playlist.m3u8") | |||||
| if err != nil { | |||||
| log.Fatal(err) | |||||
| var f *os.File | |||||
| var err error | |||||
| if input == "-" { | |||||
| data = bufio.NewReader(os.Stdin) | |||||
| } else { | |||||
| f, err = os.Open(input) | |||||
| if err != nil { | |||||
| log.Fatal(err) | |||||
| } | |||||
| data = bufio.NewReader(f) | |||||
| } | } | ||||
| fmt.Println("ok") | |||||
| data = bufio.NewReader(f) | |||||
| fmt.Println("ok2") | |||||
| } else { | } else { | ||||
| baseUrl = fmt.Sprintf("%v://%v%v", u.Scheme, u.Host, path.Dir(u.EscapedPath())) | |||||
| if *baseUrl == "" { | |||||
| *baseUrl = fmt.Sprintf("%v://%v%v", u.Scheme, u.Host, path.Dir(u.EscapedPath())) | |||||
| } | |||||
| r, err := http.Get(u.String()) | r, err := http.Get(u.String()) | ||||
| if err != nil { | if err != nil { | ||||
| log.Fatal(err) | log.Fatal(err) | ||||
| } | } | ||||
| outputJson.URL = u.String() | |||||
| outputJson.BaseUrl = *baseUrl | |||||
| data = bufio.NewReader(r.Body) | data = bufio.NewReader(r.Body) | ||||
| } | } | ||||
| } | } | ||||
| switch listType { | switch listType { | ||||
| case m3u8.MEDIA: | case m3u8.MEDIA: | ||||
| mediapl := p.(*m3u8.MediaPlaylist) | |||||
| fmt.Printf("%+v\n", mediapl) | |||||
| output, err := json.MarshalIndent(mediapl, "", " ") | |||||
| if err != nil { | |||||
| log.Fatal(err) | |||||
| outputJson.Type = PLAYLIST | |||||
| playlist := p.(*m3u8.MediaPlaylist) | |||||
| playlist.Segments = playlist.Segments[:nilIndex(playlist.Segments)] | |||||
| for _, entry := range playlist.Segments { | |||||
| u, err := url.Parse(entry.URI) | |||||
| if err != nil { | |||||
| log.Fatal("not a valid URL") | |||||
| } | |||||
| if *abs && !u.IsAbs() && *baseUrl != "" { | |||||
| entry.URI = *baseUrl + "/" + entry.URI | |||||
| } | |||||
| } | } | ||||
| fmt.Printf("%s", output) | |||||
| outputJson.Manifest = playlist | |||||
| case m3u8.MASTER: | case m3u8.MASTER: | ||||
| outputJson.master = p.(*m3u8.MasterPlaylist) | |||||
| fmt.Printf("%+v\n", outputJson.master) | |||||
| for _, entry := range outputJson.master.Variants { | |||||
| fmt.Println(entry.Resolution) | |||||
| if isUrl { | |||||
| fmt.Printf("%v/%v\n", baseUrl, entry.URI) | |||||
| outputJson.Type = MASTER | |||||
| master := p.(*m3u8.MasterPlaylist) | |||||
| for _, entry := range master.Variants { | |||||
| var chunckUrl string | |||||
| u, err := url.Parse(entry.URI) | |||||
| if err != nil { | |||||
| log.Fatal("not a valid URL") | |||||
| } | |||||
| if !u.IsAbs() { | |||||
| chunckUrl = *baseUrl + "/" + entry.URI | |||||
| if *abs && *baseUrl != "" { | |||||
| entry.URI = chunckUrl | |||||
| } | |||||
| } else { | |||||
| chunckUrl = entry.URI | |||||
| } | |||||
| if isUrl && *recursive { | |||||
| clist, err := http.Get(chunckUrl) | |||||
| if err != nil { | |||||
| log.Fatal(err) | |||||
| } | |||||
| cdata := bufio.NewReader(clist.Body) | |||||
| p, _, _ := m3u8.DecodeFrom(cdata, true) | |||||
| playlist := p.(*m3u8.MediaPlaylist) | |||||
| playlist.Segments = playlist.Segments[:nilIndex(playlist.Segments)] | |||||
| for _, entry := range playlist.Segments { | |||||
| u, err := url.Parse(entry.URI) | |||||
| if err != nil { | |||||
| log.Fatal("not a valid URL") | |||||
| } | |||||
| if *abs && !u.IsAbs() { | |||||
| entry.URI = *baseUrl + "/" + entry.URI | |||||
| } | |||||
| } | |||||
| entry.Chunklist = playlist | |||||
| } | } | ||||
| } | } | ||||
| output, err := json.MarshalIndent(outputJson.master, "", " ") | |||||
| if err != nil { | |||||
| log.Fatal(err) | |||||
| } | |||||
| fmt.Printf("%s", output) | |||||
| outputJson.Manifest = master | |||||
| } | |||||
| output, err := json.MarshalIndent(outputJson, "", " ") | |||||
| if err != nil { | |||||
| log.Fatal(err) | |||||
| } | } | ||||
| fmt.Printf("%s", output) | |||||
| } | } |