hs-m3u8 0.1.6__tar.gz → 0.1.7__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: hs-m3u8
3
- Version: 0.1.6
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.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
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "hs-m3u8"
3
- version = "0.1.6"
3
+ version = "0.1.7"
4
4
  description = "m3u8 下载器"
5
5
  authors = [
6
6
  { name = "昊色居士", email = "xhrtxh@gmail.com" }
@@ -26,7 +26,7 @@ requires-python = ">= 3.10"
26
26
 
27
27
  dependencies = [
28
28
  "m3u8>=6.0.0",
29
- "hssp>=0.4.4",
29
+ "hssp>=0.4.18",
30
30
  ]
31
31
 
32
32
  [project.urls]
@@ -38,26 +38,14 @@ documentation = "https://github.com/x-haose/hs-m3u8"
38
38
  requires = ["hatchling"]
39
39
  build-backend = "hatchling.build"
40
40
 
41
- [tool.rye]
42
- managed = true
43
- dev-dependencies = [
44
- "pre-commit>=4.0.1",
45
- "twine>=6.0.1",
46
- ]
41
+ [tool.hatch.build.targets.sdist]
47
42
  include = [
48
- "src/hs_m3u8/"
43
+ "src/hs_m3u8",
49
44
  ]
50
45
 
51
- [tool.hatch.metadata]
52
- allow-direct-references = true
53
-
54
46
  [tool.hatch.build.targets.wheel]
55
47
  packages = ["src/hs_m3u8"]
56
48
 
57
- [[tool.rye.sources]]
58
- name = "default"
59
- url = "https://pypi.tuna.tsinghua.edu.cn/simple"
60
-
61
49
  [tool.bandit]
62
50
  skips = [
63
51
  "B404",
@@ -127,20 +115,10 @@ ignore = [
127
115
  # do not perform function calls in argument defaults
128
116
  "B008",
129
117
  # too complex
130
- "C901"
118
+ "C901",
131
119
  ]
132
120
  fixable = ["ALL"]
133
121
  unfixable = []
134
122
 
135
123
  [tool.ruff.lint.per-file-ignores]
136
124
  "__init__.py" = ["F401"]
137
-
138
-
139
- [tool.rye.scripts]
140
- publish_testpypi = { cmd = "rye run twine upload -r testpypi dist/*" }
141
- publish_pypi = { cmd = "rye run twine upload dist/*" }
142
- sb = { cmd = "rye build --clean" }
143
- spt = { chain = ["sb", "publish_testpypi"] }
144
- sp = { chain = ["sb", "publish_pypi"] }
145
- check_i = { cmd = "rye run pre-commit install" }
146
- check = { cmd = "rye run pre-commit run --all-files" }
@@ -17,6 +17,7 @@ from zipfile import ZipFile
17
17
  import m3u8
18
18
  from hssp import Net
19
19
  from hssp.models.net import RequestModel
20
+ from hssp.network.response import Response
20
21
  from hssp.utils import crypto
21
22
  from loguru import logger
22
23
 
@@ -82,8 +83,11 @@ class M3u8Downloader:
82
83
  key: M3u8Key = None,
83
84
  get_m3u8_func: Callable = None,
84
85
  m3u8_request_before: Callable[[RequestModel], RequestModel] = None,
86
+ m3u8_response_after: Callable[[Response], Response] = None,
85
87
  key_request_before: Callable[[RequestModel], RequestModel] = None,
88
+ key_response_after: Callable[[Response], Response] = None,
86
89
  ts_request_before: Callable[[RequestModel], RequestModel] = None,
90
+ ts_response_after: Callable[[Response], Response] = None,
87
91
  ):
88
92
  """
89
93
 
@@ -96,8 +100,11 @@ class M3u8Downloader:
96
100
  get_m3u8_func: 处理m3u8情求的回调函数。适用于m3u8地址不是真正的地址,
97
101
  而是包含m3u8内容的情求,会把m3u8_url的响应传递给get_m3u8_func,要求返回真正的m3u8内容
98
102
  m3u8_request_before: m3u8请求前的回调函数
103
+ m3u8_response_after: m3u8响应后的回调函数
99
104
  key_request_before: key请求前的回调函数
100
- ts_request_before: ts 请求前的回调函数
105
+ key_response_after: key响应后的回调函数
106
+ ts_request_before: ts请求前的回调函数
107
+ ts_response_after: ts响应后的回调函数
101
108
  """
102
109
 
103
110
  sem = asyncio.Semaphore(max_workers) if max_workers else None
@@ -107,16 +114,22 @@ class M3u8Downloader:
107
114
  self.m3u8_net = Net(sem=sem)
108
115
  if m3u8_request_before:
109
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)
110
119
 
