easyrip 4.15.2__py3-none-any.whl → 4.16.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -719,7 +719,7 @@ class Opt_type(enum.Enum):
719
719
  "Algorithm:"
720
720
  ),
721
721
  childs=(
722
- Cmd_type_val(("ssim",), description="Default threshold: 0.9"),
722
+ Cmd_type_val(("ssim",), description="Default threshold: 0.85"),
723
723
  Cmd_type_val(("psnr",), description="Default threshold: 30"),
724
724
  Cmd_type_val(("vmaf",), description="Default threshold: 80"),
725
725
  ),
@@ -6,6 +6,20 @@ import urllib.request
6
6
  import xml.etree.ElementTree
7
7
  from time import sleep
8
8
 
9
+ REQ_HEADER = {
10
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:147.0) Gecko/20100101 Firefox/147.0"
11
+ }
12
+
13
+
14
+ def open_req(req: urllib.request.Request):
15
+ from ..easyrip_log import log
16
+
17
+ proxies = urllib.request.getproxies()
18
+ log.debug("Proxies: {}", proxies, print_level=log.LogLevel._detail)
19
+ opener = urllib.request.build_opener(urllib.request.ProxyHandler(proxies))
20
+
21
+ return opener.open(req)
22
+
9
23
 
10
24
  class zhconvert:
11
25
  """繁化姬 API"""
@@ -42,11 +56,12 @@ class zhconvert:
42
56
  data=urllib.parse.urlencode(
43
57
  {"text": org_text, "converter": target_lang.value}
44
58
  ).encode("utf-8"),
59
+ headers=REQ_HEADER,
45
60
  )
46
61
 
47
62
  for retry_num in range(5):
48
63
  try:
49
- with urllib.request.urlopen(req) as response:
64
+ with open_req(req) as response:
50
65
  for _ in range(5): # 尝试重连
51
66
  if response.getcode() != 200:
52
67
  log.debug("response.getcode() != 200")
@@ -62,11 +77,11 @@ class zhconvert:
62
77
  return text
63
78
 
64
79
  raise Exception(f"HTTP error: {response.getcode()}")
65
- except urllib.error.HTTPError:
80
+ except urllib.error.HTTPError as e:
66
81
  sleep(0.5)
67
82
  if retry_num == 4:
68
83
  raise
69
- log.debug("Attempt to reconnect")
84
+ log.debug("Attempt to reconnect: {}", e)
70
85
  continue
71
86
 
72
87
  raise Exception
@@ -78,10 +93,13 @@ class github:
78
93
  """失败返回 None"""
79
94
  from ..easyrip_log import log
80
95
 
81
- req = urllib.request.Request(release_api_url)
96
+ req = urllib.request.Request(
97
+ url=release_api_url,
98
+ headers=REQ_HEADER,
99
+ )
82
100
 
83
101
  try:
84
- with urllib.request.urlopen(req) as response:
102
+ with open_req(req) as response:
85
103
  data: dict = json.loads(response.read().decode("utf-8"))
86
104
  ver = data.get("tag_name")
87
105
  if ver is None:
@@ -111,10 +129,13 @@ class mkvtoolnix:
111
129
 
112
130
  from ..easyrip_log import log
113
131
 
114
- req = urllib.request.Request("https://mkvtoolnix.download/latest-release.xml")
132
+ req = urllib.request.Request(
133
+ url="https://mkvtoolnix.download/latest-release.xml",
134
+ headers=REQ_HEADER,
135
+ )
115
136
 
116
137
  try:
117
- with urllib.request.urlopen(req) as response:
138
+ with open_req(req) as response:
118
139
  xml_tree = xml.etree.ElementTree.XML(response.read().decode("utf-8"))
119
140
  if (ver := xml_tree.find("latest-source/version")) is None:
