Initial Commit
This commit is contained in:
commit
001c761fe8
8
.idea/.gitignore
generated
vendored
Normal file
8
.idea/.gitignore
generated
vendored
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
# Default ignored files
|
||||||
|
/shelf/
|
||||||
|
/workspace.xml
|
||||||
|
# Editor-based HTTP Client requests
|
||||||
|
/httpRequests/
|
||||||
|
# Datasource local storage ignored files
|
||||||
|
/dataSources/
|
||||||
|
/dataSources.local.xml
|
||||||
9
.idea/m3u8-downloader.iml
generated
Normal file
9
.idea/m3u8-downloader.iml
generated
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<module type="WEB_MODULE" version="4">
|
||||||
|
<component name="Go" enabled="true" />
|
||||||
|
<component name="NewModuleRootManager">
|
||||||
|
<content url="file://$MODULE_DIR$" />
|
||||||
|
<orderEntry type="inheritedJdk" />
|
||||||
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
</component>
|
||||||
|
</module>
|
||||||
8
.idea/modules.xml
generated
Normal file
8
.idea/modules.xml
generated
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="ProjectModuleManager">
|
||||||
|
<modules>
|
||||||
|
<module fileurl="file://$PROJECT_DIR$/.idea/m3u8-downloader.iml" filepath="$PROJECT_DIR$/.idea/m3u8-downloader.iml" />
|
||||||
|
</modules>
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
6
.idea/vcs.xml
generated
Normal file
6
.idea/vcs.xml
generated
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project version="4">
|
||||||
|
<component name="VcsDirectoryMappings">
|
||||||
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
|
</component>
|
||||||
|
</project>
|
||||||
15
main.go
Normal file
15
main.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"m3u8-downloader/media"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
|
||||||
|
master_url := "https://d17cyqyz9yhmep.cloudfront.net/streams/234945/playlist_1752291107574_1752292056713.m3u8"
|
||||||
|
|
||||||
|
streams := media.GetStreamMetadata(master_url)
|
||||||
|
|
||||||
|
fmt.Println(streams)
|
||||||
|
}
|
||||||
113
media/types.go
Normal file
113
media/types.go
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
package media
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"regexp"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type StreamSet struct {
|
||||||
|
PlaylistURL string
|
||||||
|
VideoURLs []VideoURL
|
||||||
|
AudioURLs []AudioURL
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetStreamMetadata(master_url string) *StreamSet {
|
||||||
|
resp, err := http.Get(master_url)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
panic(resp.StatusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
data, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
content := string(data)
|
||||||
|
lines := strings.Split(content, "\n")
|
||||||
|
video_urls := []VideoURL{}
|
||||||
|
audio_urls := []AudioURL{}
|
||||||
|
for i, line := range lines {
|
||||||
|
if strings.HasPrefix(line, "#EXT-X-STREAM-INF") {
|
||||||
|
video := NewVideoURL(lines[i], lines[i+1])
|
||||||
|
video_urls = append(video_urls, *video)
|
||||||
|
} else if strings.HasPrefix(line, "#EXT-X-MEDIA") {
|
||||||
|
audio := NewAudioURL(lines[i])
|
||||||
|
audio_urls = append(audio_urls, *audio)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &StreamSet{
|
||||||
|
PlaylistURL: master_url,
|
||||||
|
VideoURLs: video_urls,
|
||||||
|
AudioURLs: audio_urls,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type VideoURL struct {
|
||||||
|
URL string
|
||||||
|
Bandwidth int
|
||||||
|
Codecs string
|
||||||
|
Resolution string
|
||||||
|
FrameRate string
|
||||||
|
Audio string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewVideoURL(input string, url string) *VideoURL {
|
||||||
|
if strings.HasPrefix(input, "#EXT-X-STREAM-INF") {
|
||||||
|
reg := regexp.MustCompile(`([A-Z0-9-]+)=(".*?"|[^,]*)`)
|
||||||
|
split := reg.FindAllStringSubmatch(input, -1)
|
||||||
|
bandwidth := split[0][2]
|
||||||
|
bandwidth_int, err := strconv.Atoi(bandwidth)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
video := VideoURL{
|
||||||
|
URL: url,
|
||||||
|
Bandwidth: bandwidth_int,
|
||||||
|
Codecs: split[1][2],
|
||||||
|
Resolution: split[2][2],
|
||||||
|
FrameRate: split[3][2],
|
||||||
|
Audio: split[4][2],
|
||||||
|
}
|
||||||
|
return &video
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type AudioURL struct {
|
||||||
|
URL string
|
||||||
|
MediaType string
|
||||||
|
GroupId string
|
||||||
|
Name string
|
||||||
|
Default string
|
||||||
|
Autoselect string
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAudioURL(input string) *AudioURL {
|
||||||
|
if strings.HasPrefix(input, "#EXT-X-MEDIA") {
|
||||||
|
split := strings.Split(strings.Split(input, ":")[1], ",")
|
||||||
|
url := ParseAttribute(split[5])
|
||||||
|
mediaType := ParseAttribute(split[0])
|
||||||
|
groupId := ParseAttribute(split[1])
|
||||||
|
name := ParseAttribute(split[2])
|
||||||
|
default_ := ParseAttribute(split[3])
|
||||||
|
autoselect := ParseAttribute(split[4])
|
||||||
|
audio := AudioURL{
|
||||||
|
URL: url,
|
||||||
|
MediaType: mediaType,
|
||||||
|
GroupId: groupId,
|
||||||
|
Name: name,
|
||||||
|
Default: default_,
|
||||||
|
Autoselect: autoselect,
|
||||||
|
}
|
||||||
|
return &audio
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
24
media/utils.go
Normal file
24
media/utils.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package media
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ParseAttribute(attribute string) string {
|
||||||
|
split := strings.Split(attribute, "=")
|
||||||
|
return split[1]
|
||||||
|
}
|
||||||
|
|
||||||
|
func ResolutionToPixels(resolution string) int {
|
||||||
|
split := strings.Split(resolution, "x")
|
||||||
|
width, err := strconv.Atoi(split[0])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
height, err := strconv.Atoi(split[1])
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
return width * height
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user