111
120
  # 加密key的请求器
112
121
  self.key_net = Net()
113
122
  if key_request_before:
114
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)
115
126
 
116
127
  # ts内容的请求器
117
128
  self.ts_net = Net()
118
129
  if ts_request_before:
119
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)
120
133
 
121
134
  self.decrypt = decrypt
122
135
  self.m3u8_url = urlparse(m3u8_url)
@@ -146,6 +159,7 @@ class M3u8Downloader:
146
159
  :return:
147
160
  """
148
161
  mp4_path = self.save_dir.parent / f"{self.save_name}.mp4"
162
+ mp4_path = mp4_path.absolute()
149
163
  if Path(mp4_path).exists():
150
164
  self.logger.info(f"{mp4_path}已存在")
151
165
  if del_hls:
@@ -155,7 +169,7 @@ class M3u8Downloader:
155
169
  self.logger.info(
156
170
  f"开始下载: 合并ts为mp4={merge}, "
157
171
  f"删除hls信息={del_hls}, "
158
- f"下载地址为:{self.m3u8_url.geturl()}. 保存路径为:{self.save_dir}"
172
+ f"下载地址为:{self.m3u8_url.geturl()}. 保存路径为:{self.save_dir.absolute()}"
159
173
  )
160
174
 
161
175
  await self._download()
@@ -165,7 +179,7 @@ class M3u8Downloader:
165
179
  self.logger.info(f"TS应下载数量为:{count_1}, 实际下载数量为:{count_2}")
166
180
  if count_1 == 0 or count_2 == 0:
167
181
  self.logger.error("ts数量为0,请检查!!!")
168
- return
182
+ return None
169
183
 
170
184
  if count_2 != count_1:
171
185
  self.logger.error(f"ts下载数量与实际数量不符合!!!应该下载数量为:{count_1}, 实际下载数量为:{count_2}")
@@ -282,7 +296,7 @@ class M3u8Downloader:
282
296
  return
283
297
 
284
298
  if self.ts_key and self.decrypt:
285
- ts_content = crypto.decrypt_aes_256_cbc_pad7(ts_content, self.ts_key.key, self.ts_key.iv)
299
+ ts_content = crypto.decrypt_aes_256_cbc(ts_content, self.ts_key.key, self.ts_key.iv)
286
300
 
287
301
  self.save_file(ts_content, ts_path)
288
302
  self.logger.info(f"{ts_uri}下载成功")
@@ -321,7 +335,7 @@ class M3u8Downloader:
321
335
  with open(path, "rb") as ts_file:
322
336
  data = ts_file.read()
323
337
  if self.ts_key:
324
- data = crypto.decrypt_aes_256_cbc_pad7(data, self.ts_key.key, self.ts_key.iv)
338
+ data = crypto.decrypt_aes_256_cbc(data, self.ts_key.key, self.ts_key.iv)
325
339
  big_ts_file.write(data)
326
340
  big_ts_file.close()
327
341
  self.logger.info("ts文件整合完毕")
@@ -1,18 +0,0 @@
1
- # See https://pre-commit.com for more information
2
- # See https://pre-commit.com/hooks.html for more hooks
3
- repos:
4
- # bandit
5
- - repo: https://github.com/PyCQA/bandit
6
- rev: 1.7.10
7
- hooks:
8
- - id: bandit
9
- args: [ "-c", "pyproject.toml" ]
10
- additional_dependencies: [ "bandit[toml]" ]
11
-
12
- # ruff
13
- - repo: https://github.com/astral-sh/ruff-pre-commit
14
- rev: 'v0.6.9'
15
- hooks:
16
- - id: ruff
17
- args: [ --fix, --exit-non-zero-on-fix, --show-fixes ]
18
- - id: ruff-format
@@ -1,209 +0,0 @@
1
- # generated by rye
2
- # use `rye lock` or `rye sync` to update this lockfile
3
- #
4
- # last locked with the following flags:
5
- # pre: false
6
- # features: []
7
- # all-features: false
8
- # with-sources: false
9
- # generate-hashes: false
10
- # universal: false
11
-
12
- -e file:.
13
- aiohttp==3.9.5
14
- # via hssp
15
- aiosignal==1.3.1
16
- # via aiohttp
17
- annotated-types==0.7.0
18
- # via pydantic
19
- anyio==4.6.2.post1
20
- # via httpx
21
- apscheduler==3.10.4
22
- # via hssp
23
- attrs==24.2.0
24
- # via aiohttp
25
- blinker==1.9.0
26
- # via hssp
27
- certifi==2024.8.30
28
- # via curl-cffi
29
- # via httpcore
30
- # via httpx
31
- # via requests
32
- cffi==1.17.1
33
- # via curl-cffi
34
- cfgv==3.4.0
35
- # via pre-commit
36
- charset-normalizer==3.4.0
37
- # via requests
38
- click==8.1.7
39
- # via drissionpage
40
- cssselect==1.2.0
41
- # via drissionpage
42
- # via parsel
43
- curl-cffi==0.7.3
44
- # via hssp
45
- datarecorder==3.6.2
46
- # via downloadkit
47
- distlib==0.3.9
48
- # via virtualenv
49
- docutils==0.21.2
50
- # via readme-renderer
51
- downloadkit==2.0.5
52
- # via drissionpage
53
- drissionpage==4.1.0.12
54
- # via hssp
55
- et-xmlfile==2.0.0
56
- # via openpyxl
57
- fake-useragent==1.5.1
58
- # via hssp
59
- filelock==3.16.1
60
- # via tldextract
61
- # via virtualenv
62
- frozenlist==1.5.0
63
- # via aiohttp
64
- # via aiosignal
65
- furl==2.1.3
66
- # via hssp
67
- h11==0.14.0
68
- # via httpcore
69
- h2==4.1.0
70
- # via httpx
71
- hpack==4.0.0
72
- # via h2
73
- hssp==0.4.7
74
- # via hs-m3u8
75
- httpcore==1.0.6
76
- # via httpx
77
- httpx==0.27.2
78
- # via hssp
79
- hyperframe==6.0.1
80
- # via h2
81
- identify==2.6.2
82
- # via pre-commit
83
- idna==3.10
84
- # via anyio
85
- # via httpx
86
- # via requests
87
- # via tldextract
88
- # via yarl
89
- jaraco-classes==3.4.0
90
- # via keyring
91
- jaraco-context==6.0.1
92
- # via keyring
93
- jaraco-functools==4.1.0
94
- # via keyring
95
- jmespath==1.0.1
96
- # via parsel
97
- keyring==25.6.0
98
- # via twine
99
- loguru==0.7.2
100
- # via hssp
101
- lxml==5.3.0
102
- # via drissionpage
103
- # via parsel
104
- m3u8==6.0.0
105
- # via hs-m3u8
106
- markdown-it-py==3.0.0
107
- # via rich
108
- mdurl==0.1.2
109
- # via markdown-it-py
110
- more-itertools==10.6.0
111
- # via jaraco-classes
112
- # via jaraco-functools
113
- multidict==6.1.0
114
- # via aiohttp
115
- # via yarl
116
- nh3==0.2.20
117
- # via readme-renderer
118
- nodeenv==1.9.1
119
- # via pre-commit
120
- openpyxl==3.1.5
121
- # via datarecorder
122
- orderedmultidict==1.0.1
123
- # via furl
124
- packaging==24.2
125
- # via parsel
126
- # via twine
127
- parsel==1.9.1
128
- # via hssp
129
- pkginfo==1.12.0
130
- # via twine
131
- platformdirs==4.3.6
132
- # via virtualenv
133
- pre-commit==4.0.1
134
- propcache==0.2.0
135
- # via yarl
136
- psutil==6.1.0
137
- # via drissionpage
138
- pycparser==2.22
139
- # via cffi
140
- pycryptodomex==3.21.0
141
- # via hssp
142
- pydantic==2.9.2
143
- # via hssp
144
- # via pydantic-settings
145
- pydantic-core==2.23.4
146
- # via pydantic
147
- pydantic-settings==2.6.1
148
- # via hssp
149
- pygments==2.19.1
150
- # via readme-renderer
151
- # via rich
152
- python-dotenv==1.0.1
153
- # via pydantic-settings
154
- pytz==2024.2
155
- # via apscheduler
156
- pyyaml==6.0.2
157
- # via pre-commit
158
- # via pydantic-settings
159
- readme-renderer==44.0
160
- # via twine
161
- requests==2.32.3
162
- # via downloadkit
163
- # via drissionpage
164
- # via hssp
165
- # via requests-file
166
- # via requests-toolbelt
167
- # via tldextract
168
- # via twine
169
- requests-file==2.1.0
170
- # via tldextract
171
- requests-toolbelt==1.0.0
172
- # via twine
173
- rfc3986==2.0.0
174
- # via twine
175
- rich==13.9.4
176
- # via twine
177
- six==1.16.0
178
- # via apscheduler
179
- # via furl
180
- # via orderedmultidict
181
- sniffio==1.3.1
182
- # via anyio
183
- # via httpx
184
- tenacity==9.0.0
185
- # via hssp
186
- tldextract==5.1.3
187
- # via drissionpage
188
- tomli==2.1.0
189
- # via pydantic-settings
190
- twine==6.0.1
191
- typing-extensions==4.12.2
192
- # via curl-cffi
193
- # via pydantic
194
- # via pydantic-core
195
- tzlocal==5.2
196
- # via apscheduler
197
- urllib3==2.2.3
198
- # via requests
199
- # via twine
200
- uvloop==0.21.0
201
- # via hssp
202
- virtualenv==20.27.1
203
- # via pre-commit
204
- w3lib==2.2.1
205
- # via parsel
206
- websocket-client==1.8.0
207
- # via drissionpage
208
- yarl==1.17.1
209
- # via aiohttp
@@ -1,157 +0,0 @@
1
- # generated by rye
2
- # use `rye lock` or `rye sync` to update this lockfile
3
- #
4
- # last locked with the following flags:
5
- # pre: false
6
- # features: []
7
- # all-features: false
8
- # with-sources: false
9
- # generate-hashes: false
10
- # universal: false
11
-
12
- -e file:.
13
- aiohttp==3.9.5
14
- # via hssp
15
- aiosignal==1.3.1
16
- # via aiohttp
17
- annotated-types==0.7.0
18
- # via pydantic
19
- anyio==4.6.2.post1
20
- # via httpx
21
- apscheduler==3.10.4
22
- # via hssp
23
- attrs==24.2.0
24
- # via aiohttp
25
- blinker==1.9.0
26
- # via hssp
27
- certifi==2024.8.30
28
- # via curl-cffi
29
- # via httpcore
30
- # via httpx
31
- # via requests
32
- cffi==1.17.1
33
- # via curl-cffi
34
- charset-normalizer==3.4.0
35
- # via requests
36
- click==8.1.7
37
- # via drissionpage
38
- cssselect==1.2.0
39
- # via drissionpage
40
- # via parsel
41
- curl-cffi==0.7.3
42
- # via hssp
43
- datarecorder==3.6.2
44
- # via downloadkit
45
- downloadkit==2.0.5
46
- # via drissionpage
47
- drissionpage==4.1.0.12
48
- # via hssp
49
- et-xmlfile==2.0.0
50
- # via openpyxl
51
- fake-useragent==1.5.1
52
- # via hssp
53
- filelock==3.16.1
54
- # via tldextract
55
- frozenlist==1.5.0
56
- # via aiohttp
57
- # via aiosignal
58
- furl==2.1.3
59
- # via hssp
60
- h11==0.14.0
61
- # via httpcore
62
- h2==4.1.0
63
- # via httpx
64
- hpack==4.0.0
65
- # via h2
66
- hssp==0.4.7
67
- # via hs-m3u8
68
- httpcore==1.0.6
69
- # via httpx
70
- httpx==0.27.2
71
- # via hssp
72
- hyperframe==6.0.1
73
- # via h2
74
- idna==3.10
75
- # via anyio
76
- # via httpx
77
- # via requests
78
- # via tldextract
79
- # via yarl
80
- jmespath==1.0.1
81
- # via parsel
82
- loguru==0.7.2
83
- # via hssp
84
- lxml==5.3.0
85
- # via drissionpage
86
- # via parsel
87
- m3u8==6.0.0
88
- # via hs-m3u8
89
- multidict==6.1.0
90
- # via aiohttp
91
- # via yarl
92
- openpyxl==3.1.5
93
- # via datarecorder
94
- orderedmultidict==1.0.1
95
- # via furl
96
- packaging==24.2
97
- # via parsel
98
- parsel==1.9.1
99
- # via hssp
100
- propcache==0.2.0
101
- # via yarl
102
- psutil==6.1.0
103
- # via drissionpage
104
- pycparser==2.22
105
- # via cffi
106
- pycryptodomex==3.21.0
107
- # via hssp
108
- pydantic==2.9.2
109
- # via hssp
110
- # via pydantic-settings
111
- pydantic-core==2.23.4
112
- # via pydantic
113
- pydantic-settings==2.6.1
114
- # via hssp
115
- python-dotenv==1.0.1
116
- # via pydantic-settings
117
- pytz==2024.2
118
- # via apscheduler
119
- pyyaml==6.0.2
120
- # via pydantic-settings
121
- requests==2.32.3
122
- # via downloadkit
123
- # via drissionpage
124
- # via hssp
125
- # via requests-file
126
- # via tldextract
127
- requests-file==2.1.0
128
- # via tldextract
129
- six==1.16.0
130
- # via apscheduler
131
- # via furl
132
- # via orderedmultidict
133
- sniffio==1.3.1
134
- # via anyio
135
- # via httpx
136
- tenacity==9.0.0
137
- # via hssp
138
- tldextract==5.1.3
139
- # via drissionpage
140
- tomli==2.1.0
141
- # via pydantic-settings
142
- typing-extensions==4.12.2
143
- # via curl-cffi
144
- # via pydantic
145
- # via pydantic-core
146
- tzlocal==5.2
147
- # via apscheduler
148
- urllib3==2.2.3
149
- # via requests
150
- uvloop==0.21.0
151
- # via hssp
152
- w3lib==2.2.1
153
- # via parsel
154
- websocket-client==1.8.0
155
- # via drissionpage
156
- yarl==1.17.1
157
- # via aiohttp
File without changes
@@ -1,14 +0,0 @@
1
- import asyncio
2
-
3
- from hs_m3u8 import M3u8Downloader
4
-
5
-
6
- async def main():
7
- url = "https://surrit.com/6d3bb2b2-d707-4b79-adf0-89542cb1383c/playlist.m3u8"
8
- name = "SDAB-129"
9
- dl = M3u8Downloader(m3u8_url=url, save_path=f"../../downloads/{name}", max_workers=64)
10
- await dl.run(del_hls=False, merge=True)
11
-
12
-
13
- if __name__ == "__main__":
14
- asyncio.run(main())
@@ -1,33 +0,0 @@
1
- import asyncio
2
-
3
- from hs_m3u8 import M3u8Downloader
4
-
5
-
6
- def get_m3u8(resp_text: str):
7
- """
8
- 获取m3u8真实文本
9
- Args:
10
- resp_text: m3u8_url 获取到的响应文本
11
-
12
- Returns:
13
- 返回真正的m3u8文本
14
-
15
- """
16
- return resp_text
17
-
18
-
19
- async def main():
20
- url = "https://surrit.com/6d3bb2b2-d707-4b79-adf0-89542cb1383c/playlist.m3u8"
21
- name = "SDAB-129"
22
- headers = {
23
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
24
- "(KHTML, like Gecko) Chrome/129.0.0.0 Safari/537.36"
25
- }
26
- dl = M3u8Downloader(
27
- m3u8_url=url, save_path=f"../../downloads/{name}", headers=headers, max_workers=64, get_m3u8_func=get_m3u8
28
- )
29
- await dl.run(del_hls=False, merge=True)
30
-
31
-
32
- if __name__ == "__main__":
33
- asyncio.run(main())
@@ -1,14 +0,0 @@
1
- import asyncio
2
-
3
- from hs_m3u8 import M3u8Downloader
4
-
5
-
6
- async def main():
7
- url = "https://surrit.com/85f671be-4ebc-4cad-961e-a8d339483cc6/playlist.m3u8"
8
- name = "CUS-2413"
9
- dl = M3u8Downloader(m3u8_url=url, save_path=f"../../downloads/{name}", max_workers=64)
10
- await dl.run(del_hls=False, merge=True)
11
-
12
-
13
- if __name__ == "__main__":
14
- asyncio.run(main())
@@ -1,43 +0,0 @@
1
- # pip install hs-m3u8==0.1.4
2
-
3
- import asyncio
4
-
5
- from hs_m3u8 import M3u8Downloader, M3u8Key
6
-
7
-
8
- async def main():
9
- url = "https://r1-ndr-private.ykt.cbern.com.cn/edu_product/esp/assets/68b6bed7-d093-7c8c-9133-95cf8205d21d.t/zh-CN/1712805650284/transcode/videos/68b6bed7-d093-7c8c-9133-95cf8205d21d-1920x1080-true-47fe81c5c8d91daf25e9fffd7082f934-eed6db5a85074b6dbbe5fa71f1243b26.m3u8"
10
- name = "ykt"
11
- headers = {
12
- "Accept": "*/*",
13
- "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7",
14
- "Cache-Control": "no-cache",
15
- "Connection": "keep-alive",
16
- "Origin": "https://basic.smartedu.cn",
17
- "Pragma": "no-cache",
18
- "Referer": "https://basic.smartedu.cn/",
19
- "Sec-Fetch-Dest": "empty",
20
- "Sec-Fetch-Mode": "cors",
21
- "Sec-Fetch-Site": "cross-site",
22
- "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) "
23
- "Chrome/126.0.0.0 Safari/537.36",
24
- "X-ND-AUTH": 'MAC id="7F938B205F876FC3C7550081F114A1A4028222C3BFB978FD9B439192D004CB8EEB65E66BB'
25
- 'C63E66FED6DD51F34F99411A6039E623E9A9D05",nonce="1742462574752:Z4IGAAV6"'
26
- ',mac="EUr56dXrCO1YGd3Ub1fj9MyJY9NxQPi7ZI14N/GFwpQ="',
27
- "sec-ch-ua": '"Not/A)Brand";v="8", "Chromium";v="126", "Google Chrome";v="126"',
28
- "sec-ch-ua-mobile": "?0",
29
- "sec-ch-ua-platform": '"Windows"',
30
- }
31
- key = M3u8Key(key=bytes.fromhex("34623235336163353939353834643437"))
32
- dl = M3u8Downloader(
33
- m3u8_url=url,
34
- save_path=f"../../downloads/{name}",
35
- max_workers=64,
36
- headers=headers,
37
- key=key,
38
- )
39
- await dl.run(del_hls=False, merge=True)
40
-
41
-
42
- if __name__ == "__main__":
43
- asyncio.run(main())
@@ -1,14 +0,0 @@
1
- import asyncio
2
-
3
- from hs_m3u8 import M3u8Downloader
4
-
5
-
6
- async def main():
7
- url = "https://v3.dious.cc/20220422/EZWdBGuQ/index.m3u8"
8
- name = "日日是好日"
9
- dl = M3u8Downloader(m3u8_url=url, save_path=f"../../downloads/{name}", max_workers=64)
10
- await dl.run(del_hls=False, merge=True)
11
-
12
-
13
- if __name__ == "__main__":
14
- asyncio.run(main())
@@ -1,14 +0,0 @@
1
- import asyncio
2
-
3
- from hs_m3u8 import M3u8Downloader
4
-
5
-
6
- async def main():
7
- url = "https://v4.qrssv.com/202412/05/CCu6EzN8tR20/video/index.m3u8"
8
- name = "毒液:最后一舞 HD-索尼"
9
- dl = M3u8Downloader(m3u8_url=url, save_path=f"../../downloads/{name}", max_workers=64)
10
- await dl.run(del_hls=False, merge=True)
11
-
12
-
13
- if __name__ == "__main__":
14
- asyncio.run(main())
@@ -1,14 +0,0 @@
1
- import asyncio
2
-
3
- from hs_m3u8 import M3u8Downloader
4
-
5
-
6
- async def main():
7
- url = "http://1251107588.vod2.myqcloud.com/40f34e4dvodtransgzp1251107588/722ec94f387702303749471522/voddrm.token.eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9~eyJ0eXBlIjoiRHJtVG9rZW4iLCJhcHBJZCI6MTI1MTEwNzU4OCwiZmlsZUlkIjoiMzg3NzAyMzAzNzQ5NDcxNTIyIiwiY3VycmVudFRpbWVTdGFtcCI6MCwiZXhwaXJlVGltZVN0YW1wIjoyMTQ3NDgzNjQ3LCJyYW5kb20iOjAsIm92ZXJsYXlLZXkiOiIiLCJvdmVybGF5SXYiOiIiLCJjaXBoZXJlZE92ZXJsYXlLZXkiOiI0NTQ2NzliYjY5Zjg1N2M3NGZjY2YxOGM1ZTk4ZjQyMjk4YTMxMzhkYjgyMTNkZThmYjA4ZDM2MzY0MjQ0NjQ3OWFhYmZlYjk0MmYzZTE1MWNkZjM2OGQ5NGEwMzhlNjI4YjlmMTM1OGM4ODkwMjlkMzcwMjZiYzQ3MTY0MGViMWI5ODExYTg5MWU1ZmYxODk3MjliNGIyOWU4ZWExZjNkZWNkZWJmYTVjZmY0N2U4YzBjYjU4OGE2MWUxZmMzNzNmZWQxYWZhOGU5MmJmMGQ4YjFmNjIwMjM4YWJjMzYyM2FlYWVjYjlkNDI3MmI2ZmMzMmRmNjBlN2VmYjc1NjkzIiwiY2lwaGVyZWRPdmVybGF5SXYiOiIwMTYxOTE2YmI5NWRjOWJlZDgyNmI5NmE0MTY1OThkM2IyZmYyYzJmM2JhZDVmNzg2NDEyMWFlYjJiMWVmNjQwNzg0NmNmZmI5YjkyN2E1YzFlMTFhMGE0MDNlMzg5MWE4Y2VkMTJhMTYyNWRlZDFlYWYwMmJkNTI2ZGFjZWE2OGRjNjc1NTE5ZmE3MjBhYTcxNGU3MGE2MjdhM2IwM2I0YzFjMWJjNjJmODYxMDAyN2M3ZjhlYzc4MTg1MDhlNDc0YTJiZmM3NTZjOTVmMWY3NGMxYWQ5NTkyNjBhZTM0NDczNDA4OWZlMGY5YWIzZmYwYzQxZTFlNGNjYWE4YjcxIiwia2V5SWQiOjEsInN0cmljdE1vZGUiOjAsInBlcnNpc3RlbnQiOiIiLCJyZW50YWxEdXJhdGlvbiI6MCwiZm9yY2VMMVRyYWNrVHlwZXMiOm51bGx9~OvCFF2x41XbwQK_C1fUE6Orr77BeCttlt6-H5Uj8izg.video_1407500_1.m3u8?encdomain=cmv1&sign=b574e853145eeb93fcec3b26d28b9665&t=7fffffff"
8
- name = "siyuanren"
9
- dl = M3u8Downloader(m3u8_url=url, save_path=f"../../downloads/{name}", max_workers=64)
10
- await dl.run(del_hls=False, merge=True)
11
-
12
-
13
- if __name__ == "__main__":
14
- asyncio.run(main())
@@ -1,16 +0,0 @@
1
- import asyncio
2
-
3
- from hs_m3u8 import M3u8Downloader
4
-
5
-
6
- async def main():
7
- url = (
8
- "https://video.twimg.com/ext_tw_video/1879556885663342592/pu/pl/Vcvv0UK9lOhezJt1.m3u8?variant_version=1&tag=12"
9
- )
10
- name = "x"
11
- dl = M3u8Downloader(m3u8_url=url, save_path=f"../../downloads/{name}", max_workers=64)
12
- await dl.run(del_hls=False, merge=True)
13
-
14
-
15
- if __name__ == "__main__":
16
- asyncio.run(main())
File without changes
File without changes
File without changes