120
141
  log.debug(
easyrip/global_val.py CHANGED
@@ -4,7 +4,7 @@ from functools import cache
4
4
  from pathlib import Path
5
5
 
6
6
  PROJECT_NAME = "Easy Rip"
7
- PROJECT_VERSION = "4.15.2"
7
+ PROJECT_VERSION = "4.16.0"
8
8
  PROJECT_TITLE = f"{PROJECT_NAME} v{PROJECT_VERSION}"
9
9
  PROJECT_URL = "https://github.com/op200/EasyRip"
10
10
  PROJECT_RELEASE_API = "https://api.github.com/repos/op200/EasyRip/releases/latest"
easyrip/ripper/ripper.py CHANGED
@@ -8,6 +8,7 @@ from collections.abc import Callable, Iterable
8
8
  from dataclasses import dataclass
9
9
  from datetime import datetime
10
10
  from itertools import zip_longest
11
+ from operator import itemgetter
11
12
  from pathlib import Path
12
13
  from threading import Thread
13
14
  from time import sleep
@@ -21,7 +22,7 @@ from ..easyrip_mlang import (
21
22
  gettext,
22
23
  translate_subtitles,
23
24
  )
24
- from ..utils import get_base62_time, read_text, type_match
25
+ from ..utils import get_base62_time, type_match
25
26
  from .media_info import Media_info, Stream_error
26
27
  from .param import (
27
28
  FONT_SUFFIX_SET,
@@ -1305,30 +1306,23 @@ class Ripper:
1305
1306
  while True:
1306
1307
  match quality_detection[0]:
1307
1308
  case "ssim":
1308
- quality_detection_th = 0.9
1309
+ quality_detection_th = 0.85
1309
1310
  quality_detection_filter = "ssim=f="
1310
1311
 
1311
1312
  def quality_detection_cmp(
1312
- text: str, threshold: float
1313
- ) -> None:
1314
- for line in text.splitlines():
1315
- values = tuple(
1316
- s.split(":")[1] for s in line.split()[:-1]
1313
+ text: str,
1314
+ ) -> list[tuple[str | int, float]]:
1315
+ return [
1316
+ (n, q)
1317
+ for line in text.splitlines()
1318
+ if (
1319
+ v := [
1320
+ s.split(":")[1] for s in line.split()[:-1]
1321
+ ]
1317
1322
  )
1318
- ssim_all = float(values[-1])
1319
- n = values[0]
1320
- log.debug(
1321
- f"{n}: {ssim_all}",
1322
- is_format=False,
1323
- print_level=log.LogLevel._detail,
1324
- )
1325
- if ssim_all < threshold:
1326
- log.error(
1327
- "SSIM {} < threshold {} in frame {}",
1328
- ssim_all,
1329
- threshold,
1330
- n,
1331
- )
1323
+ and (q := float(v[-1]))
1324
+ and (n := int(v[0]) - 1)
1325
+ ]
1332
1326
 
1333
1327
  break
1334
1328
  case "psnr":
@@ -1336,26 +1330,15 @@ class Ripper:
1336
1330
  quality_detection_filter = "psnr=f="
1337
1331
 
1338
1332
  def quality_detection_cmp(
1339
- text: str, threshold: float
1340
- ) -> None:
1341
- for line in text.splitlines():
1342
- values = tuple(
1343
- s.split(":")[1] for s in line.split()
1344
- )
1345
- psnr_avg_all = float(values[-4])
1346
- n = values[0]
1347
- log.debug(
1348
- f"{n}: {psnr_avg_all}",
1349
- is_format=False,
1350
- print_level=log.LogLevel._detail,
1351
- )
1352
- if psnr_avg_all < threshold:
1353
- log.error(
1354
- "PSNR {} < threshold {} in frame {}",
1355
- psnr_avg_all,
1356
- threshold,
1357
- n,
1358
- )
1333
+ text: str,
1334
+ ) -> list[tuple[str | int, float]]:
1335
+ return [
1336
+ (n, q)
1337
+ for line in text.splitlines()
1338
+ if (v := [s.split(":")[1] for s in line.split()])
1339
+ and (q := float(v[-4]))
1340
+ and (n := int(v[0]) - 1)
1341
+ ]
1359
1342
 
1360
1343
  break
1361
1344
  case "vmaf":
@@ -1363,23 +1346,13 @@ class Ripper:
1363
1346
  quality_detection_filter = "libvmaf=log_fmt=csv:log_path="
1364
1347
 
1365
1348
  def quality_detection_cmp(
1366
- text: str, threshold: float
1367
- ) -> None:
1368
- for line in tuple(csv.reader(text))[1:]:
1369
- vmaf = float(line[-1])
1370
- n = int(line[0]) + 1
1371
- log.debug(
1372
- f"{n}: {vmaf}",
1373
- is_format=False,
1374
- print_level=log.LogLevel._detail,
1375
- )
1376
- if vmaf < threshold:
1377
- log.error(
1378
- "VMAF {} < threshold {} in frame {}",
1379
- vmaf,
1380
- threshold,
1381
- n,
1382
- )
1349
+ text: str,
1350
+ ) -> list[tuple[str | int, float]]:
1351
+ return [
1352
+ (n, q)
1353
+ for v in tuple(csv.reader(text.splitlines()[1:]))
1354
+ if (q := float(v[-2])) and (n := v[0])
1355
+ ]
1383
1356
 
