1
mirror of https://github.com/nilaoda/N_m3u8DL-CLI synced 2025-09-05 23:29:33 +02:00

Compare commits

...

283 Commits

Author SHA1 Message Date
nilaoda
985f6e57c3 Fix #785 2023-06-03 17:30:51 +08:00
nilaoda
d9eea2e80f 修正Part分割 2023-03-25 23:17:47 +08:00
nilaoda
0cc4a87a4c Update FUNDING.yml 2022-11-17 23:10:19 +08:00
nilaoda
66d0864d72 update discord link 2022-10-10 13:44:53 +08:00
nilaoda
965ac2b513 update discord link 2022-10-10 13:43:58 +08:00
nilaoda
a95334ec57 fix #718 2022-09-05 21:55:09 +08:00
nilaoda
e05a21a034 Merge pull request #714 from xifangczy/master
修复 录制间隔负数导致错误
2022-08-19 20:12:37 +08:00
O2bmm
13cd5d0870 修复 录制间隔负数导致错误 2022-08-19 19:38:03 +08:00
nilaoda
8d9ad7af41 Update README.md 2022-07-20 21:44:36 +08:00
nilaoda
0a11816acf fix #708 2022-07-20 21:34:18 +08:00
nilaoda
81ba4ff7d3 Create FUNDING.yml 2022-07-14 20:08:45 +08:00
nilaoda
f5a9ed08a1 update version 2022-07-12 00:21:39 +08:00
nilaoda
6b8bfde19f update docs 2022-07-12 00:10:53 +08:00
nilaoda
ff738f2849 Merge pull request #698 from xifangczy/master
fix: 修正m3u8dl协议 转义符问题
2022-07-11 23:44:31 +08:00
O2bmm
3d35c24a2e fix: 修正m3u8dl协议 转义符问题 2022-07-11 01:32:30 +08:00
nilaoda
41d7151e7e Update HLSLiveDownloader.cs 2022-06-22 11:43:36 +08:00
nilaoda
94246ef163 支持ChaCha20解密 2022-06-20 23:18:27 +08:00
nilaoda
9c118631cf 优化对#EXT-X-BYTERANGE的处理 2022-06-05 02:15:24 +08:00
nilaoda
2ee9ab234f fix #665 #661 2022-05-26 20:18:05 +08:00
nilaoda
606f2184df 修正对于m3u8dl://的描述 2022-05-26 01:26:18 +08:00
nilaoda
7dd2b6cee2 update doc 2022-05-24 15:24:22 +08:00
nilaoda
f744aa990e 3.0.0 2022-05-24 14:41:44 +08:00
nilaoda
97c9f444b8 Update HLSLiveDownloader.cs 2022-05-24 14:39:33 +08:00
nilaoda
8aac37bbe2 去除无效处理 2022-05-24 14:11:47 +08:00
nilaoda
b7e19ec699 elearning cdeledu 2022-05-19 21:10:35 +08:00
nilaoda
7e7c5c6ba9 kkbox.com.tw 2022-05-10 19:55:44 +08:00
nilaoda
50722079ba 处理BMP HEADER 2022-05-08 20:15:00 +08:00
nilaoda
d529ece032 读取在MPD开头定义的<BaseURL>,并替换本身的URL 2022-05-03 22:47:26 +08:00
nilaoda
9ed8b359a1 fix kakao.com 2022-04-22 23:49:40 +08:00
nilaoda
a7591e3978 Merge pull request #640 from abevol/add-uri-support
添加对m3u8dl链接协议的支持
2022-04-13 22:44:19 +08:00
abevol
094a89bc79 添加对m3u8dl链接协议的支持 2022-04-13 20:03:27 +08:00
nilaoda
9e7b603d3b Merge pull request #623 from bxb100/master
fix: GitHub action can't use windowWidth
2022-03-14 11:02:23 +08:00
John Bi
3801090928 fix: github action can't using windowWidth 2022-03-14 01:23:41 +08:00
nilaoda
42c1d628d4 ... 2022-03-10 22:56:37 +08:00
nilaoda
ecefecd827 fix #619 2022-03-10 22:12:23 +08:00
nilaoda
4661818c1f better init info 2021-12-13 17:45:35 +08:00
nilaoda
fa61cd136d update help text 2021-12-13 17:44:58 +08:00
nilaoda
472fb0cf02 Merge pull request #571 from Mtcno/master
添加socks5代理,引用HttpToSocks5Proxy
2021-12-13 17:36:19 +08:00
nilaoda
28e39a94ac Delete FodyWeavers.xsd 2021-12-13 17:35:43 +08:00
nilaoda
a42ade64f3 Delete FodyWeavers.xml 2021-12-13 17:35:19 +08:00
Mtcno
539f773e37 添加sock5代理,引用HttpToSocks5Proxy 2021-12-13 00:50:14 +08:00
nilaoda
d6f27cf90f update docs 2021-12-07 22:31:46 +08:00
nilaoda
8912ee5e4b 优化杜比视界判断 2021-12-07 22:28:27 +08:00
nilaoda
409437b2c7 WriteInit 2021-11-29 01:29:54 +08:00
nilaoda
350d3b508d Update Program.cs 2021-11-26 14:32:26 +08:00
nilaoda
1e3f06eaae del useless files 2021-11-26 12:26:47 +08:00
nilaoda
2d4bc42d55 handle empty cmd 2021-11-26 12:23:19 +08:00
nilaoda
68e06d3fa7 Change to CommandLineParser 2021-11-26 12:14:25 +08:00
nilaoda
6c3340e94e 2.9.9 2021-11-23 15:22:09 +08:00
nilaoda
051faa9f2b 修复重试失效问题 2021-11-23 14:37:50 +08:00
nilaoda
115f9c9424 update image 2021-11-20 10:52:01 +08:00
nilaoda
faf67cd527 2.9.8 2021-11-20 10:14:31 +08:00
nilaoda
38d1a1a2dc 修正init url缺失baseurl问题 2021-11-12 23:28:35 +08:00
nilaoda
12eb68d592 修复日志冲突问题 2021-10-19 11:14:41 +08:00
nilaoda
0804e295e5 修复流选择的显示bug 2021-10-19 10:53:03 +08:00
nilaoda
847c4683cb update wetv js 2021-10-17 00:51:46 +08:00
nilaoda
8c72947860 package exe only 2021-10-17 00:24:34 +08:00
nilaoda
f0b240a6ee 优化AppleTV处理 2021-09-05 19:21:08 +08:00
nilaoda
793cf53042 解决同一个period且同id导致被重复添加分片 2021-09-05 18:17:05 +08:00
nilaoda
612fc29197 修复padding负值问题 2021-09-02 22:41:16 +08:00
nilaoda
307e2389de Update README.md 2021-09-02 10:46:11 +08:00
nilaoda
1c932abdc3 Update AssemblyInfo.cs 2021-08-23 11:38:19 +08:00
nilaoda
314f0065c7 fix node select bug and type show bug #496 2021-08-23 11:35:14 +08:00
nilaoda
59060bb74d Merge pull request #495 from ncnnnnn/patch-2
Update README.md
2021-08-21 22:30:13 +08:00
ncnnnnn
cab882c3a3 Update README.md 2021-08-21 20:35:02 +08:00
nilaoda
9955532ce5 强校验MAP下载成功 2021-08-15 20:18:06 +08:00
nilaoda
7e127be8c2 初步修改显示输出样式 2021-08-15 15:32:01 +08:00
nilaoda
b46571a57f Merge pull request #470 from CW-B-W/master
Fix typos in README_ENG.md
2021-07-18 02:28:52 +08:00
Chiao-Wei Wang
da5861d907 Update README_ENG.md 2021-07-18 01:57:16 +08:00
nilaoda
92bc91a1fb drm-json to m3u8 2021-07-04 00:40:05 +08:00
nilaoda
439f50103e 1.支持iq-drm格式json自动转换 2.优化master选择最高清晰度逻辑 2021-07-04 00:38:17 +08:00
nilaoda
8a95e31b2f update docs 2021-07-03 22:35:00 +08:00
nilaoda
115b8a156a Update packages.config 2021-06-27 23:06:33 +08:00
nilaoda
120bcaebb5 Update N_m3u8DL-CLI.csproj 2021-06-27 23:01:22 +08:00
nilaoda
455d56707c Update N_m3u8DL-CLI.csproj 2021-06-27 22:55:05 +08:00
nilaoda
048adcf118 支持解压brotli 2021-06-27 22:41:12 +08:00
nilaoda
fe5aa27b1c 修正判断png图片时可能出现的数组越界bug 2021-06-27 22:39:16 +08:00
nilaoda
039aa489b1 优化范围选择结尾识别 2021-06-27 22:38:32 +08:00
nilaoda
14e80f0b06 优化输出并增加ETA显示 2021-03-27 14:04:31 +08:00
nilaoda
2256fff549 日志文件初始化时,精确到毫秒防止重复 2021-03-27 14:03:54 +08:00
nilaoda
84cfd4e138 Update README_ENG.md 2021-03-26 09:35:28 +08:00
nilaoda
e70c229135 Update README.md 2021-03-26 09:30:30 +08:00
nilaoda
8b520d0c19 修正AppleTV逻辑 2021-03-25 23:11:18 +08:00
nilaoda
71d69de51a Update changelog.txt 2021-03-25 22:09:44 +08:00
nilaoda
bc89ead00d 为下载分片增加了自动重试机制(3次) 2021-03-25 22:09:26 +08:00
nilaoda
ae79d6eb3a 优化下载监控 2021-03-25 22:07:04 +08:00
nilaoda
96bd8af883 适配AppleTv资源 2021-03-22 23:18:22 +08:00
nilaoda
89b1e30e0f 修复enableAudioOnly且下载MPD文件时留下冗余(Audio)文件夹的情况 2021-03-22 23:17:09 +08:00
nilaoda
7a741359ab Update README.md 2021-03-04 13:17:07 +08:00
nilaoda
564b6ad291 Update README_ENG.md 2021-03-04 13:12:06 +08:00
nilaoda
a0fc9404f7 Update README.md 2021-03-04 13:11:06 +08:00
nilaoda
5267be1699 Update changelog.txt 2021-03-04 12:26:20 +08:00
nilaoda
20bfda39e7 bug fix
- 修复M3U8选择音轨/字幕不生效问题
  - 外挂音轨时enableAudioOnly可仅下载音频
