Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

main.go 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  1. package main
  2. import (
  3. "bufio"
  4. "encoding/json"
  5. "flag"
  6. "fmt"
  7. "log"
  8. "net/http"
  9. "net/url"
  10. "os"
  11. "path"
  12. "strings"
  13. "github.com/grafov/m3u8"
  14. )
  15. const baseScheme = "http"
  16. const MASTER = "master"
  17. const PLAYLIST = "playlist"
  18. type m3u8Json struct {
  19. URL string
  20. BaseUrl string
  21. Type string
  22. Manifest interface{}
  23. }
  24. func nilIndex(input []*m3u8.MediaSegment) int {
  25. output := -1
  26. for i := range input {
  27. if input[i] == nil {
  28. return i
  29. }
  30. }
  31. return output
  32. }
  33. func main() {
  34. isUrl := false
  35. var data *bufio.Reader
  36. var outputJson m3u8Json
  37. recursive := flag.Bool("r", false, "Recursive download master and playlists")
  38. abs := flag.Bool("a", false, "make URI absolute")
  39. baseUrl := flag.String("b", "", "Base URL")
  40. flag.Parse()
  41. inputs := flag.Args()
  42. if len(inputs) != 1 {
  43. log.Fatal("Only 1 input is allowed")
  44. }
  45. input := inputs[0]
  46. u, err := url.Parse(input)
  47. if err != nil {
  48. log.Fatal("not a valid URL")
  49. }
  50. if strings.Contains(u.Scheme, baseScheme) {
  51. isUrl = true
  52. }
  53. if !isUrl {
  54. var f *os.File
  55. var err error
  56. if input == "-" {
  57. data = bufio.NewReader(os.Stdin)
  58. } else {
  59. f, err = os.Open(input)
  60. if err != nil {
  61. log.Fatal(err)
  62. }
  63. data = bufio.NewReader(f)
  64. }
  65. } else {
  66. if *baseUrl == "" {
  67. *baseUrl = fmt.Sprintf("%v://%v%v", u.Scheme, u.Host, path.Dir(u.EscapedPath()))
  68. }
  69. r, err := http.Get(u.String())
  70. if err != nil {
  71. log.Fatal(err)
  72. }
  73. outputJson.URL = u.String()
  74. outputJson.BaseUrl = *baseUrl
  75. data = bufio.NewReader(r.Body)
  76. }
  77. p, listType, err := m3u8.DecodeFrom(data, true)
  78. if err != nil {
  79. log.Fatal(err)
  80. }
  81. switch listType {
  82. case m3u8.MEDIA:
  83. outputJson.Type = PLAYLIST
  84. playlist := p.(*m3u8.MediaPlaylist)
  85. playlist.Segments = playlist.Segments[:nilIndex(playlist.Segments)]
  86. for _, entry := range playlist.Segments {
  87. u, err := url.Parse(entry.URI)
  88. if err != nil {
  89. log.Fatal("not a valid URL")
  90. }
  91. if *abs && !u.IsAbs() && *baseUrl != "" {
  92. entry.URI = *baseUrl + "/" + entry.URI
  93. }
  94. }
  95. outputJson.Manifest = playlist
  96. case m3u8.MASTER:
  97. outputJson.Type = MASTER
  98. master := p.(*m3u8.MasterPlaylist)
  99. for _, entry := range master.Variants {
  100. var chunckUrl string
  101. u, err := url.Parse(entry.URI)
  102. if err != nil {
  103. log.Fatal("not a valid URL")
  104. }
  105. if !u.IsAbs() {
  106. chunckUrl = *baseUrl + "/" + entry.URI
  107. if *abs && *baseUrl != "" {
  108. entry.URI = chunckUrl
  109. }
  110. } else {
  111. chunckUrl = entry.URI
  112. }
  113. if isUrl && *recursive {
  114. clist, err := http.Get(chunckUrl)
  115. if err != nil {
  116. log.Fatal(err)
  117. }
  118. cdata := bufio.NewReader(clist.Body)
  119. p, _, _ := m3u8.DecodeFrom(cdata, true)
  120. playlist := p.(*m3u8.MediaPlaylist)
  121. playlist.Segments = playlist.Segments[:nilIndex(playlist.Segments)]
  122. for _, entry := range playlist.Segments {
  123. u, err := url.Parse(entry.URI)
  124. if err != nil {
  125. log.Fatal("not a valid URL")
  126. }
  127. if *abs && !u.IsAbs() {
  128. entry.URI = *baseUrl + "/" + entry.URI
  129. }
  130. }
  131. entry.Chunklist = playlist
  132. }
  133. }
  134. outputJson.Manifest = master
  135. }
  136. output, err := json.MarshalIndent(outputJson, "", " ")
  137. if err != nil {
  138. log.Fatal(err)
  139. }
  140. fmt.Printf("%s", output)
  141. }