1384
1357
  break
1385
1358
  case _:
@@ -1404,6 +1377,7 @@ class Ripper:
1404
1377
  .replace("\\", "/")
1405
1378
  .replace(":", "\\\\:")
1406
1379
  )
1380
+
1407
1381
  if os.system(
1408
1382
  f'ffmpeg -i "{self.input_path_list[0]}" -i "{os.path.join(self.output_dir, temp_name)}" -lavfi "{quality_detection_filter}{quality_detection_data_file_filter_str}" -f null -'
1409
1383
  ):
@@ -1414,9 +1388,22 @@ class Ripper:
1414
1388
  "-quality-detection",
1415
1389
  f"{quality_detection[0]}:{quality_detection_th}",
1416
1390
  )
1417
- quality_detection_cmp(
1418
- read_text(quality_detection_data_file), quality_detection_th
1419
- )
1391
+ with quality_detection_data_file.open("rt", encoding="utf-8") as f:
1392
+ _res = quality_detection_cmp(f.read())
1393
+ for n, q in _res:
1394
+ if q < quality_detection_th:
1395
+ log.error(
1396
+ "{} {} < threshold {} in frame {}",
1397
+ quality_detection[0].upper(),
1398
+ q,
1399
+ quality_detection_th,
1400
+ n,
1401
+ )
1402
+ log.info(
1403
+ "{} min = {}",
1404
+ quality_detection[0].upper(),
1405
+ min(map(itemgetter(1), _res)),
1406
+ )
1420
1407
  log.debug("'{}' end", "-quality-detection")
1421
1408
  quality_detection_data_file.unlink(missing_ok=True)
1422
1409
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: easyrip
3
- Version: 4.15.2
3
+ Version: 4.16.0
4
4
  Author: op200
5
5
  License-Expression: AGPL-3.0-or-later
6
6
  Project-URL: Homepage, https://github.com/op200/EasyRip
@@ -1,10 +1,10 @@
1
1
  easyrip/__init__.py,sha256=DULQoFEAEHYk7dS8Zxky56so7qDPqHm7jUc_Zop1eXw,616
2
2
  easyrip/__main__.py,sha256=oiDLhxR-o7dh6jAZMuiOX6RMX_LTFRMOhg16kR1dVZM,4743
3
- easyrip/easyrip_command.py,sha256=RfJMjlFIlFznxM2YyDkrlAoxbaJUC8xOZEkxvOUD1Pk,34010
3
+ easyrip/easyrip_command.py,sha256=6j2EFg9PesESmPpDbxfs8mzLVTMwcEjj9xeuPfbq7B4,34011
4
4
  easyrip/easyrip_log.py,sha256=R-dM3CWUBFITtG7GSD1zy4X4MhZqxkoiBPjlIpI76cY,15573
5
5
  easyrip/easyrip_main.py,sha256=EjEjs1UCVSMGxdQ-XUggiDbZ0pOxiKcC85toNdbFTV4,48766
6
6
  easyrip/easyrip_prompt.py,sha256=OidVzSkBksC89HzDcvqGkF9CXyhPNINYDp1sgLarxf8,7087
7
- easyrip/global_val.py,sha256=imyOEDnS1dmIULjmq0UrwEcKBF7Bcb4ELybrsPws57s,866
7
+ easyrip/global_val.py,sha256=AwfM4dmCupM8c_3c1INZ5KUZySFfbpBwVJ_ZOk_P4TI,866
8
8
  easyrip/utils.py,sha256=N1rMF1MyoC-YFBgy10_u29cFoowfhR-5Viea93O7wQ4,8750
9
9
  easyrip/easyrip_config/config.py,sha256=KWXZMEYxdXYUGLQ-MR0A7nnOwR6QZdVrWBopfb2QZSA,9869