2021-03-04 12:23:51 +08:00
nilaoda
ba4c0eeda7 Update Program.cs 2021-02-22 11:58:52 +08:00
nilaoda
5d72e24002 update docs 2021-02-22 11:16:45 +08:00
nilaoda
a87c051d23 update readme 2021-02-22 11:00:32 +08:00
nilaoda
44e1b68d6b update help info 2021-02-22 10:57:53 +08:00
nilaoda
e65dfa52cd Merge pull request #375 from evanlabs/master
添加用户网络代理支持,使用--proxyAddress指定代理地址。
2021-02-22 10:49:42 +08:00
EvanYeung
965c173899 添加用户网络代理支持,使用--proxyAddress指定代理地址。 2021-02-22 09:50:18 +08:00
nilaoda
880af02cc2 打印MPD解析日志 2021-02-21 15:13:44 +08:00
nilaoda
2742de43c4 增加键值 2021-02-21 15:13:07 +08:00
nilaoda
9d8cb57390 MPD检测最后一个分片是否有效 2021-02-21 13:24:15 +08:00
nilaoda
9e2a192dab Update changelog.txt 2021-02-21 13:23:57 +08:00
nilaoda
33cf9e2256 Update Parser.cs 2021-02-11 17:06:19 +08:00
nilaoda
2959cbbb5c Update changelog.txt 2021-02-11 17:06:08 +08:00
nilaoda
c2eb8a6adc 修正MPD拼接BaseUrl逻辑 2021-02-10 22:32:06 +08:00
nilaoda
e1b591b81c Update N_m3u8DL-CLI.csproj 2021-02-03 11:54:02 +08:00
nilaoda
334b1939b5 修复气球云;优化独播库 2021-02-03 00:38:57 +08:00
nilaoda
7e916b65fd Update changelog.txt 2021-02-01 22:57:37 +08:00
nilaoda
4ead563fa2 修正自定义KEY切存在IV时的隐患 2021-02-01 22:57:27 +08:00
nilaoda
1b387a06e5 update docs 2021-02-01 22:52:07 +08:00
nilaoda
6e7b4ac7ea ddyun识别90mm 2021-02-01 22:42:56 +08:00
nilaoda
e98c5205d1 优化跳过png的算法 2021-02-01 14:18:03 +08:00
nilaoda
d7890dd124 优化跳过png的算法 2021-02-01 14:11:28 +08:00
nilaoda
82f2111522 update 2021-01-24 16:26:32 +08:00
nilaoda
4c3207586f Update MPDParser.cs 2021-01-24 16:24:03 +08:00
nilaoda
69b411e37c fix sub merge bug 2021-01-24 16:22:13 +08:00
nilaoda
1e8525041f Download from DSNP 2021-01-24 16:21:32 +08:00
nilaoda
65ae72d4a4 Update MPDParser.cs 2021-01-18 20:36:43 +08:00
nilaoda
4a4bfae5ab 优化MPD下载行为 2021-01-18 02:00:19 +08:00
nilaoda
d586dddfcd Update changelog.txt 2021-01-18 01:59:31 +08:00
nilaoda
fca6b3ff6c Update changelog.txt 2020-12-29 23:19:39 +08:00
nilaoda
5d75626a36 Update Global.cs 2020-12-29 23:18:16 +08:00
nilaoda
a94271c244 mpd - xigua 2020-12-20 18:53:40 +08:00
nilaoda
c51118dce7 解密huke88 2020-12-20 18:53:02 +08:00
nilaoda
81b2e87bf7 处理同一ID分散在不同Period的情况 2020-12-12 02:07:41 +08:00
nilaoda
71a9878aaa Update changelog.txt 2020-12-06 21:32:48 +08:00
nilaoda
769fe4e926 Update Global.cs 2020-12-06 21:32:38 +08:00
nilaoda
1f57ba7c09 Update Parser.cs 2020-12-06 21:32:29 +08:00
nilaoda
71282bda30 Update N_m3u8DL-CLI.csproj 2020-12-02 20:35:44 +08:00
nilaoda
41ee8aebdf update project 2020-12-02 20:31:44 +08:00
nilaoda
a4537bc093 del xml 2020-12-02 20:23:50 +08:00
nilaoda
b8a60b3917 Update packages.config 2020-12-02 20:23:36 +08:00
nilaoda
8091dd290f Update N_m3u8DL-CLI.csproj 2020-12-02 20:15:29 +08:00
nilaoda
d48e84e611 Update FodyWeavers.xml 2020-12-02 20:10:29 +08:00
nilaoda
9f5423a437 Costura.Fody 2020-12-02 19:56:20 +08:00
nilaoda
ce7e38770a Update N_m3u8DL-CLI.csproj 2020-12-02 19:51:29 +08:00
nilaoda
8fdb2e918e Update packages.config 2020-12-02 19:49:10 +08:00
nilaoda
d4b7d240c1 修正多语言识别问题 2020-12-02 11:56:46 +08:00
nilaoda
484d2941ed Update Global.cs 2020-12-02 11:56:17 +08:00
nilaoda
a0f2b66575 Update changelog.txt 2020-12-02 11:56:04 +08:00
nilaoda
65cc0681e2 Update changelog.txt 2020-11-26 21:02:04 +08:00
nilaoda
7d980ec9a2 Update Global.cs 2020-11-26 21:01:57 +08:00
nilaoda
ec5892c05a 修复可能存在的溢出问题 2020-11-26 21:01:48 +08:00
nilaoda
9aed50fbf9 优化MPD识别 2020-11-26 21:01:03 +08:00
nilaoda
d657b455cd BUG FIX 2020-11-25 21:16:41 +08:00
nilaoda
cda6575605 BUG FIX 2020-11-25 21:16:18 +08:00
nilaoda
0d6377d41b Update changelog.txt 2020-11-25 17:34:53 +08:00
nilaoda
9c76bdcbce 支持选择音轨 2020-11-25 17:34:12 +08:00
nilaoda
83915ff606 Update Global.cs 2020-11-25 14:12:46 +08:00
nilaoda
9cd4746f33 Update changelog.txt 2020-11-25 14:11:31 +08:00
nilaoda
33a5b917ac 修正MPD判断最高清晰度的逻辑 2020-11-25 14:08:40 +08:00
nilaoda
f69978bd82 修改芒果TV请求头 2020-11-23 21:53:41 +08:00
nilaoda
d9fd526886 Update changelog.txt 2020-11-23 21:53:26 +08:00
nilaoda
1cc8ecfaaf Update Global.cs 2020-11-23 21:30:12 +08:00
nilaoda
2bc2dde2ad 修改默认UA 2020-11-23 21:29:48 +08:00
nilaoda
c3ddcf9e0e Update Program.cs 2020-11-23 21:29:31 +08:00
nilaoda
ba5d20dd02 Update Parser.cs 2020-11-23 21:29:03 +08:00
nilaoda
16f705fe66 Update Global.cs 2020-11-22 23:13:59 +08:00
nilaoda
d141cabc4a Update changelog.txt 2020-11-22 23:08:51 +08:00
nilaoda
adcf884a93 新的任务监控逻辑 2020-11-22 23:08:33 +08:00
nilaoda
9d903a025f Update DownloadManager.cs 2020-11-22 22:36:21 +08:00
nilaoda
0bd23ab641 更新版本号 2020-11-22 18:48:54 +08:00
nilaoda
a38f27ccd7 手动处理重定向
解决HTTPS协议自动重定向后,Referer丢失问题
2020-11-22 18:29:40 +08:00
nilaoda
3acec5efd3 Update Global.cs 2020-11-22 15:40:47 +08:00
nilaoda
90874e4bfe Update Parser.cs 2020-11-22 14:30:41 +08:00
nilaoda
b94768e3e8 修复自定义MPD的BaseURL 2020-11-22 00:40:17 +08:00
nilaoda
311f3b882e 更新版本号 2020-11-21 19:36:04 +08:00
nilaoda
4b4f537984 BUG FIX 2020-11-21 19:34:47 +08:00
nilaoda
8032d50b42 传递MPD_URL时处理302 2020-11-21 19:34:27 +08:00
nilaoda
f615764e55 Update build_latest.yml 2020-11-21 13:48:20 +08:00
nilaoda
ccaa200ef8 Update build_latest.yml 2020-11-21 13:45:56 +08:00
nilaoda
6058d878eb Update N_m3u8DL-CLI.csproj 2020-11-21 13:40:15 +08:00
nilaoda
c712c6dee0 Create changelog.txt 2020-11-21 13:30:56 +08:00
nilaoda
bb24bb998f Update Global.cs 2020-11-21 13:11:15 +08:00
nilaoda
e9d951efa5 检测GIF HEADER 2020-11-21 12:25:01 +08:00
nilaoda
6f88a805ef 修复PNG检测逻辑
多写了一个分号……
2020-11-21 12:08:28 +08:00
nilaoda
6aa6d63a8d Convert MPD to M3U8
通过将MPD转换为m3u8进行下载
2020-11-20 23:34:35 +08:00
nilaoda
147246caba Update Parser.cs 2020-11-18 16:05:18 +08:00
nilaoda
35c1ee4777 Update Parser.cs 2020-11-18 15:52:36 +08:00
nilaoda
8b32081b85 识别m3u8文件中的EXT-X-PROGRAM-DATE-TIME 2020-11-18 15:33:39 +08:00
nilaoda
c00de328d1 修改默认UA 修改音轨判断逻辑
修改UA为Mozilla/5.0 (Linux; U; Android 7.0; zh-cn; 15 Plus Build/NRD90M) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.126 MQQBrowser/9.4 Mobile Safari/537.36

修改AAC滤镜的使用逻辑

