hs-m3u8 0.1.5__py3-none-any.whl → 0.1.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
hs_m3u8/__init__.py
CHANGED
hs_m3u8/main.py
CHANGED
|
@@ -16,6 +16,8 @@ from zipfile import ZipFile
|
|
|
16
16
|
|
|
17
17
|
import m3u8
|
|
18
18
|
from hssp import Net
|
|
19
|
+
from hssp.models.net import RequestModel
|
|
20
|
+
from hssp.network.response import Response
|
|
19
21
|
from hssp.utils import crypto
|
|
20
22
|
from loguru import logger
|
|
21
23
|
|
|
@@ -80,6 +82,12 @@ class M3u8Downloader:
|
|
|
80
82
|
headers=None,
|
|
81
83
|
key: M3u8Key = None,
|
|
82
84
|
get_m3u8_func: Callable = None,
|
|
85
|
+
m3u8_request_before: Callable[[RequestModel], RequestModel] = None,
|
|
86
|
+
m3u8_response_after: Callable[[Response], Response] = None,
|
|
87
|
+
key_request_before: Callable[[RequestModel], RequestModel] = None,
|
|
88
|
+
key_response_after: Callable[[Response], Response] = None,
|
|
89
|
+
ts_request_before: Callable[[RequestModel], RequestModel] = None,
|
|
90
|
+
ts_response_after: Callable[[Response], Response] = None,
|
|
83
91
|
):
|
|
84
92
|
"""
|
|
85
93
|
|
|
@@ -91,11 +99,38 @@ class M3u8Downloader:
|
|
|
91
99
|
headers: 情求头
|
|
92
100
|
get_m3u8_func: 处理m3u8情求的回调函数。适用于m3u8地址不是真正的地址,
|
|
93
101
|
而是包含m3u8内容的情求,会把m3u8_url的响应传递给get_m3u8_func,要求返回真正的m3u8内容
|
|
102
|
+
m3u8_request_before: m3u8请求前的回调函数
|
|
103
|
+
m3u8_response_after: m3u8响应后的回调函数
|
|
104
|
+
key_request_before: key请求前的回调函数
|
|
105
|
+
key_response_after: key响应后的回调函数
|
|
106
|
+
ts_request_before: ts请求前的回调函数
|
|
107
|
+
ts_response_after: ts响应后的回调函数
|
|
94
108
|
"""
|
|
95
109
|
|
|
96
110
|
sem = asyncio.Semaphore(max_workers) if max_workers else None
|
|
97
111
|
self.headers = headers
|
|
98
|
-
|
|
112
|
+
|
|
113
|
+
# m3u8 内容的请求器
|
|
114
|
+
self.m3u8_net = Net(sem=sem)
|
|
115
|
+
if m3u8_request_before:
|
|
116
|
+
self.m3u8_net.request_before_signal.connect(m3u8_request_before)
|
|
117
|
+
if m3u8_response_after:
|
|
118
|
+
self.m3u8_net.response_after_signal.connect(m3u8_response_after)
|
|
119
|
+
|
|
120
|
+
# 加密key的请求器
|
|
121
|
+
self.key_net = Net()
|
|
122
|
+
if key_request_before:
|
|
123
|
+
self.key_net.request_before_signal.connect(key_request_before)
|
|
124
|
+
if key_response_after:
|
|
125
|
+
self.key_net.response_after_signal.connect(key_response_after)
|
|
126
|
+
|
|
127
|
+
# ts内容的请求器
|
|
128
|
+
self.ts_net = Net()
|
|
129
|
+
if ts_request_before:
|
|
130
|
+
self.ts_net.request_before_signal.connect(ts_request_before)
|
|
131
|
+
if ts_response_after:
|
|
132
|
+
self.ts_net.response_after_signal.connect(ts_response_after)
|
|
133
|
+
|
|
99
134
|
self.decrypt = decrypt
|
|
100
135
|
self.m3u8_url = urlparse(m3u8_url)
|
|
101
136
|
self.get_m3u8_func = get_m3u8_func
|
|
@@ -112,7 +147,9 @@ class M3u8Downloader:
|
|
|
112
147
|
|
|
113
148
|
async def run(self, merge=True, del_hls=False):
|
|
114
149
|
await self.start(merge, del_hls)
|
|
115
|
-
await self.
|
|
150
|
+
await self.m3u8_net.close()
|
|
151
|
+
await self.key_net.close()
|
|
152
|
+
await self.ts_net.close()
|
|
116
153
|
|
|
117
154
|
async def start(self, merge=True, del_hls=False):
|
|
118
155
|
"""
|
|
@@ -122,6 +159,7 @@ class M3u8Downloader:
|
|
|
122
159
|
:return:
|
|
123
160
|
"""
|
|
124
161
|
mp4_path = self.save_dir.parent / f"{self.save_name}.mp4"
|
|
162
|
+
mp4_path = mp4_path.absolute()
|
|
125
163
|
if Path(mp4_path).exists():
|
|
126
164
|
self.logger.info(f"{mp4_path}已存在")
|
|
127
165
|
if del_hls:
|
|
@@ -131,7 +169,7 @@ class M3u8Downloader:
|
|
|
131
169
|
self.logger.info(
|
|
132
170
|
f"开始下载: 合并ts为mp4={merge}, "
|
|
133
171
|
f"删除hls信息={del_hls}, "
|
|
134
|
-
f"下载地址为:{self.m3u8_url.geturl()}. 保存路径为:{self.save_dir}"
|
|
172
|
+
f"下载地址为:{self.m3u8_url.geturl()}. 保存路径为:{self.save_dir.absolute()}"
|
|
135
173
|
)
|
|
136
174
|
|
|
137
175
|
await self._download()
|
|
@@ -141,7 +179,7 @@ class M3u8Downloader:
|
|
|
141
179
|
self.logger.info(f"TS应下载数量为:{count_1}, 实际下载数量为:{count_2}")
|
|
142
180
|
if count_1 == 0 or count_2 == 0:
|
|
143
181
|
self.logger.error("ts数量为0,请检查!!!")
|
|
144
|
-
return
|
|
182
|
+
return None
|
|
145
183
|
|
|
146
184
|
if count_2 != count_1:
|
|
147
185
|
self.logger.error(f"ts下载数量与实际数量不符合!!!应该下载数量为:{count_1}, 实际下载数量为:{count_2}")
|
|
@@ -182,7 +220,7 @@ class M3u8Downloader:
|
|
|
182
220
|
:param url:
|
|
183
221
|
:return:
|
|
184
222
|
"""
|
|
185
|
-
resp = await self.
|
|
223
|
+
resp = await self.m3u8_net.get(url.geturl(), headers=self.headers)
|
|
186
224
|
m3u8_text = self.get_m3u8_func(resp.text) if self.get_m3u8_func else resp.text
|
|
187
225
|
m3u8_obj = m3u8.loads(m3u8_text)
|
|
188
226
|
prefix = f"{url.scheme}://{url.netloc}"
|
|
@@ -220,7 +258,7 @@ class M3u8Downloader:
|
|
|
220
258
|
if len(m3u8_obj.keys) > 0 and m3u8_obj.keys[0]:
|
|
221
259
|
iv = m3u8_obj.keys[0].iv
|
|
222
260
|
if not self.custom_key:
|
|
223
|
-
resp = await self.
|
|
261
|
+
resp = await self.key_net.get(m3u8_obj.keys[0].absolute_uri, headers=self.headers)
|
|
224
262
|
key_data = resp.content
|
|
225
263
|
else:
|
|
226
264
|
key_data = self.custom_key.key
|
|
@@ -252,13 +290,13 @@ class M3u8Downloader:
|
|
|
252
290
|
if Path(ts_path).exists():
|
|
253
291
|
self.ts_path_list[index] = str(ts_path)
|
|
254
292
|
return
|
|
255
|
-
resp = await self.
|
|
293
|
+
resp = await self.ts_net.get(ts_item["uri"], self.headers)
|
|
256
294
|
ts_content = resp.content
|
|
257
295
|
if ts_content is None:
|
|
258
296
|
return
|
|
259
297
|
|
|
260
298
|
if self.ts_key and self.decrypt:
|
|
261
|
-
ts_content = crypto.
|
|
299
|
+
ts_content = crypto.decrypt_aes_256_cbc(ts_content, self.ts_key.key, self.ts_key.iv)
|
|
262
300
|
|
|
263
301
|
self.save_file(ts_content, ts_path)
|
|
264
302
|
self.logger.info(f"{ts_uri}下载成功")
|
|
@@ -282,10 +320,10 @@ class M3u8Downloader:
|
|
|
282
320
|
# mp4路径
|
|
283
321
|
mp4_path = self.save_dir.parent / f"{self.save_name}.mp4"
|
|
284
322
|
|
|
285
|
-
#
|
|
323
|
+
# 如果有mp4的头,则把ts放到后面
|
|
286
324
|
mp4_head_data = b""
|
|
287
325
|
if self.mp4_head_hrl:
|
|
288
|
-
resp = await self.
|
|
326
|
+
resp = await self.ts_net.get(self.mp4_head_hrl)
|
|
289
327
|
mp4_head_data = resp.content
|
|
290
328
|
mp4_head_file = self.save_dir / "head.mp4"
|
|
291
329
|
mp4_head_file.write_bytes(mp4_head_data)
|
|
@@ -297,7 +335,7 @@ class M3u8Downloader:
|
|
|
297
335
|
with open(path, "rb") as ts_file:
|
|
298
336
|
data = ts_file.read()
|
|
299
337
|
if self.ts_key:
|
|
300
|
-
data = crypto.
|
|
338
|
+
data = crypto.decrypt_aes_256_cbc(data, self.ts_key.key, self.ts_key.iv)
|
|
301
339
|
big_ts_file.write(data)
|
|
302
340
|
big_ts_file.close()
|
|
303
341
|
self.logger.info("ts文件整合完毕")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: hs-m3u8
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.7
|
|
4
4
|
Summary: m3u8 下载器
|
|
5
5
|
Project-URL: homepage, https://github.com/x-haose/hs-m3u8
|
|
6
6
|
Project-URL: repository, https://github.com/x-haose/hs-m3u8
|
|
@@ -20,7 +20,7 @@ Classifier: Programming Language :: Python :: 3.12
|
|
|
20
20
|
Classifier: Programming Language :: Python :: 3.13
|
|
21
21
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
22
|
Requires-Python: >=3.10
|
|
23
|
-
Requires-Dist: hssp>=0.4.
|
|
23
|
+
Requires-Dist: hssp>=0.4.18
|
|
24
24
|
Requires-Dist: m3u8>=6.0.0
|
|
25
25
|
Description-Content-Type: text/markdown
|
|
26
26
|
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
hs_m3u8/__init__.py,sha256=_AhYioHAgwPXE10FXGZ3ZKj1urwFYR0L9xzBn8pQPJw,72
|
|
2
|
+
hs_m3u8/main.py,sha256=dyRy7ciRMbvrrjAE01mhjuw1Wj4mHG_DZiJNHHVtJ9Y,13403
|
|
3
|
+
hs_m3u8/res/ffmpeg_win.exe.zip,sha256=x_7Fa9N3hzN1d7Ph9ZwOiwpuRfLEVnhNL8tPjuZZMe0,60131319
|
|
4
|
+
hs_m3u8-0.1.7.dist-info/METADATA,sha256=w3wygMm94rIns6-RxhisG85tS7myzNSconLpH7sJPus,2205
|
|
5
|
+
hs_m3u8-0.1.7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
6
|
+
hs_m3u8-0.1.7.dist-info/RECORD,,
|
hs_m3u8-0.1.5.dist-info/RECORD
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
hs_m3u8/__init__.py,sha256=HINaNDvyRMsgqg9VY_AsV9ierd8KhdtNyJRdQ8BcFg8,72
|
|
2
|
-
hs_m3u8/main.py,sha256=jZ0650qosfrhiS1r3-UGhjp8shx6TvcElXAEls7f3jQ,11609
|
|
3
|
-
hs_m3u8/res/ffmpeg_win.exe.zip,sha256=x_7Fa9N3hzN1d7Ph9ZwOiwpuRfLEVnhNL8tPjuZZMe0,60131319
|
|
4
|
-
hs_m3u8-0.1.5.dist-info/METADATA,sha256=3htPtN-CKSxXaS3o9oootUP4RMdS_tQSIyn4vBT0B4I,2204
|
|
5
|
-
hs_m3u8-0.1.5.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
6
|
-
hs_m3u8-0.1.5.dist-info/RECORD,,
|
|
File without changes
|