10
10
  easyrip/easyrip_config/config_key.py,sha256=_jjdKOunskUoG7UUWOz3QZK-s4LF_x6hmM9MKttyS2Q,766
@@ -16,17 +16,17 @@ easyrip/easyrip_mlang/lang_zh_Hans_CN.py,sha256=OuWg_sNEzNkvlF1EPMFDZrucfQ1Y92zK
16
16
  easyrip/easyrip_mlang/translator.py,sha256=jlgZYSPHvwv1Pps3akKkSgVsGcLtV2psKaXyZH4QCbA,5870
17
17
  easyrip/easyrip_web/__init__.py,sha256=tMyEeaSGeEJjND7MF0MBv9aDiDgaO3MOnppwxA70U2c,177
18
18
  easyrip/easyrip_web/http_server.py,sha256=iyulCAFQrJlz86Lrr-Dm3fhOnNCf79Bp6fVHhr0ephY,8350
19
- easyrip/easyrip_web/third_party_api.py,sha256=E-60yoY6D0pPUfYW1VIh0763htyV5z6getzlLtLAdQc,4624
19
+ easyrip/easyrip_web/third_party_api.py,sha256=JJSkhqc1HGk2VFd90uH8bfOw0TxHOanMNp4jhhtk94s,5165
20
20
  easyrip/ripper/media_info.py,sha256=KdSodS6nIp2BWEer5y4mD5xwyhP15_PgNRhz2fnHmw0,5082
21
21
  easyrip/ripper/param.py,sha256=PfJzJz9LPCB5hAM9G4GjPxdn_EZRgAz-vxYzuHGQLp8,13084
22
- easyrip/ripper/ripper.py,sha256=qppP5D-4e4LYKemlsOvq8wTJwYBlPhEo7k2nhwKSQEs,60501
22
+ easyrip/ripper/ripper.py,sha256=h2jZaysF8r8UB5jEJRA1gqS-L6N_IpsDvtBlEToRgYY,59555
23
23
  easyrip/ripper/sub_and_font/__init__.py,sha256=cBT7mxL7RRFaJXFPXuZ7RT-YK6FbnanaU5v6U9BOquw,153
24
24
  easyrip/ripper/sub_and_font/ass.py,sha256=EhDkVY5JXU77euWPId7H2v85j444m8ZLm7wUid7TYd8,35307
25
25
  easyrip/ripper/sub_and_font/font.py,sha256=X2dPcPzbwQf3fv_g_mxO-zY7puVAX9Nv-9QHn88q4oA,7745
26
26
  easyrip/ripper/sub_and_font/subset.py,sha256=--rAA3VH1rm_jBOC3yMs3rOJpn3tPuvfXqkimbBtx3s,18653
27
- easyrip-4.15.2.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
28
- easyrip-4.15.2.dist-info/METADATA,sha256=vaOTNo3-DbhZBoHbfyfPnrcvR_C0qdl1j94LwGRu63Y,4061
29
- easyrip-4.15.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
30
- easyrip-4.15.2.dist-info/entry_points.txt,sha256=D6GBMMTzZ-apgX76KyZ6jxMmIFqGYwU9neeLLni_qKI,49
31
- easyrip-4.15.2.dist-info/top_level.txt,sha256=kuEteBXm-Gf90jRQgH3-fTo-Z-Q6czSuUEqY158H4Ww,8
32
- easyrip-4.15.2.dist-info/RECORD,,
27
+ easyrip-4.16.0.dist-info/licenses/LICENSE,sha256=hIahDEOTzuHCU5J2nd07LWwkLW7Hko4UFO__ffsvB-8,34523
28
+ easyrip-4.16.0.dist-info/METADATA,sha256=IIR3XuhVQT62DjdPWwz-oe6MRx9sX8eF0OUwXHu0xgo,4061
29
+ easyrip-4.16.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
30
+ easyrip-4.16.0.dist-info/entry_points.txt,sha256=D6GBMMTzZ-apgX76KyZ6jxMmIFqGYwU9neeLLni_qKI,49
31
+ easyrip-4.16.0.dist-info/top_level.txt,sha256=kuEteBXm-Gf90jRQgH3-fTo-Z-Q6czSuUEqY158H4Ww,8
32
+ easyrip-4.16.0.dist-info/RECORD,,