当m3u8文本大小大于50MB时应当放弃
2020-11-18 15:03:21 +08:00
nilaoda
d5193c1645 fix bug 2020-11-06 22:11:21 +08:00
nilaoda
c06fbf5820 update docs 2020-11-03 11:38:24 +08:00
nilaoda
e700edba56 Update Program.cs
修正处理文件名过长的逻辑
2020-10-14 22:18:56 +08:00
nilaoda
aad948da7c v2.7.5 2020-10-14 22:01:03 +08:00
nilaoda
14f7b20176 Merge pull request #246 from Suwmlee/master
Fix build error
2020-09-22 10:19:45 +08:00
Mathhew
a66a9a4096 Fix build error 2020-09-22 09:49:58 +08:00
nilaoda
c862f23a9c v2.7.4
支持ddyun m3u8解密
2020-09-20 13:41:49 +08:00
nilaoda
1a722e80de Delete DecryptNfmovies.cs 2020-09-20 13:41:02 +08:00
nilaoda
eff43e8ac3 Merge pull request #240 from Suwmlee/master
Add github action
2020-09-17 18:58:30 +08:00
Mathhew
7648f8f8dc Add github action 2020-09-17 10:05:35 +08:00
nilaoda
1edc1a43fe v2.7.3 2020-09-14 21:53:51 +08:00
nilaoda
01e7735018 v2.7.2 2020-08-09 20:59:38 +08:00
nilaoda
a0c41d6116 v2.7.2 2020-08-09 20:34:32 +08:00
nilaoda
c3c25774de v2.7.2 2020-08-09 20:33:15 +08:00
nilaoda
ba40641a21 v2.7.1 2020-07-19 09:24:24 +08:00
nilaoda
5d76418780 v2.7.0
优酷杜比视界下载逻辑优化;支持IMOCO m3u8/key解密;从当前路径和exe路径同时寻找ffmpeg;支持多语言本地化(简繁英)
2020-07-18 17:20:28 +08:00
nilaoda
fd48b766b5 v2.6.3 2020-04-17 22:54:57 +08:00
nilaoda
0f25cc0ae8 v2.6.2 2020-04-17 20:17:56 +08:00
nilaoda
1c6bd688e3 Merge branch 'master' of https://github.com/nilaoda/N_m3u8DL-CLI 2020-04-17 19:25:37 +08:00
nilaoda
480857cc3b v2.6.1 2020-04-17 19:25:32 +08:00
nilaoda
52af9a44a8 Update README.md 2020-03-12 14:39:29 +08:00
nilaoda
84d137b504 Update README.md 2020-03-12 00:50:16 +08:00
nilaoda
a4f1064c81 Update README.md 2020-03-11 21:21:25 +08:00
nilaoda
eac08b12f8 v2.6.0 2020-03-11 18:01:33 +08:00
nilaoda
c81c911888 Update Docs 2020-03-11 17:58:03 +08:00
nilaoda
361e901e5b Update Docs 2020-03-11 17:55:47 +08:00
nilaoda
3567f4c4cc Update README_ENG.md 2020-03-11 17:42:10 +08:00
nilaoda
2f7b0f7304 Update README_ENG.md 2020-03-11 17:41:56 +08:00
nilaoda
000d0db4ae Update README.md 2020-03-11 17:41:42 +08:00
nilaoda
d551ad52c1 Update README.md 2020-03-11 17:01:56 +08:00
nilaoda
c064c83c21 Update README.md 2020-03-11 15:14:06 +08:00
nilaoda
f6ed0f9e4d Update youku.html 2020-03-11 11:26:59 +08:00
nilaoda
f65fee94ca Update Docs 2020-03-08 11:01:13 +08:00
nilaoda
ce64a92b0d Update README.md 2020-03-06 01:03:30 +08:00
nilaoda
42790ce540 Update README.md 2020-03-06 01:00:50 +08:00
nilaoda
83d8ca1c8c Update README.md 2020-03-06 00:58:20 +08:00
nilaoda
4b5a64eb98 v2.5.7 2020-03-05 20:05:15 +08:00
nilaoda
2b5af09c3b Update HLSLiveDownloader.cs 2020-03-05 14:46:03 +08:00
nilaoda
6368adc2ab Update HLSLiveDownloader.cs 2020-03-04 21:09:41 +08:00
nilaoda
fcd7840091 只认第一个"#EXT-X-MAP", 其余的全部丢弃 2020-03-04 02:13:02 +08:00
nilaoda
d77cb62dff Update HLSLiveDownloader.cs 2020-03-03 19:03:42 +08:00
nilaoda
34394c6a2b 修复输出太长只在最后一行显示的问题 2020-03-03 19:03:24 +08:00
nilaoda
091cba8555 Merge pull request #101 from youxia2016/master
Update Downloader.cs
2020-03-02 22:09:15 +08:00
游侠
b02b6b7168 Update Downloader.cs
跳过过期片段
2020-03-02 21:56:01 +08:00
nilaoda
b7408b0599 v2.5.6 2020-03-02 20:20:38 +08:00
nilaoda
b83cb35170 Merge pull request #100 from youxia2016/master
自动设置请求分段文件时间间隔
修复网络断线一直Downloading及cpu 100%
2020-03-02 20:19:20 +08:00
游侠
ed0a7b71a7 自动设置请求分段文件时间间隔
时间间隔一般为9-18秒,同一直播平台也不相同,自适应间隔,可以防止多次请求
2020-03-02 19:39:44 +08:00
游侠
50eae19bf3 修复网络掉线cpu 100%以及下载超时时间
网络如果突然断掉cpu会100% 风扇狂转
2020-03-02 18:35:28 +08:00
nilaoda
cba8f3ea52 v2.5.5 2020-03-02 17:14:15 +08:00
nilaoda
7fd93e1232 Merge pull request #98 from youxia2016/master
请求失败重试
2020-03-02 16:48:32 +08:00
游侠
74a7e3c3ec 加入savename参数可读取N_m3u8DL-CLI.args.txt
输入网址及保存文件名 更加人性化
2020-03-02 16:48:28 +08:00
nilaoda
849d712e11 Update README.md 2020-03-02 16:42:12 +08:00
游侠
7544f3a02c 添加Http重试次数
进行重试 可更稳定
2020-03-02 16:39:28 +08:00
nilaoda
0120736c53 Update README_ENG.md 2020-03-01 12:17:27 +08:00
nilaoda
e4bde4926c Update README.md 2020-03-01 12:17:08 +08:00
nilaoda
d42cd6a60d v2.5.4 2020-02-28 18:27:55 +08:00
nilaoda
175f13adc9 v2.5.3 2020-02-27 20:36:25 +08:00
nilaoda
72f1c043b1 腾讯视频DRM内容m3u8获取JS 2020-02-27 14:29:55 +08:00
nilaoda
a2e2070f5d update docs 2020-02-25 22:14:55 +08:00
nilaoda
6c96deb366 Update Downloader.cs 2020-02-25 01:10:38 +08:00
nilaoda
2bd900ee5d v2.5.2 2020-02-25 01:01:15 +08:00
nilaoda
1261810510 Update Downloader.cs 2020-02-24 17:05:01 +08:00
nilaoda
26823dbd7e Update docs 2020-02-24 16:29:18 +08:00
nilaoda
698699d9fc Update README.md 2020-02-24 16:25:13 +08:00
nilaoda
ebed7fa1e3 优化直播录制 2020-02-24 16:23:40 +08:00
nilaoda
73a8348155 v2.5.0 2020-02-23 21:07:36 +08:00
nilaoda
5ace0b3a4f 增加优酷教程 2020-02-23 20:23:23 +08:00
nilaoda
5abe889da0 Update README_ENG.md 2020-02-23 20:22:18 +08:00
nilaoda
f1070fd1b4 Update README.md 2020-02-23 20:13:23 +08:00
nilaoda
4af82cc7f9 v2.4.9 2020-02-18 15:20:04 +08:00
nilaoda
809380b7ab 修正VIKI下载JS 2020-02-11 23:59:37 +08:00
nilaoda
ab57420507 增加基于Firefox的网易云课堂KEY获取教程 2020-02-02 01:23:52 +08:00
nilaoda
80230f12fe 增加网易云课堂KEY获取教程 2020-02-02 00:43:55 +08:00
nilaoda
a6c7c0fd8c ?__gda__行为优化 2020-01-31 21:39:05 +08:00
nilaoda
bd6df6b58c JS增加naver tv 2020-01-31 21:38:27 +08:00
nilaoda
e0a9071d62 修改超链接错误 2020-01-30 19:16:11 +08:00
nilaoda
5c9bcf72d2 更新OnDemandChina获取JS 2020-01-29 23:48:15 +08:00
nilaoda
7cf2c12d0c 增加OnDemandChina获取JS 2020-01-29 23:41:03 +08:00
nilaoda
1b35fe2d2c Update DownloadManager.cs 2020-01-29 22:45:26 +08:00
nilaoda
ed3aae1cb9 v2.4.7 2020-01-29 22:28:07 +08:00
nilaoda
01c2ecbeb5 增加爱奇艺字幕JS 2020-01-28 23:48:35 +08:00
nilaoda
9993ec8177 添加获取爱奇艺高帧率视频JS 2020-01-09 23:01:20 +08:00
nilaoda
464300c860 Update N_m3u8DL-CLI.sln 2020-01-07 21:22:43 +08:00
nilaoda
45fa58a46f Update README.md 2020-01-06 09:44:09 +08:00
nilaoda
f93ddc7107 Update README.md 2019-12-30 16:38:08 +08:00
nilaoda
05f450fa6d 永远信任https 2019-12-28 23:45:31 +08:00
nilaoda
580c374d7b 更新腾讯视频代码 2019-12-28 14:17:43 +08:00
nilaoda
b58dc5d8e0 Update README_ENG.md 2019-12-26 23:29:03 +08:00
nilaoda
f50cf7862a Add link 2019-12-23 17:16:28 +08:00
nilaoda
fdad68d483 Create README_ENG.md 2019-12-23 17:04:46 +08:00
nilaoda
d7aaa5323b 修复腾讯视频HDR10下载问题 2019-12-18 23:04:05 +08:00
nilaoda
6c2e13b800 v2.4.4
修复part大于1时读取json混流文件的严重错误;自动去除优酷的广告分片及前情提要
2019-12-18 19:49:58 +08:00
nilaoda
086fc57958 修复解析bug;增加杜比视界识别场景 2019-12-18 09:15:42 +08:00
nilaoda
bc349b8977 文件名特殊字符处理 2019-12-16 22:16:54 +08:00
nilaoda
cc4efed3c6 完善芒果TV请求头的自动添加 2019-11-30 00:43:00 +08:00
nilaoda
cf958e833b fix doc 2019-11-15 23:55:30 +08:00
nilaoda
fb09add0cd update docs 2019-11-15 10:49:07 +08:00
nilaoda
5a3c5baefd 更新JS 2019-11-13 23:35:04 +08:00
nilaoda
839afd8e61 Update N_m3u8DL-CLI.csproj 2019-11-08 20:38:25 +08:00
nilaoda
338c7a25d0 更新文档 2019-10-24 15:40:28 +08:00
nilaoda
f57ce8c2da Update README.md 2019-10-24 15:32:14 +08:00
66 changed files with 6813 additions and 4382 deletions

13
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,13 @@
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: ['https://nilaoda.github.io/N_m3u8DL-CLI/source/images/alipay.png','https://www.buymeacoffee.com/nilaoda']

34
.github/workflows/build_latest.yml vendored Normal file
View File

@@ -0,0 +1,34 @@
name: Build_Latest
on: [push]
jobs:
build:
runs-on: windows-latest
steps:
- uses: actions/checkout@v1
name: Checkout Code
- name: Setup MSBuild Path
uses: warrenbuckley/Setup-MSBuild@v1
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true'
- name: Setup NuGet
uses: NuGet/setup-nuget@v1.0.2
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true'
- name: Restore NuGet Packages
run: nuget restore N_m3u8DL-CLI.sln
- name: Build
run: msbuild N_m3u8DL-CLI.sln /p:Configuration=Release /p:DebugSymbols=false /p:DebugType=None
- name: Upload Artifact
uses: actions/upload-artifact@v1.0.0
with:
name: N_m3u8DL-CLI_latest
path: N_m3u8DL-CLI\bin\Release\N_m3u8DL-CLI.exe

View File

@@ -1,12 +1,10 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27703.2000
# Visual Studio Version 16
VisualStudioVersion = 16.0.29215.179
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "N_m3u8DL-CLI", "N_m3u8DL-CLI\N_m3u8DL-CLI.csproj", "{4FB61439-B738-46AC-B3AF-2BF72150D057}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "GUI-MainWindow", "GUI-MainWindow\GUI-MainWindow.csproj", "{FE91DB43-1F1F-4119-B808-A7F4795BB4D0}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -17,10 +15,6 @@ Global
{4FB61439-B738-46AC-B3AF-2BF72150D057}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4FB61439-B738-46AC-B3AF-2BF72150D057}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4FB61439-B738-46AC-B3AF-2BF72150D057}.Release|Any CPU.Build.0 = Release|Any CPU
{FE91DB43-1F1F-4119-B808-A7F4795BB4D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FE91DB43-1F1F-4119-B808-A7F4795BB4D0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE91DB43-1F1F-4119-B808-A7F4795BB4D0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE91DB43-1F1F-4119-B808-A7F4795BB4D0}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

661
N_m3u8DL-CLI/CSChaCha20.cs Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,77 +0,0 @@
using System.Collections.Generic;
namespace N_m3u8DL_CLI
{
public class CommandLineArgument
{
List<CommandLineArgument> _arguments;
int _index;
string _argumentText;
public CommandLineArgument Next
{
get
{
if (_index < _arguments.Count - 1)
{
return _arguments[_index + 1];
}
return null;
}
}
public CommandLineArgument Previous
{
get
{
if (_index > 0)
{
return _arguments[_index - 1];
}
return null;
}
}
internal CommandLineArgument(List<CommandLineArgument> args, int index, string argument)
{
_arguments = args;
_index = index;
_argumentText = argument;
}
public CommandLineArgument Take()
{
return Next;
}
public IEnumerable<CommandLineArgument> Take(int count)
{
var list = new List<CommandLineArgument>();
var parent = this;
for (int i = 0; i < count; i++)
{
var next = parent.Next;
if (next == null)
break;
list.Add(next);
parent = next;
}
return list;
}
public static implicit operator string(CommandLineArgument argument)
{
return argument._argumentText;
}
public override string ToString()
{
return _argumentText;
}
}
}

View File

