-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathwork.go
186 lines (158 loc) · 4.03 KB
/
work.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
package mediago
import (
"bytes"
"encoding/hex"
"errors"
"fmt"
"net/url"
"os"
"path"
"caorushizi.cn/mediago/utils"
"github.com/grafov/m3u8"
)
func processSegment(params DownloadParams, errParams chan<- DownloadParams) {
fmt.Printf("开始下载:%v\n", params)
var (
downloadFile *os.File
filepath = path.Join(params.Local, params.Name)
content []byte
err error
)
// 判断文件是否存在,如果存在则跳过下载
if utils.FileExist(filepath) {
return
}
if content, err = utils.HttpGet(params.Url); err != nil {
utils.Logger.Error(err)
errParams <- params
fmt.Printf("下载失败,正在重试。")
return
}
decoder := *params.Decoder
switch decoder.Method {
case "AES-128":
if content, err = utils.AES128Decrypt(content, decoder.Key, decoder.Iv); err != nil {
utils.Logger.Error(err)
return
}
}
if downloadFile, err = os.Create(filepath); err != nil {
utils.Logger.Error(err)
return
}
if _, err = downloadFile.Write(content); err != nil {
utils.Logger.Error(err)
return
}
if err = downloadFile.Close(); err != nil {
utils.Logger.Error(err)
return
}
}
func processM3u8File(params DownloadParams) ([]DownloadParams, error) {
var (
err error
playlist *m3u8.MediaPlaylist
baseMediaDir string // 分片文件文件夹下载路径
segmentDir string // 分片文件下载具体路径 = baseMediaDir + segmentDirName
downloadList []DownloadParams
)
outFile := utils.PathJoin(params.Local, fmt.Sprintf("%s.mp4", params.Name))
if utils.FileExist(outFile) {
return nil, errors.New("文件已经存在!")
}
if err = utils.PrepareDir(params.Local); err != nil {
return nil, err
}
// 开始处理 http 请求
utils.Logger.Debugf("开始解析 m3u8 文件")
var (
listType m3u8.ListType
p m3u8.Playlist
)
var content []byte
if content, err = utils.HttpGet(params.Url); err != nil {
return nil, err
}
fmt.Printf("下载完成123123123")
m3u8Reader := bytes.NewReader(content)
if p, listType, err = m3u8.DecodeFrom(m3u8Reader, true); err != nil {
return nil, err
}
switch listType {
case m3u8.MEDIA:
playlist = p.(*m3u8.MediaPlaylist)
if playlist == nil {
return nil, errors.New("片段列表为空")
}
// 创建视频集合文件夹
baseMediaDir = utils.PathJoin(params.Local, params.Name)
if err = utils.PrepareDir(baseMediaDir); err != nil {
return nil, err
}
// 创建视频片段文件夹
segmentDir = utils.PathJoin(baseMediaDir, "part_1")
if err = utils.PrepareDir(segmentDir); err != nil {
return nil, err
}
var (
segmentKey *m3u8.Key
)
for index, segment := range playlist.Segments {
if segment == nil {
continue
}
var segmentUrl string
if segmentUrl, err = utils.ResolveUrl(segment.URI, params.Url); err != nil {
// todo: 处理错误
return nil, err
}
// 当前片段是否含有 key ,如果没有则使用上一个片段的 key
if segment.Key != nil {
segmentKey = segment.Key
utils.ParseKeyFromUrl(segmentKey, params.Url)
}
var (
method string
key []byte
iv []byte
)
if segmentKey == nil {
method = ""
} else {
method = segmentKey.Method
key = utils.CachedKey[segmentKey]
if iv, err = hex.DecodeString(segmentKey.IV[2:]); err != nil {
return nil, err
}
}
downloadList = append(downloadList, DownloadParams{
Name: fmt.Sprintf("%06d.ts", index),
Local: segmentDir,
Url: segmentUrl,
Decoder: &Decoder{
Method: method,
Key: key,
Iv: iv,
},
})
}
return downloadList, nil
case m3u8.MASTER:
masterPlaylist := p.(*m3u8.MasterPlaylist)
variants := masterPlaylist.Variants
// todo: 这里选择清晰度
selected := variants[0]
urlStr := selected.URI
var urlOb *url.URL
if !utils.IsUrl(urlStr) {
if urlOb, err = url.Parse(params.Url); err != nil {
return nil, err
}
urlOb.Path = urlStr
}
params.Url = urlOb.String()
return processM3u8File(params)
}
return nil, errors.New("没有匹配到正确的媒体类型")
}