hs-m3u8 0.1.4__py3-none-any.whl → 0.1.6__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
|
@@ -9,12 +9,14 @@ import shutil
|
|
|
9
9
|
import subprocess
|
|
10
10
|
from collections.abc import Callable
|
|
11
11
|
from hashlib import md5
|
|
12
|
+
from importlib import resources
|
|
12
13
|
from pathlib import Path
|
|
13
14
|
from urllib.parse import urljoin, urlparse
|
|
14
15
|
from zipfile import ZipFile
|
|
15
16
|
|
|
16
17
|
import m3u8
|
|
17
18
|
from hssp import Net
|
|
19
|
+
from hssp.models.net import RequestModel
|
|
18
20
|
from hssp.utils import crypto
|
|
19
21
|
from loguru import logger
|
|
20
22
|
|
|
@@ -28,20 +30,18 @@ def get_ffmpeg():
|
|
|
28
30
|
if current_os != "Windows":
|
|
29
31
|
return "ffmpeg"
|
|
30
32
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
+
with resources.as_file(resources.files("hs_m3u8.res")) as package_dir:
|
|
34
|
+
ffmpeg_bin = package_dir / "ffmpeg_win.exe"
|
|
35
|
+
if ffmpeg_bin.exists():
|
|
36
|
+
return str(ffmpeg_bin)
|
|
33
37
|
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
# ZIP 文件
|
|
39
|
+
ffmpeg_bin_zip = package_dir / "ffmpeg_win.exe.zip"
|
|
40
|
+
if ffmpeg_bin_zip.exists():
|
|
41
|
+
with ZipFile(ffmpeg_bin_zip, "r") as zip_ref:
|
|
42
|
+
zip_ref.extractall(ffmpeg_bin.parent)
|
|
36
43
|
|
|
37
|
-
|
|
38
|
-
ffmpeg_bin_zip = Path(ffmpeg_bin.parent) / f"{ffmpeg_bin.name}.zip"
|
|
39
|
-
if ffmpeg_bin_zip.exists():
|
|
40
|
-
# 解压缩到同一目录
|
|
41
|
-
with ZipFile(ffmpeg_bin_zip, "r") as zip_ref:
|
|
42
|
-
zip_ref.extractall(ffmpeg_bin.parent)
|
|
43
|
-
|
|
44
|
-
return ffmpeg_bin
|
|
44
|
+
return ffmpeg_bin
|
|
45
45
|
|
|
46
46
|
|
|
47
47
|
class M3u8Key:
|
|
@@ -81,6 +81,9 @@ class M3u8Downloader:
|
|
|
81
81
|
headers=None,
|
|
82
82
|
key: M3u8Key = None,
|
|
83
83
|
get_m3u8_func: Callable = None,
|
|
84
|
+
m3u8_request_before: Callable[[RequestModel], RequestModel] = None,
|
|
85
|
+
key_request_before: Callable[[RequestModel], RequestModel] = None,
|
|
86
|
+
ts_request_before: Callable[[RequestModel], RequestModel] = None,
|
|
84
87
|
):
|
|
85
88
|
"""
|
|
86
89
|
|
|
@@ -92,11 +95,29 @@ class M3u8Downloader:
|
|
|
92
95
|
headers: 情求头
|
|
93
96
|
get_m3u8_func: 处理m3u8情求的回调函数。适用于m3u8地址不是真正的地址,
|
|
94
97
|
而是包含m3u8内容的情求,会把m3u8_url的响应传递给get_m3u8_func,要求返回真正的m3u8内容
|
|
98
|
+
m3u8_request_before: m3u8请求前的回调函数
|
|
99
|
+
key_request_before: key请求前的回调函数
|
|
100
|
+
ts_request_before: ts 请求前的回调函数
|
|
95
101
|
"""
|
|
96
102
|
|
|
97
103
|
sem = asyncio.Semaphore(max_workers) if max_workers else None
|
|
98
104
|
self.headers = headers
|
|
99
|
-
|
|
105
|
+
|
|
106
|
+
# m3u8 内容的请求器
|
|
107
|
+
self.m3u8_net = Net(sem=sem)
|
|
108
|
+
if m3u8_request_before:
|
|
109
|
+
self.m3u8_net.request_before_signal.connect(m3u8_request_before)
|
|
110
|
+
|
|
111
|
+
# 加密key的请求器
|
|
112
|
+
self.key_net = Net()
|
|
113
|
+
if key_request_before:
|
|
114
|
+
self.key_net.request_before_signal.connect(key_request_before)
|
|
115
|
+
|
|
116
|
+
# ts内容的请求器
|
|
117
|
+
self.ts_net = Net()
|
|
118
|
+
if ts_request_before:
|
|
119
|
+
self.ts_net.request_before_signal.connect(ts_request_before)
|
|
120
|
+
|
|
100
121
|
self.decrypt = decrypt
|
|
101
122
|
self.m3u8_url = urlparse(m3u8_url)
|
|
102
123
|
self.get_m3u8_func = get_m3u8_func
|
|
@@ -113,7 +134,9 @@ class M3u8Downloader:
|
|
|
113
134
|
|
|
114
135
|
async def run(self, merge=True, del_hls=False):
|
|
115
136
|
await self.start(merge, del_hls)
|
|
116
|
-
await self.
|
|
137
|
+
await self.m3u8_net.close()
|
|
138
|
+
await self.key_net.close()
|
|
139
|
+
await self.ts_net.close()
|
|
117
140
|
|
|
118
141
|
async def start(self, merge=True, del_hls=False):
|
|
119
142
|
"""
|
|
@@ -183,7 +206,7 @@ class M3u8Downloader:
|
|
|
183
206
|
:param url:
|
|
184
207
|
:return:
|
|
185
208
|
"""
|
|
186
|
-
resp = await self.
|
|
209
|
+
resp = await self.m3u8_net.get(url.geturl(), headers=self.headers)
|
|
187
210
|
m3u8_text = self.get_m3u8_func(resp.text) if self.get_m3u8_func else resp.text
|
|
188
211
|
m3u8_obj = m3u8.loads(m3u8_text)
|
|
189
212
|
prefix = f"{url.scheme}://{url.netloc}"
|
|
@@ -221,7 +244,7 @@ class M3u8Downloader:
|
|
|
221
244
|
if len(m3u8_obj.keys) > 0 and m3u8_obj.keys[0]:
|
|
222
245
|
iv = m3u8_obj.keys[0].iv
|
|
223
246
|
if not self.custom_key:
|
|
224
|
-
resp = await self.
|
|
247
|
+
resp = await self.key_net.get(m3u8_obj.keys[0].absolute_uri, headers=self.headers)
|
|
225
248
|
key_data = resp.content
|
|
226
249
|
else:
|
|
227
250
|
key_data = self.custom_key.key
|
|
@@ -253,7 +276,7 @@ class M3u8Downloader:
|
|
|
253
276
|
if Path(ts_path).exists():
|
|
254
277
|
self.ts_path_list[index] = str(ts_path)
|
|
255
278
|
return
|
|
256
|
-
resp = await self.
|
|
279
|
+
resp = await self.ts_net.get(ts_item["uri"], self.headers)
|
|
257
280
|
ts_content = resp.content
|
|
258
281
|
if ts_content is None:
|
|
259
282
|
return
|
|
@@ -283,10 +306,10 @@ class M3u8Downloader:
|
|
|
283
306
|
# mp4路径
|
|
284
307
|
mp4_path = self.save_dir.parent / f"{self.save_name}.mp4"
|
|
285
308
|
|
|
286
|
-
#
|
|
309
|
+
# 如果有mp4的头,则把ts放到后面
|
|
287
310
|
mp4_head_data = b""
|
|
288
311
|
if self.mp4_head_hrl:
|
|
289
|
-
resp = await self.
|
|
312
|
+
resp = await self.ts_net.get(self.mp4_head_hrl)
|
|
290
313
|
mp4_head_data = resp.content
|
|
291
314
|
mp4_head_file = self.save_dir / "head.mp4"
|
|
292
315
|
mp4_head_file.write_bytes(mp4_head_data)
|
|
Binary file
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
hs_m3u8/__init__.py,sha256=_AhYioHAgwPXE10FXGZ3ZKj1urwFYR0L9xzBn8pQPJw,72
|
|
2
|
+
hs_m3u8/main.py,sha256=dickli-bmyAoNB7N3pmx2UU_VUDGSISU913BB-VwMbk,12620
|
|
3
|
+
hs_m3u8/res/ffmpeg_win.exe.zip,sha256=x_7Fa9N3hzN1d7Ph9ZwOiwpuRfLEVnhNL8tPjuZZMe0,60131319
|
|
4
|
+
hs_m3u8-0.1.6.dist-info/METADATA,sha256=ujcGSSJnM5o_uWCgXDnfmweC0t4iWwqqCaMNvticSzI,2204
|
|
5
|
+
hs_m3u8-0.1.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
6
|
+
hs_m3u8-0.1.6.dist-info/RECORD,,
|
hs_m3u8-0.1.4.dist-info/RECORD
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
hs_m3u8/__init__.py,sha256=WxYMLrnGwdYDEmbxZmUV-l2DPs9jrYDP0cAnHxkqtFs,72
|
|
2
|
-
hs_m3u8/main.py,sha256=RELt4z7AM7OuXYiRkCe-yf4A1JGQ9FtIaBj6Vov3Ig0,11574
|
|
3
|
-
hs_m3u8-0.1.4.dist-info/METADATA,sha256=ddVI5SkdoINuFHSPS9uFGDeOmCybhT1al4_4SmXPHRs,2204
|
|
4
|
-
hs_m3u8-0.1.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
5
|
-
hs_m3u8-0.1.4.dist-info/RECORD,,
|
|
File without changes
|