@@ -1,39 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace N_m3u8DL_CLI
{
public class CommandLineArgumentParser
{
List<CommandLineArgument> _arguments;
public static CommandLineArgumentParser Parse(string[] args)
{
return new CommandLineArgumentParser(args);
}
public CommandLineArgumentParser(string[] args)
{
_arguments = new List<CommandLineArgument>();
for (int i = 0; i < args.Length; i++)
{
_arguments.Add(new CommandLineArgument(_arguments, i, args[i]));
}
}
public CommandLineArgument Get(string argumentName)
{
return _arguments.FirstOrDefault(p => p == argumentName);
}
public bool Has(string argumentName)
{
return _arguments.Count(p => p == argumentName) > 0;
}
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,83 @@
using NiL.JS.BaseLibrary;
using NiL.JS.Core;
using NiL.JS.Extensions;
using System;
using Array = System.Array;
namespace N_m3u8DL_CLI
{
internal class DecodeCdeledu
{
private static string JS = @"
var _keyStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
var removePaddingChars = function(input) {
var lkey = _keyStr.indexOf(input.charAt(input.length - 1));
if (lkey == 64) {
return input.substring(0, input.length - 1);
}
return input;
}
var base64Decode = function(input, arrayBuffer) {
input = removePaddingChars(input);
input = removePaddingChars(input);
var bytes = parseInt((input.length / 4) * 3, 10);
var uarray;
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;
var j = 0;
if (arrayBuffer) {
uarray = new Uint8Array(arrayBuffer);
} else {
uarray = new Uint8Array(bytes);
}
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, '');
for (i = 0; i < bytes; i += 3) {
enc1 = _keyStr.indexOf(input.charAt(j++));
enc2 = _keyStr.indexOf(input.charAt(j++));
enc3 = _keyStr.indexOf(input.charAt(j++));
enc4 = _keyStr.indexOf(input.charAt(j++));
chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;
uarray[i] = chr1;
if (enc3 != 64)
uarray[i + 1] = chr2;
if (enc4 != 64)
uarray[i + 2] = chr3;
}
return uarray;
}
var uint8ArrayToString = function(uDataArr) {
var arrStr = '';
for (var i = 0; i < uDataArr.length; i++) {
arrStr += String.fromCharCode(uDataArr[i]);
}
return arrStr;
}
var decodeKey = function(dataKeyString) {
var decodeArr = base64Decode(dataKeyString);
var decodeArrString = uint8ArrayToString(decodeArr);
return decodeArrString;
if (decodeArrString.indexOf('|&|') > 0) {
return decodeArrString;
}
return '';
}
";
//https://video.cdeledu.com/js/lib/cdel.hls.min-1.0.js?v=1.3
public static string DecodeKey(string txt)
{
var context = new Context();
context.Eval(JS);
var concatFunction = context.GetVariable("decodeKey").As<Function>();
string key = concatFunction.Call(new Arguments { txt }).ToString();
string realKey = key.Split(new string[] { "|&|" }, StringSplitOptions.None)[1];
return realKey;
}
}
}

View File

@@ -0,0 +1,41 @@
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
namespace N_m3u8DL_CLI
{
class DecodeDdyun
{
public static string DecryptM3u8(byte[] byteArray)
{
string tmp = DecodeNfmovies.DecryptM3u8(byteArray);
if (tmp.StartsWith("duoduo.key"))
{
tmp = Regex.Replace(tmp, @"#EXT-X-BYTERANGE:.*\s", "");
tmp = tmp.Replace("https:", "jump/https:")
.Replace("inews.gtimg.com", "puui.qpic.cn");
}
return tmp;
}
//https://player.ddyunp.com/jQuery.min.js?v1.5
public static string GetVaildM3u8Url(string url)
{
//url: https://hls.ddyunp.com/ddyun/id/1/key/playlist.m3u8
string id = Regex.Match(url, @"\w{20,}").Value;
string tm = Global.GetTimeStamp(false);
string t = ((long.Parse(tm) / 0x186a0) * 0x64).ToString();
string tmp = id + "duoduo" + "1" + t;
MD5 md5 = MD5.Create();
byte[] bs = Encoding.UTF8.GetBytes(tmp);
byte[] hs = md5.ComputeHash(bs);
StringBuilder sb = new StringBuilder();
foreach (byte b in hs)
{
sb.Append(b.ToString("x2"));
}
string key = sb.ToString();
return Regex.Replace(url, @"1/\w{20,}", "1/" + key);
}
}
}

View File

@@ -0,0 +1,53 @@
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
namespace N_m3u8DL_CLI
{
//https://js.huke88.com/assets/revision/js/plugins/tcplayer/tcplayer.v4.1.min.js?v=930
//https://js.huke88.com/assets/revision/js/plugins/tcplayer/libs/hls.min.0.13.2m.js?v=930
class DecodeHuke88Key
{
private static string[] GetOverlayInfo(string url)
{
var enc = new Regex("eyJ\\w{100,}").Match(url).Value;
var json = Encoding.UTF8.GetString(Convert.FromBase64String(enc));
JObject jObject = JObject.Parse(json);
var key = jObject["overlayKey"].ToString();
var iv = jObject["overlayIv"].ToString();
return new string[] { key, iv };
}
public static string DecodeKey(string url, byte[] data)
{
var info = GetOverlayInfo(url);
var overlayKey = info[0];
var overlayIv = info[1];
var l = new List<byte>();
var c = new List<byte>();
for (int h = 0; h < 16; h++)
{
var f = overlayKey.Substring(2 * h, 2);
var g = overlayIv.Substring(2 * h, 2);
l.Add(Convert.ToByte(f, 16));
c.Add(Convert.ToByte(g, 16));
}
var _lastCipherblock = c.ToArray();
var t = new byte[data.Length];
var r = data;
r = Decrypter.AES128Decrypt(data, l.ToArray(), Decrypter.HexStringToBytes("00000000000000000000000000000000"), CipherMode.CBC, PaddingMode.Zeros);
for (var o = 0; o < 16; o++)
t[o] = (byte)(r[o] ^ _lastCipherblock[o]);
var key = Convert.ToBase64String(t);
return key;
}
}
}

203
N_m3u8DL-CLI/DecodeImooc.cs Normal file
View File

@@ -0,0 +1,203 @@
using NiL.JS.BaseLibrary;
using NiL.JS.Core;
using NiL.JS.Extensions;
using System;
using Array = System.Array;
namespace N_m3u8DL_CLI
{
/*
* js代码来自https://www.imooc.com/static/moco/player/3.0.6.3/mocoplayer.js?v=202006122046
*
*/
class DecodeImooc
{
private static string JS = @"
function n(t, e) {
function r(t, e) {
var r = '';
if ('object' == typeof t)
for (var n = 0; n < t.length; n++)
r += String.fromCharCode(t[n]);
t = r || t;
for (var i, o, a = new Uint8Array(t.length), s = e.length, n = 0; n < t.length; n++)
o = n % s,
i = t[n],
i = i.toString().charCodeAt(0),
a[n] = i ^ e.charCodeAt(o);
return a
}
function n(t) {
var e = '';
if ('object' == typeof t)
for (var r = 0; r < t.length; r++)
e += String.fromCharCode(t[r]);
t = e || t;
var n = new Uint8Array(t.length);
for (r = 0; r < t.length; r++)
n[r] = t[r].toString().charCodeAt(0);
var i, o, r = 0;
for (r = 0; r < n.length; r++)
0 != (i = n[r] % 3) && r + i < n.length && (o = n[r + 1],
n[r + 1] = n[r + i],
n[r + i] = o,
r = r + i + 1);
return n
}
function i(t) {
var e = '';
if ('object' == typeof t)
for (var r = 0; r < t.length; r++)
e += String.fromCharCode(t[r]);
t = e || t;
var n = new Uint8Array(t.length);
for (r = 0; r < t.length; r++)
n[r] = t[r].toString().charCodeAt(0);
var r = 0
, i = 0
, o = 0
, a = 0;
for (r = 0; r < n.length; r++)
o = n[r] % 2,
o && r++,
a++;
var s = new Uint8Array(a);
for (r = 0; r < n.length; r++)
o = n[r] % 2,
s[i++] = o ? n[r++] : n[r];
return s
}
function o(t, e) {
var r = 0
, n = 0
, i = 0
, o = 0
, a = '';
if ('object' == typeof t)
for (var r = 0; r < t.length; r++)
a += String.fromCharCode(t[r]);
t = a || t;
var s = new Uint8Array(t.length);
for (r = 0; r < t.length; r++)
s[r] = t[r].toString().charCodeAt(0);
for (r = 0; r < t.length; r++)
if (0 != (o = s[r] % 5) && 1 != o && r + o < s.length && (i = s[r + 1],
n = r + 2,
s[r + 1] = s[r + o],
s[o + r] = i,
(r = r + o + 1) - 2 > n))
for (; n < r - 2; n++)
s[n] = s[n] ^ e.charCodeAt(n % e.length);
for (r = 0; r < t.length; r++)
s[r] = s[r] ^ e.charCodeAt(r % e.length);
return s
}
for (var a = {
data: {
info: t
}
}, s = {
q: r,
h: n,
m: i,
k: o
}, l = a.data.info, u = l.substring(l.length - 4).split(''), c = 0; c < u.length; c++)
u[c] = u[c].toString().charCodeAt(0) % 4;
u.reverse();
for (var d = [], c = 0; c < u.length; c++)
d.push(l.substring(u[c] + 1, u[c] + 2)),
l = l.substring(0, u[c] + 1) + l.substring(u[c] + 2);
a.data.encrypt_table = d,
a.data.key_table = [];
for (var c in a.data.encrypt_table)
'q' != a.data.encrypt_table[c] && 'k' != a.data.encrypt_table[c] || (a.data.key_table.push(l.substring(l.length - 12)),
l = l.substring(0, l.length - 12));
a.data.key_table.reverse(),
a.data.info = l;
var f = new Array(-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,-1,0,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,-1,-1,-1,-1,-1,-1,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,-1,-1,-1,-1,-1);
a.data.info = function(t) {
var e, r, n, i, o, a, s;
for (a = t.length,
o = 0,
s = ''; o < a; ) {
do {
e = f[255 & t.charCodeAt(o++)]
} while (o < a && -1 == e);if (-1 == e)
break;
do {
r = f[255 & t.charCodeAt(o++)]
} while (o < a && -1 == r);if (-1 == r)
break;
s += String.fromCharCode(e << 2 | (48 & r) >> 4);
do {
if (61 == (n = 255 & t.charCodeAt(o++)))
return s;
n = f[n]
} while (o < a && -1 == n);if (-1 == n)
break;
s += String.fromCharCode((15 & r) << 4 | (60 & n) >> 2);
do {
if (61 == (i = 255 & t.charCodeAt(o++)))
return s;
i = f[i]
} while (o < a && -1 == i);if (-1 == i)
break;
s += String.fromCharCode((3 & n) << 6 | i)
}
return s
}(a.data.info);
for (var c in a.data.encrypt_table) {
var h = a.data.encrypt_table[c];
if ('q' == h || 'k' == h) {
var p = a.data.key_table.pop();
a.data.info = s[a.data.encrypt_table[c]](a.data.info, p)
} else
a.data.info = s[a.data.encrypt_table[c]](a.data.info)
}
if (e)
return a.data.info;
var g = '';
for (c = 0; c < a.data.info.length; c++)
g += String.fromCharCode(a.data.info[c]);
return g
}
function Uint8ArrayToString(fileData){
var dataString = '';
for (var i = 0; i < fileData.length; i++) {
dataString += Number(fileData[i]) + ',';
}
return dataString;
}
function decodeKey(resp){
var string = eval('('+resp+')');
//return btoa(String.fromCharCode.apply(null, new Uint8Array(n(string.data.info, 1))));
return Uint8ArrayToString(new Uint8Array(n(string.data.info, 1)));
}
function decodeM3u8(resp){
var string = eval('('+resp+')');
return n(string.data.info);
}
";
public static string DecodeM3u8(string resp)
{
var context = new Context();
context.Eval(JS);
var concatFunction = context.GetVariable("decodeM3u8").As<Function>();
string m3u8 = concatFunction.Call(new Arguments { resp }).ToString();
return m3u8;
}
public static string DecodeKey(string resp)
{
var context = new Context();
context.Eval(JS);
var concatFunction = context.GetVariable("decodeKey").As<Function>();
string key = concatFunction.Call(new Arguments { resp }).ToString();
byte[] v = Array.ConvertAll(key.Trim(',').Split(','), s => (byte)int.Parse(s));
string realKey = Convert.ToBase64String(v);
return realKey;
}
}
}

View File

@@ -0,0 +1,36 @@
using System;
using System.IO;
using System.Linq;
using System.Text;
namespace N_m3u8DL_CLI
{
class DecodeNfmovies
{
//https://jx.nfmovies.com/hls.min.js
public static string DecryptM3u8(byte[] byteArray)
{
var t = byteArray;
var decrypt = "";
if (137 == t[0] && 80 == t[1] && 130 == t[354] && 96 == t[353]) t = t.Skip(355).ToArray();
else
{
if (137 != t[0] || 80 != t[1] || 130 != t[394] || 96 != t[393])
{
for (var i = 0; i < t.Length; i++) decrypt += Convert.ToChar(t[i]);
return decrypt;
}
t = t.Skip(395).ToArray();
}
using (var zipStream =
new System.IO.Compression.GZipStream(new MemoryStream(t), System.IO.Compression.CompressionMode.Decompress))
{
using (StreamReader sr = new StreamReader(zipStream, Encoding.UTF8))
{
decrypt = sr.ReadToEnd();
}
}
return decrypt;
}
}
}

View File

@@ -1,16 +1,14 @@
using System;
using System.Collections.Generic;
using CSChaCha20;
using System;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace N_m3u8DL_CLI
{
class Decrypter
{
public static byte[] AES128Decrypt(string filePath, byte[] keyByte, byte[] ivByte)
public static byte[] AES128Decrypt(string filePath, byte[] keyByte, byte[] ivByte, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
{
FileStream fs = new FileStream(filePath, FileMode.Open);
//获取文件大小
@@ -19,36 +17,70 @@ namespace N_m3u8DL_CLI
fs.Read(inBuff, 0, inBuff.Length);
fs.Close();
Aes dcpt = Aes.Create("AES");
Aes dcpt = Aes.Create();
dcpt.BlockSize = 128;
dcpt.KeySize = 128;
dcpt.Key = keyByte;
dcpt.IV = ivByte;
dcpt.Mode = CipherMode.CBC;
dcpt.Padding = PaddingMode.PKCS7;
dcpt.Mode = mode;
dcpt.Padding = padding;
ICryptoTransform cTransform = dcpt.CreateDecryptor();
Byte[] resultArray = cTransform.TransformFinalBlock(inBuff, 0, inBuff.Length);
return resultArray;
}
public static byte[] AES128Decrypt(byte[] encryptedBuff, byte[] keyByte, byte[] ivByte)
public static byte[] AES128Decrypt(byte[] encryptedBuff, byte[] keyByte, byte[] ivByte, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
{
byte[] inBuff = encryptedBuff;
Aes dcpt = Aes.Create("AES");
Aes dcpt = Aes.Create();
dcpt.BlockSize = 128;
dcpt.KeySize = 128;
dcpt.Key = keyByte;
dcpt.IV = ivByte;
dcpt.Mode = CipherMode.CBC;
dcpt.Padding = PaddingMode.PKCS7;
dcpt.Mode = mode;
dcpt.Padding = padding;
ICryptoTransform cTransform = dcpt.CreateDecryptor();
Byte[] resultArray = cTransform.TransformFinalBlock(inBuff, 0, inBuff.Length);
return resultArray;
}
public static byte[] CHACHA20Decrypt(byte[] encryptedBuff, byte[] keyBytes, byte[] nonceBytes)
{
if (keyBytes.Length != 32)
throw new Exception("Key must be 32 bytes!");
if (nonceBytes.Length != 12 && nonceBytes.Length != 8)
throw new Exception("Key must be 12 or 8 bytes!");
if (nonceBytes.Length == 8)
nonceBytes = (new byte[4] { 0, 0, 0, 0 }).Concat(nonceBytes).ToArray();
var decStream = new MemoryStream();
using (BinaryReader reader = new BinaryReader(new MemoryStream(encryptedBuff)))
{
using (BinaryWriter writer = new BinaryWriter(decStream))
{
while (true)
{
var buffer = reader.ReadBytes(1024);
byte[] dec = new byte[buffer.Length];
if (buffer.Length > 0)
{
ChaCha20 forDecrypting = new ChaCha20(keyBytes, nonceBytes, 0);
forDecrypting.DecryptBytes(dec, buffer);
writer.Write(dec, 0, dec.Length);
}
else
{
break;
}
}
}
}
return decStream.ToArray();
}
public static byte[] HexStringToBytes(string hexStr)
{
if (string.IsNullOrEmpty(hexStr))
@@ -56,7 +88,7 @@ namespace N_m3u8DL_CLI
return new byte[0];
}
if (hexStr.StartsWith("0x") || hexStr.StartsWith("0X"))
if (hexStr.StartsWith("0x") || hexStr.StartsWith("0X"))
{
hexStr = hexStr.Remove(0, 2);
}

File diff suppressed because it is too large Load Diff

View File

@@ -47,6 +47,10 @@ namespace N_m3u8DL_CLI
public long ExpectByte { get => expectByte; set => expectByte = value; }
public long StartByte { get => startByte; set => startByte = value; }
public double SegDur { get => segDur; set => segDur = value; }
public static bool EnableChaCha20 { get; set; } = false;
public static string ChaCha20KeyBase64 { get; set; }
public static string ChaCha20NonceBase64 { get; set; }
//重写WebClinet
//private class WebClient : System.Net.WebClient
@@ -72,43 +76,55 @@ namespace N_m3u8DL_CLI
{
IsDone = false; //设置为未完成下载
if (Method == "NONE")
if (Method == "NONE" || method.Contains("NOTSUPPORTED"))
{
LOGGER.PrintLine("<" + SegIndex + " Downloading>");
LOGGER.WriteLine("<" + SegIndex + " Downloading>");
byte[] segBuff = Global.HttpDownloadFileToBytes(fileUrl, Headers, TimeOut);
//byte[] segBuff = Global.WebClientDownloadToBytes(fileUrl, Headers);
Global.AppendBytesToFileStreamAndDoNotClose(LiveStream, segBuff);
LOGGER.PrintLine("<" + SegIndex + " Complete>\r\n");
LOGGER.WriteLine("<" + SegIndex + " Complete>");
IsDone = true;
}
else if (Method == "AES-128")
{
LOGGER.PrintLine("<" + SegIndex + " Downloading>");
LOGGER.WriteLine("<" + SegIndex + " Downloading>");
byte[] encryptedBuff = Global.HttpDownloadFileToBytes(fileUrl, Headers, TimeOut);
//byte[] encryptedBuff = Global.WebClientDownloadToBytes(fileUrl, Headers);
byte[] decryptBuff = Decrypter.AES128Decrypt(
byte[] decryptBuff = null;
decryptBuff = Decrypter.AES128Decrypt(
encryptedBuff,
Convert.FromBase64String(Key),
Decrypter.HexStringToBytes(Iv)
);
Global.AppendBytesToFileStreamAndDoNotClose(LiveStream, decryptBuff);
LOGGER.PrintLine("<" + SegIndex + " Complete>\r\n");
LOGGER.WriteLine("<" + SegIndex + " Complete>");
IsDone = true;
}
else
{
LOGGER.PrintLine("不支持这种加密方式!", LOGGER.Error);
//LOGGER.PrintLine("不支持这种加密方式!", LOGGER.Error);
IsDone = true;
}
if (firstSeg && Global.FileSize(LiveFile) != 0)
{
LOGGER.STOPLOG = false; //记录日志
//LOGGER.STOPLOG = false; //记录日志
foreach (string ss in (string[])Global.GetVideoInfo(LiveFile).ToArray(typeof(string)))
{
LOGGER.WriteLine(ss.Trim());
}
firstSeg = false;
LOGGER.STOPLOG = true; //停止记录日志
//LOGGER.STOPLOG = true; //停止记录日志
}
HLSLiveDownloader.REC_DUR += SegDur;
if (HLSLiveDownloader.REC_DUR_LIMIT != -1 && HLSLiveDownloader.REC_DUR >= HLSLiveDownloader.REC_DUR_LIMIT)
{
LOGGER.PrintLine(strings.recordLimitReached, LOGGER.Warning);
LOGGER.WriteLine(strings.recordLimitReached);
Environment.Exit(0); //正常退出
}
return;
}
@@ -167,9 +183,18 @@ namespace N_m3u8DL_CLI
if (File.Exists(savePath) && Global.ShouldStop == false)
{
FileInfo fi = new FileInfo(savePath);
if (Method == "NONE")
if (File.Exists(fi.FullName) && EnableChaCha20)
{
fi.MoveTo(Path.GetDirectoryName(savePath) + "\\" + Path.GetFileNameWithoutExtension(savePath) + ".ts");
byte[] decryptBuff = Decrypter.CHACHA20Decrypt(File.ReadAllBytes(fi.FullName), Convert.FromBase64String(ChaCha20KeyBase64), Convert.FromBase64String(ChaCha20NonceBase64));
FileStream fs = new FileStream(Path.GetDirectoryName(SavePath) + "\\" + Path.GetFileNameWithoutExtension(SavePath) + ".ts", FileMode.Create);
fs.Write(decryptBuff, 0, decryptBuff.Length);
fs.Close();
DownloadManager.DownloadedSize += fi.Length;
fi.Delete();
}
else if (Method == "NONE" || Method.Contains("NOTSUPPORTED"))
{
fi.MoveTo(Path.GetDirectoryName(SavePath) + "\\" + Path.GetFileNameWithoutExtension(SavePath) + ".ts");
DownloadManager.DownloadedSize += fi.Length;
//Console.WriteLine(Path.GetFileNameWithoutExtension(savePath) + " Completed.");
}
@@ -179,11 +204,24 @@ namespace N_m3u8DL_CLI
//解密
try
{
byte[] decryptBuff = Decrypter.AES128Decrypt(
fi.FullName,
Convert.FromBase64String(Key),
Decrypter.HexStringToBytes(Iv)
);
byte[] decryptBuff = null;
if(fileUrl.Contains(".51cto.com/")) //使用AES-128-ECB模式解密
{
decryptBuff = Decrypter.AES128Decrypt(
fi.FullName,
Convert.FromBase64String(Key),
Decrypter.HexStringToBytes(Iv),
System.Security.Cryptography.CipherMode.ECB
);
}
else
{
decryptBuff = Decrypter.AES128Decrypt(
fi.FullName,
Convert.FromBase64String(Key),
Decrypter.HexStringToBytes(Iv)
);
}
FileStream fs = new FileStream(Path.GetDirectoryName(savePath) + "\\" + Path.GetFileNameWithoutExtension(savePath) + ".ts", FileMode.Create);
fs.Write(decryptBuff, 0, decryptBuff.Length);
fs.Close();
@@ -193,20 +231,16 @@ namespace N_m3u8DL_CLI
}
catch (Exception ex)
{
LOGGER.PrintLine(ex.Message, LOGGER.Error);
LOGGER.WriteLineError(ex.Message);
Thread.Sleep(3000);
Environment.Exit(-1);
}
}
else if(File.Exists(fi.FullName)
&& Method != "AES-128")
{
LOGGER.WriteLineError($"Do not support this METHOD: {Method}");
LOGGER.PrintLine("不支持这种加密方式!", LOGGER.Error);
return;
}
else
{
LOGGER.WriteLineError("Something was wrong!");
LOGGER.PrintLine("遇到了某些错误!", LOGGER.Error);
LOGGER.WriteLineError(strings.SomethingWasWrong);
LOGGER.PrintLine(strings.SomethingWasWrong, LOGGER.Error);
return;
}
return;
@@ -215,17 +249,17 @@ namespace N_m3u8DL_CLI
catch (Exception ex)
{
LOGGER.WriteLineError(ex.Message);
if (ex.Message.Contains("404"))
if (ex.Message.Contains("404") || ex.Message.Contains("400"))//(400) 错误的请求,片段过期会提示400错误
{
IsDone = true;
return;
}
else if (IsLive && count++ < Retry)
{
Thread.Sleep(5000);
Thread.Sleep(2000);//直播一般3-6秒一个片段
Down();
}
}
}
}
}
}

View File

@@ -10,19 +10,27 @@ namespace N_m3u8DL_CLI
{
class FFmpeg
{
private static string outPutPath = string.Empty;
private static string reportFile = string.Empty;
private static bool useAACFilter = false; //是否启用滤镜
private static bool writeDate = true; //是否写入录制日期
public static string OutPutPath { get => outPutPath; set => outPutPath = value; }
public static string ReportFile { get => reportFile; set => reportFile = value; }
public static bool UseAACFilter { get => useAACFilter; set => useAACFilter = value; }
public static bool WriteDate { get => writeDate; set => writeDate = value; }
public static string FFMPEG_PATH = "ffmpeg";
public static string REC_TIME = ""; //录制日期
public static string OutPutPath { get; set; } = string.Empty;
public static string ReportFile { get; set; } = string.Empty;
public static bool UseAACFilter { get; set; } = false; //是否启用滤镜
public static bool WriteDate { get; set; } = true; //是否写入录制日期
public static void Merge(string[] files, string muxFormat, bool fastStart,
string poster = "", string audioName = "", string title = "",
string copyright = "", string comment = "", string encodingTool = "")
{
string dateString = string.IsNullOrEmpty(REC_TIME) ? DateTime.Now.ToString("o") : REC_TIME;
//同名文件已存在的共存策略
if (File.Exists($"{OutPutPath}.{muxFormat.ToLower()}"))
{
OutPutPath = Path.Combine(Path.GetDirectoryName(OutPutPath),
Path.GetFileName(OutPutPath) + "_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss"));
}
string command = "-loglevel warning -i concat:\"";
string data = string.Empty;
string ddpAudio = string.Empty;
@@ -43,7 +51,7 @@ namespace N_m3u8DL_CLI
command += " " + (string.IsNullOrEmpty(ddpAudio) ? "" : "-i \"" + ddpAudio + "\"");
command +=
$" -map 0:v? {(string.IsNullOrEmpty(ddpAudio) ? "-map 0:a?" : $"-map {(string.IsNullOrEmpty(poster) ? "1" : "2")}:a -map 0:a?")} -map 0:s? " + (string.IsNullOrEmpty(poster) ? "" : addPoster)
+ (writeDate ? " -metadata date=\"" + DateTime.Now.ToString("o") + "\"" : "") +
+ (WriteDate ? " -metadata date=\"" + dateString + "\"" : "") +
" -metadata encoding_tool=\"" + encodingTool + "\" -metadata title=\"" + title +
"\" -metadata copyright=\"" + copyright + "\" -metadata comment=\"" + comment +
$"\" -metadata:s:a:{(string.IsNullOrEmpty(ddpAudio) ? "0" : "1")} handler_name=\"" + audioName + $"\" -metadata:s:a:{(string.IsNullOrEmpty(ddpAudio) ? "0" : "1")} handler=\"" + audioName + "\" ";
@@ -76,8 +84,8 @@ namespace N_m3u8DL_CLI
}
Run("ffmpeg", command, Path.GetDirectoryName(files[0]));
LOGGER.WriteLine("Result in [ffreport.log]");
Run(FFMPEG_PATH, command, Path.GetDirectoryName(files[0]));
LOGGER.WriteLine(strings.ffmpegDone);
//Console.WriteLine(command);
}
@@ -85,8 +93,8 @@ namespace N_m3u8DL_CLI
{
if (Global.VIDEO_TYPE == "H264")
{
Run("ffmpeg",
"-loglevel quiet -i \"" + file + "\" -map 0 -c copy -f mpegts -bsf:v h264_mp4toannexb \""
Run(FFMPEG_PATH,
"-loglevel quiet -i \"" + file + "\" -map 0 -c copy -copy_unknown -f mpegts -bsf:v h264_mp4toannexb \""
+ Path.GetFileNameWithoutExtension(file) + "[MPEGTS].ts\"",
Path.GetDirectoryName(file));
if (File.Exists(Path.GetDirectoryName(file) + "\\" + Path.GetFileNameWithoutExtension(file) + "[MPEGTS].ts"))
@@ -97,8 +105,8 @@ namespace N_m3u8DL_CLI
}
else if (Global.VIDEO_TYPE == "H265")
{
Run("ffmpeg",
"-loglevel quiet -i \"" + file + "\" -map 0 -c copy -f mpegts -bsf:v hevc_mp4toannexb \""
Run(FFMPEG_PATH,
"-loglevel quiet -i \"" + file + "\" -map 0 -c copy -copy_unknown -f mpegts -bsf:v hevc_mp4toannexb \""
+ Path.GetFileNameWithoutExtension(file) + "[MPEGTS].ts\"",
Path.GetDirectoryName(file));
if (File.Exists(Path.GetDirectoryName(file) + "\\" + Path.GetFileNameWithoutExtension(file) + "[MPEGTS].ts"))

File diff suppressed because it is too large Load Diff

View File

@@ -12,15 +12,17 @@ namespace N_m3u8DL_CLI
{
class HLSLiveDownloader
{
public static int REC_DUR_LIMIT = -1; //默认不限制录制时长
public static double REC_DUR = 0; //已录制时长
private string liveFile = string.Empty;
private string jsonFile = string.Empty;
private string headers = string.Empty;
private string downDir = string.Empty;
private FileStream liveStream = null;
private int targetduration = 10;
private double targetduration = 10;
private bool isFirstJson = true;
public double TotalDuration { get; set; }
public string Headers { get => headers; set => headers = value; }
public string DownDir { get => downDir; set => downDir = value; }
public FileStream LiveStream { get => liveStream; set => liveStream = value; }
@@ -33,7 +35,7 @@ namespace N_m3u8DL_CLI
public void TimerStart()
{
timer.Enabled = true;
timer.Interval = (targetduration - 2) * 1000; //执行间隔时间,单位为毫秒
//timer.Interval = (targetduration - 2) * 1000; //执行间隔时间,单位为毫秒
timer.Start();
timer.Elapsed += new ElapsedEventHandler(UpdateList);
UpdateList(timer, new EventArgs()); //立即执行一次
@@ -57,7 +59,10 @@ namespace N_m3u8DL_CLI
string jsonContent = File.ReadAllText(jsonFile);
JObject initJson = JObject.Parse(jsonContent);
string m3u8Url = initJson["m3u8"].Value<string>();
targetduration = initJson["m3u8Info"]["targetDuration"].Value<int>();
targetduration = initJson["m3u8Info"]["targetDuration"].Value<double>();
TotalDuration = initJson["m3u8Info"]["totalDuration"].Value<double>();
timer.Interval = Math.Abs(TotalDuration - targetduration) * 1000;//设置定时器运行间隔
if (timer.Interval <= 1000) timer.Interval = 10000;
JArray lastSegments = JArray.Parse(initJson["m3u8Info"]["segments"][0].ToString().Trim()); //上次的分段,用于比对新分段
ArrayList tempList = new ArrayList(); //所有待下载的列表
tempList.Clear();
@@ -74,8 +79,10 @@ namespace N_m3u8DL_CLI
}
Parser parser = new Parser();
parser.Headers = Headers;
parser.DownDir = Path.GetDirectoryName(jsonFile);
parser.M3u8Url = m3u8Url;
parser.LiveStream = true;
parser.Parse(); //产生新的json文件
jsonContent = File.ReadAllText(jsonFile);
@@ -89,6 +96,8 @@ namespace N_m3u8DL_CLI
//Console.WriteLine(seg.ToString());
}
}
if (toDownList.Count > 0)
Record();
}
//public void TryDownload()
@@ -108,10 +117,9 @@ namespace N_m3u8DL_CLI
private void Record()
{
ArrayList temp = toDownList;
while(temp.Count != 0)
while (toDownList.Count > 0 && (sd.FileUrl != "" ? sd.IsDone : true))
{
JObject info = JObject.Parse(temp[0].ToString());
JObject info = JObject.Parse(toDownList[0].ToString());
int index = info["index"].Value<int>();
sd.FileUrl = info["segUri"].Value<string>();
sd.Method = info["method"].Value<string>();
@@ -120,22 +128,21 @@ namespace N_m3u8DL_CLI
sd.Key = info["key"].Value<string>();
sd.Iv = info["iv"].Value<string>();
}
sd.TimeOut = 60000;
sd.TimeOut = (int)timer.Interval - 1000;//超时时间不超过下次执行时间
if (sd.TimeOut <= 0) sd.TimeOut = (int)timer.Interval;
sd.SegIndex = index;
sd.Headers = Headers;
sd.SegDur = info["duration"].Value<double>();
sd.IsLive = true; //标记为直播
sd.LiveFile = LiveFile;
sd.LiveStream = LiveStream;
sd.Down(); //开始下载
while (sd.IsDone != true) ; //忙等待
while (sd.IsDone != true) { Thread.Sleep(1); }; //忙等待 Thread.Sleep(1) 可防止cpu 100% 防止电脑风扇狂转
if (toDownList.Count > 0)
toDownList.RemoveAt(0); //下完删除一项
}
LOGGER.PrintLine("Waiting...");
//不断查找是否有新分段,有的话立即开始下载
while (isNewSeg() != true)
isNewSeg();
Record();
LOGGER.PrintLine("Waiting...", LOGGER.Warning);
LOGGER.WriteLine("Waiting...");
}
//检测是否有新分片

View File

@@ -0,0 +1,116 @@
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace N_m3u8DL_CLI
{
class IqJsonParser
{
public static string Parse(string downDir, string json)
{
JObject jObject = JObject.Parse(json);
var aClips = jObject["payload"]["wm_a"]["audio_track1"]["files"].Value<JArray>();
var vClips = jObject["payload"]["wm_a"]["video_track1"]["files"].Value<JArray>();
var codecsList = new List<string>();
var audioPath = "";
var videoPath = "";
var audioInitPath = "";
var videoInitPath = "";
if (aClips.Count > 0)
{
var init = jObject["payload"]["wm_a"]["audio_track1"]["codec_init"].Value<string>();
byte[] bytes = Convert.FromBase64String(init);
//输出init文件
audioInitPath = Path.Combine(downDir, "iqAudioInit.mp4");
File.WriteAllBytes(audioInitPath, bytes);
StringBuilder sb = new StringBuilder();
sb.AppendLine("#EXTM3U");
sb.AppendLine("#EXT-X-VERSION:3");
sb.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
sb.AppendLine("#CREATED-BY:N_m3u8DL-CLI");
sb.AppendLine($"#EXT-CODEC:{jObject["payload"]["wm_a"]["audio_track1"]["codec"].Value<string>()}");
sb.AppendLine($"#EXT-KID:{jObject["payload"]["wm_a"]["audio_track1"]["key_id"].Value<string>()}");
sb.AppendLine($"#EXT-X-MAP:URI=\"{new Uri(Path.Combine(downDir + "(Audio)", "iqAudioInit.mp4")).ToString()}\"");
sb.AppendLine("#EXT-X-KEY:METHOD=PLZ-KEEP-RAW,URI=\"None\"");
foreach (var a in aClips)
{
sb.AppendLine($"#EXTINF:{a["duration_second"].ToString()}");
sb.AppendLine(a["file_name"].Value<string>());
}
sb.AppendLine("#EXT-X-ENDLIST");
//输出m3u8文件
var _path = Path.Combine(downDir, "iqAudio.m3u8");
File.WriteAllText(_path, sb.ToString());
audioPath = new Uri(_path).ToString();
codecsList.Add(jObject["payload"]["wm_a"]["audio_track1"]["codec"].Value<string>());
}
if (vClips.Count > 0)
{
var init = jObject["payload"]["wm_a"]["video_track1"]["codec_init"].Value<string>();
byte[] bytes = Convert.FromBase64String(init);
//输出init文件
videoInitPath = Path.Combine(downDir, "iqVideoInit.mp4");
File.WriteAllBytes(videoInitPath, bytes);
StringBuilder sb = new StringBuilder();
sb.AppendLine("#EXTM3U");
sb.AppendLine("#EXT-X-VERSION:3");
sb.AppendLine("#EXT-X-PLAYLIST-TYPE:VOD");
sb.AppendLine("#CREATED-BY:N_m3u8DL-CLI");
sb.AppendLine($"#EXT-CODEC:{jObject["payload"]["wm_a"]["video_track1"]["codec"].Value<string>()}");
sb.AppendLine($"#EXT-KID:{jObject["payload"]["wm_a"]["video_track1"]["key_id"].Value<string>()}");
sb.AppendLine($"#EXT-X-MAP:URI=\"{new Uri(videoInitPath).ToString()}\"");
sb.AppendLine("#EXT-X-KEY:METHOD=PLZ-KEEP-RAW,URI=\"None\"");
foreach (var a in vClips)
{
var start = a["seekable"]["pos_start"].Value<long>();
var size = a["size"].Value<long>();
sb.AppendLine($"#EXTINF:{a["duration_second"].ToString()}");
sb.AppendLine($"#EXT-X-BYTERANGE:{size}@{start}");
sb.AppendLine(a["file_name"].Value<string>());
}
sb.AppendLine("#EXT-X-ENDLIST");
//输出m3u8文件
var _path = Path.Combine(downDir, "iqVideo.m3u8");
File.WriteAllText(_path, sb.ToString());
videoPath = new Uri(_path).ToString();
codecsList.Add(jObject["payload"]["wm_a"]["video_track1"]["codec"].Value<string>());
}
var content = "";
if ((videoPath == "" && audioPath != "") || Global.VIDEO_TYPE == "IGNORE")
{
return audioPath;
}
else if (audioPath == "" && videoPath != "")
{
return videoPath;
}
else
{
if (!Directory.Exists(downDir + "(Audio)"))
Directory.CreateDirectory(downDir + "(Audio)");
var _path = Path.Combine(downDir + "(Audio)", "iqAudio.m3u8");
var _pathInit = Path.Combine(downDir + "(Audio)", "iqAudioInit.mp4");
File.Copy(new Uri(audioPath).LocalPath, _path, true);
File.Copy(new Uri(audioInitPath).LocalPath, _pathInit, true);
audioPath = new Uri(_path).ToString();
content = $"#EXTM3U\r\n" +
$"#EXT-X-MEDIA:TYPE=AUDIO,URI=\"{audioPath}\",GROUP-ID=\"default-audio-group\",NAME=\"stream_0\",AUTOSELECT=YES,CHANNELS=\"0\"\r\n" +
$"#EXT-X-STREAM-INF:BANDWIDTH=99999,CODECS=\"{string.Join(",", codecsList)}\",RESOLUTION=0x0,AUDIO=\"default-audio-group\"\r\n" +
$"{videoPath}";
}
var _masterPath = Path.Combine(downDir, "master.m3u8");
File.WriteAllText(_masterPath, content);
return new Uri(_masterPath).ToString();
}
}
}

View File

@@ -11,8 +11,6 @@ namespace N_m3u8DL_CLI
{
class LOGGER
{
public static int CursorIndex = 5;
public static int FFmpegCorsorIndex = 5;
public const int Default = 1;
public const int Error = 2;
public const int Warning = 3;
@@ -36,8 +34,13 @@ namespace N_m3u8DL_CLI
{
if (!Directory.Exists(Path.GetDirectoryName(LOGFILE)))//若文件夹不存在则新建文件夹
Directory.CreateDirectory(Path.GetDirectoryName(LOGFILE)); //新建文件夹
if (File.Exists(LOGFILE))//若文件存在则删除
File.Delete(LOGFILE);
//若文件存在则加序号
int index = 1;
var fileName = Path.GetFileNameWithoutExtension(LOGFILE);
while (File.Exists(LOGFILE))
{
LOGFILE = Path.Combine(Path.GetDirectoryName(LOGFILE), $"{fileName}-{index++}.log");
}
string file = LOGFILE;
string now = DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss");
string init = "LOG " + DateTime.Now.ToString("yyyy/MM/dd") + "\r\n"
@@ -57,35 +60,37 @@ namespace N_m3u8DL_CLI
//读写锁机制,当资源被占用,其他线程等待
static ReaderWriterLockSlim LogWriteLock = new ReaderWriterLockSlim();
public static void PrintLine(string text, int printLevel = 1, int cursorIndex = 0)
public static void PrintLine(string text, int printLevel = 1)
{
int windowWith = 63;
try
{
if (cursorIndex == 0)
Console.SetCursorPosition(0, CursorIndex++);
else
Console.SetCursorPosition(0, cursorIndex);
windowWith = Console.WindowWidth;
}
catch (Exception)
catch (Exception e)
{
;
// empty
}
switch (printLevel)
{
case 0:
Console.Write("\r" + new string(' ', windowWith - 1) + "\r");
Console.WriteLine(" ".PadRight(12) + " " + text);
break;
case 1:
Console.Write("\r" + new string(' ', windowWith - 1) + "\r");
Console.Write(DateTime.Now.ToString("HH:mm:ss.fff") + " ");
Console.WriteLine(text);
break;
case 2:
Console.Write("\r" + new string(' ', windowWith - 1) + "\r");
Console.Write(DateTime.Now.ToString("HH:mm:ss.fff") + " ");
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(text);
Console.ResetColor();
break;
case 3:
Console.Write("\r" + new string(' ', windowWith - 1) + "\r");
Console.Write(DateTime.Now.ToString("HH:mm:ss.fff") + " ");
Console.ForegroundColor = ConsoleColor.DarkYellow;
Console.WriteLine(text);
@@ -113,7 +118,7 @@ namespace N_m3u8DL_CLI
}
catch (Exception)
{
}
finally
{
@@ -138,7 +143,7 @@ namespace N_m3u8DL_CLI
}
catch (Exception)
{
}
finally
{
@@ -151,7 +156,7 @@ namespace N_m3u8DL_CLI
{
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(DateTime.Now.ToString("o") + " " + text);
while (Console.ForegroundColor == ConsoleColor.Red)
while (Console.ForegroundColor == ConsoleColor.Red)
Console.ResetColor();
}
}

874
N_m3u8DL-CLI/MPDParser.cs Normal file

File diff suppressed because it is too large Load Diff

110
N_m3u8DL-CLI/MyOptions.cs Normal file
View File

@@ -0,0 +1,110 @@
using CommandLine;
using CommandLine.Text;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace N_m3u8DL_CLI
{
internal class MyOptions
{
[Value(0, Hidden = true, MetaName = "Input Source", HelpText = "Help_input", ResourceType = typeof(strings))]
public string Input { get; set; }
[Option("workDir", HelpText = "Help_workDir", ResourceType = typeof(strings))]
public string WorkDir { get; set; }
[Option("saveName", HelpText = "Help_saveName", ResourceType = typeof(strings))]
public string SaveName { get; set; } = "";
[Option("baseUrl", HelpText = "Help_baseUrl", ResourceType = typeof(strings))]
public string BaseUrl { get; set; }
[Option("headers", HelpText = "Help_headers", ResourceType = typeof(strings))]
public string Headers { get; set; } = "";
[Option("maxThreads", Default = 32U, HelpText = "Help_maxThreads", ResourceType = typeof(strings))]
public uint MaxThreads { get; set; }
[Option("minThreads", Default = 16U, HelpText = "Help_minThreads", ResourceType = typeof(strings))]
public uint MinThreads { get; set; }
[Option("retryCount", Default = 15U, HelpText = "Help_retryCount", ResourceType = typeof(strings))]
public uint RetryCount { get; set; }
[Option("timeOut", Default = 10U, HelpText = "Help_timeOut", ResourceType = typeof(strings))]
public uint TimeOut { get; set; }
[Option("muxSetJson", HelpText = "Help_muxSetJson", ResourceType = typeof(strings))]
public string MuxSetJson { get; set; }
[Option("useKeyFile", HelpText = "Help_useKeyFile", ResourceType = typeof(strings))]
public string UseKeyFile { get; set; }
[Option("useKeyBase64", HelpText = "Help_useKeyBase64", ResourceType = typeof(strings))]
public string UseKeyBase64 { get; set; }
[Option("useKeyIV", HelpText = "Help_useKeyIV", ResourceType = typeof(strings))]
public string UseKeyIV { get; set; }
[Option("downloadRange", HelpText = "Help_downloadRange", ResourceType = typeof(strings))]
public string DownloadRange { get; set; }
[Option("liveRecDur", HelpText = "Help_liveRecDur", ResourceType = typeof(strings))]
public string LiveRecDur { get; set; }
[Option("stopSpeed", HelpText = "Help_stopSpeed", ResourceType = typeof(strings))]
public long StopSpeed { get; set; } = 0L;
[Option("maxSpeed", HelpText = "Help_maxSpeed", ResourceType = typeof(strings))]
public long MaxSpeed { get; set; } = 0L;
[Option("proxyAddress", HelpText = "Help_proxyAddress", ResourceType = typeof(strings))]
public string ProxyAddress { get; set; }
[Option("enableDelAfterDone", HelpText = "Help_enableDelAfterDone", ResourceType = typeof(strings))]
public bool EnableDelAfterDone { get; set; }
[Option("enableMuxFastStart", HelpText = "Help_enableMuxFastStart", ResourceType = typeof(strings))]
public bool EnableMuxFastStart { get; set; }
[Option("enableBinaryMerge", HelpText = "Help_enableBinaryMerge", ResourceType = typeof(strings))]
public bool EnableBinaryMerge { get; set; }
[Option("enableParseOnly", HelpText = "Help_enableParseOnly", ResourceType = typeof(strings))]
public bool EnableParseOnly { get; set; }
[Option("enableAudioOnly", HelpText = "Help_enableAudioOnly", ResourceType = typeof(strings))]
public bool EnableAudioOnly { get; set; }
[Option("disableDateInfo", HelpText = "Help_disableDateInfo", ResourceType = typeof(strings))]
public bool DisableDateInfo { get; set; }
[Option("disableIntegrityCheck", HelpText = "Help_disableIntegrityCheck", ResourceType = typeof(strings))]
public bool DisableIntegrityCheck { get; set; }
[Option("noMerge", HelpText = "Help_noMerge", ResourceType = typeof(strings))]
public bool NoMerge { get; set; }
[Option("noProxy", HelpText = "Help_noProxy", ResourceType = typeof(strings))]
public bool NoProxy { get; set; }
[Option("registerUrlProtocol", HelpText = "Help_registerUrlProtocol", ResourceType = typeof(strings))]
public bool RegisterUrlProtocol { get; set; }
[Option("unregisterUrlProtocol", HelpText = "Help_unregisterUrlProtocol", ResourceType = typeof(strings))]
public bool UnregisterUrlProtocol { get; set; }
[Option("enableChaCha20", HelpText = "enableChaCha20")]
public bool EnableChaCha20 { get; set; }
[Option("chaCha20KeyBase64", HelpText = "ChaCha20KeyBase64")]
public string ChaCha20KeyBase64 { get; set; }
[Option("chaCha20NonceBase64", HelpText = "ChaCha20NonceBase64")]
public string ChaCha20NonceBase64 { get; set; }
}
}

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props" Condition="Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" />
<Import Project="..\packages\Resource.Embedder.2.1.1\build\Resource.Embedder.props" Condition="Exists('..\packages\Resource.Embedder.2.1.1\build\Resource.Embedder.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -12,6 +14,8 @@
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x86</PlatformTarget>
@@ -38,46 +42,98 @@
<ApplicationIcon>logo_3Iv_icon.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="BrotliSharpLib, Version=0.3.2.0, Culture=neutral, PublicKeyToken=3f4e2a1cd615fcb7, processorArchitecture=MSIL">
<HintPath>..\packages\BrotliSharpLib.0.3.3\lib\net451\BrotliSharpLib.dll</HintPath>
</Reference>
<Reference Include="CommandLine, Version=2.8.0.0, Culture=neutral, PublicKeyToken=5a870481e358d379, processorArchitecture=MSIL">
<HintPath>..\packages\CommandLineParser.2.8.0\lib\net45\CommandLine.dll</HintPath>
</Reference>
<Reference Include="Costura, Version=4.1.0.0, Culture=neutral, PublicKeyToken=9919ef960d84173d, processorArchitecture=MSIL">
<HintPath>..\packages\Costura.Fody.4.1.0\lib\net40\Costura.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Build.Framework" />
<Reference Include="Microsoft.Build.Utilities.v4.0" />
<Reference Include="Microsoft.JScript" />
<Reference Include="Newtonsoft.Json">
<HintPath>..\..\HDC上传助手\HDC上传助手\bin\Debug\Newtonsoft.Json.dll</HintPath>
<Reference Include="Microsoft.Win32.TaskScheduler, Version=2.8.7.0, Culture=neutral, PublicKeyToken=c416bc1b32d97233, processorArchitecture=MSIL">
<HintPath>..\packages\TaskScheduler.2.8.7\lib\net452\Microsoft.Win32.TaskScheduler.dll</HintPath>
</Reference>
<Reference Include="MihaZupan.HttpToSocks5Proxy, Version=1.4.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\HttpToSocks5Proxy.1.4.0\lib\net45\MihaZupan.HttpToSocks5Proxy.dll</HintPath>
</Reference>
<Reference Include="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51" />
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NiL.JS, Version=2.5.1428.0, Culture=neutral, PublicKeyToken=fa941a7c2a4de689, processorArchitecture=MSIL">
<HintPath>..\packages\NiL.JS.2.5.1428\lib\net45\NiL.JS.dll</HintPath>
</Reference>
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Collections" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.IO" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=4.0.4.1, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.4.5.2\lib\netstandard1.0\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="UACHelper, Version=1.3.0.4, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\UACHelper.1.3.0.5\lib\net40\UACHelper.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="CommandLineArgument.cs" />
<Compile Include="CommandLineArgumentParser.cs" />
<Compile Include="CSChaCha20.cs" />
<Compile Include="Decode51CtoKey.cs" />
<Compile Include="DecodeCdeledu.cs" />
<Compile Include="DecodeDdyun.cs" />
<Compile Include="DecodeHuke88Key.cs" />
<Compile Include="DecodeImooc.cs" />
<Compile Include="Decrypter.cs" />
<Compile Include="DecodeNfmovies.cs" />
<Compile Include="FFmpeg.cs" />
<Compile Include="Global.cs" />
<Compile Include="HLSLiveDownloader.cs" />
<Compile Include="HLSTags.cs" />
<Compile Include="IqJsonParser.cs" />
<Compile Include="LOGGER.cs" />
<Compile Include="DownloadManager.cs" />
<Compile Include="MPDParser.cs" />
<Compile Include="MyOptions.cs" />
<Compile Include="Parser.cs" />
<Compile Include="Program.cs" />
<Compile Include="ProgressReporter.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Downloader.cs" />
<Compile Include="strings.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>strings.resx</DependentUpon>
</Compile>
<Compile Include="strings.en-US.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>strings.en-US.resx</DependentUpon>
</Compile>
<Compile Include="strings.zh-TW.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>strings.zh-TW.resx</DependentUpon>
</Compile>
<Compile Include="Watcher.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config">
<SubType>Designer</SubType>
</None>
</ItemGroup>
<ItemGroup>
<None Include="bin\Debug\Newtonsoft.Json.dll" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<COMReference Include="Scripting">
@@ -93,5 +149,31 @@
<ItemGroup>
<Content Include="logo_3Iv_icon.ico" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="strings.en-US.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>strings.en-US.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="strings.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>strings.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="strings.zh-TW.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>strings.zh-TW.Designer.cs</LastGenOutput>
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>这台计算机上缺少此项目引用的 NuGet 程序包。使用“NuGet 程序包还原”可下载这些程序包。有关更多信息,请参见 http://go.microsoft.com/fwlink/?LinkID=322105。缺少的文件是 {0}。</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\Resource.Embedder.2.1.1\build\Resource.Embedder.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Resource.Embedder.2.1.1\build\Resource.Embedder.props'))" />
<Error Condition="!Exists('..\packages\Fody.6.0.0\build\Fody.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Fody.6.0.0\build\Fody.targets'))" />
<Error Condition="!Exists('..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\Costura.Fody.4.1.0\build\Costura.Fody.props'))" />
</Target>
<Import Project="..\packages\Fody.6.0.0\build\Fody.targets" Condition="Exists('..\packages\Fody.6.0.0\build\Fody.targets')" />
</Project>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace N_m3u8DL_CLI
{
class ProgressReporter
{
private static string speed = "";
private static string progress = "";
static object lockThis = new object();
public static void Report(string progress, string speed)
{
lock (lockThis)
{
int windowWith = 63;
try
{
windowWith = Console.WindowWidth;
}
catch (Exception e)
{
// empty
}
if (!string.IsNullOrEmpty(progress)) ProgressReporter.progress = progress;
if (!string.IsNullOrEmpty(speed)) ProgressReporter.speed = speed;
string now = DateTime.Now.ToString("HH:mm:ss.000");
var sub = windowWith - 4 - ProgressReporter.progress.Length - ProgressReporter.speed.Length - now.Length;
if (sub <= 0) sub = 0;
string print = now + " " + ProgressReporter.progress + " " + ProgressReporter.speed + new string(' ', sub);
Console.Write("\r" + print + "\r");
//Console.Write(print);
}
}
}
}

View File

@@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("nilaoda")]
[assembly: AssemblyProduct("N_m3u8DL-CLI")]
[assembly: AssemblyCopyright("Copyright © 2019")]
[assembly: AssemblyCopyright("Copyright © 2022")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
// 方法是按如下所示使用“*”: :
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyVersion("3.0.2.0")]
[assembly: AssemblyFileVersion("3.0.2.0")]

View File

@@ -59,10 +59,12 @@ namespace N_m3u8DL_CLI
//Console.Title = Now + " / " + Total;
string downloadedSize = Global.FormatFileSize(DownloadManager.DownloadedSize);
string estimatedSize = Global.FormatFileSize(DownloadManager.DownloadedSize * total / now);
int padding = downloadedSize.Length > estimatedSize.Length ? downloadedSize.Length : estimatedSize.Length;
DownloadManager.ToDoSize = (DownloadManager.DownloadedSize * total / now) - DownloadManager.DownloadedSize;
string percent = (Convert.ToDouble(now) / Convert.ToDouble(total) * 100).ToString("0.00") + "%";
Console.SetCursorPosition(0, 2);
Console.Write(("Progress: " + Now + " of " + Total
+ $" ({percent}/{downloadedSize}/{estimatedSize}/{Global.FormatTime(Convert.ToInt32(TotalDuration))})").PadRight(62));
var print = "Progress: " + Now + "/" + Total
+ $" ({percent}) -- {downloadedSize.PadLeft(padding)}/{estimatedSize.PadRight(padding)}";
ProgressReporter.Report(print, "");
}
private void OnRenamed(object source, RenamedEventArgs e)
@@ -77,10 +79,12 @@ namespace N_m3u8DL_CLI
//Console.Title = Now + " / " + Total;
string downloadedSize = Global.FormatFileSize(DownloadManager.DownloadedSize);
string estimatedSize = Global.FormatFileSize(DownloadManager.DownloadedSize * total / now);
int padding = downloadedSize.Length > estimatedSize.Length ? downloadedSize.Length : estimatedSize.Length;
DownloadManager.ToDoSize = (DownloadManager.DownloadedSize * total / now) - DownloadManager.DownloadedSize;
string percent = (Convert.ToDouble(now) / Convert.ToDouble(total) * 100).ToString("0.00") + "%";
Console.SetCursorPosition(0, 2);
Console.Write(("Progress: " + Now + " of " + Total
+ $" ({percent}/{downloadedSize}/{estimatedSize}/{Global.FormatTime(Convert.ToInt32(TotalDuration))})").PadRight(62));
var print = "Progress: " + Now + "/" + Total
+ $" ({percent}) -- {downloadedSize.PadLeft(padding)}/{estimatedSize.PadRight(padding)}";
ProgressReporter.Report(print, "");
}
private void OnDeleted(object source, FileSystemEventArgs e)
@@ -95,10 +99,12 @@ namespace N_m3u8DL_CLI
//Console.Title = Now + " / " + Total;
string downloadedSize = Global.FormatFileSize(DownloadManager.DownloadedSize);
string estimatedSize = Global.FormatFileSize(DownloadManager.DownloadedSize * total / now);
int padding = downloadedSize.Length > estimatedSize.Length ? downloadedSize.Length : estimatedSize.Length;
DownloadManager.ToDoSize = (DownloadManager.DownloadedSize * total / now) - DownloadManager.DownloadedSize;
string percent = (Convert.ToDouble(now) / Convert.ToDouble(total) * 100).ToString("0.00") + "%";
Console.SetCursorPosition(0, 2);
Console.Write(("Progress: " + Now + " of " + Total
+ $" ({percent}/{downloadedSize}/{estimatedSize}/{Global.FormatTime(Convert.ToInt32(TotalDuration))})").PadRight(62));
var print = "Progress: " + Now + "/" + Total
+ $" ({percent}) -- {downloadedSize.PadLeft(padding)}/{estimatedSize.PadRight(padding)}";
ProgressReporter.Report(print, "");
}
}
}

362
N_m3u8DL-CLI/changelog.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="BrotliSharpLib" version="0.3.3" targetFramework="net46" />
<package id="CommandLineParser" version="2.8.0" targetFramework="net46" />
<package id="Costura.Fody" version="4.1.0" targetFramework="net46" />
<package id="Fody" version="6.0.0" targetFramework="net46" developmentDependency="true" />
<package id="HttpToSocks5Proxy" version="1.4.0" targetFramework="net46" />
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net46" />
<package id="NiL.JS" version="2.5.1428" targetFramework="net46" />
<package id="Resource.Embedder" version="2.1.1" targetFramework="net46" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.2" targetFramework="net46" />
<package id="TaskScheduler" version="2.8.7" targetFramework="net46" />
<package id="UACHelper" version="1.3.0.5" targetFramework="net46" />
</packages>

837
N_m3u8DL-CLI/strings.Designer.cs generated Normal file

File diff suppressed because it is too large Load Diff

0
N_m3u8DL-CLI/strings.en-US.Designer.cs generated Normal file
View File

Some files were not shown because too many files have changed in this diff Show More