mirror of
https://github.com/9001/copyparty.git
synced 2026-02-26 13:33:09 -07:00
jxl-enc: add th-qvx (separate qscale) + misc
This commit is contained in:
parent
fef34b5465
commit
48c1017843
|
|
@ -1706,7 +1706,8 @@ def add_thumbnail(ap):
|
||||||
ap2.add_argument("--th-ram-max", metavar="GB", type=float, default=th_ram, help="max memory usage (GiB) permitted by thumbnailer; not very accurate")
|
ap2.add_argument("--th-ram-max", metavar="GB", type=float, default=th_ram, help="max memory usage (GiB) permitted by thumbnailer; not very accurate")
|
||||||
ap2.add_argument("--th-crop", metavar="TXT", type=u, default="y", help="crop thumbnails to 4:3 or keep dynamic height; client can override in UI unless force. [\033[32my\033[0m]=crop, [\033[32mn\033[0m]=nocrop, [\033[32mfy\033[0m]=force-y, [\033[32mfn\033[0m]=force-n (volflag=crop)")
|
ap2.add_argument("--th-crop", metavar="TXT", type=u, default="y", help="crop thumbnails to 4:3 or keep dynamic height; client can override in UI unless force. [\033[32my\033[0m]=crop, [\033[32mn\033[0m]=nocrop, [\033[32mfy\033[0m]=force-y, [\033[32mfn\033[0m]=force-n (volflag=crop)")
|
||||||
ap2.add_argument("--th-x3", metavar="TXT", type=u, default="n", help="show thumbs at 3x resolution; client can override in UI unless force. [\033[32my\033[0m]=yes, [\033[32mn\033[0m]=no, [\033[32mfy\033[0m]=force-yes, [\033[32mfn\033[0m]=force-no (volflag=th3x)")
|
ap2.add_argument("--th-x3", metavar="TXT", type=u, default="n", help="show thumbs at 3x resolution; client can override in UI unless force. [\033[32my\033[0m]=yes, [\033[32mn\033[0m]=no, [\033[32mfy\033[0m]=force-yes, [\033[32mfn\033[0m]=force-no (volflag=th3x)")
|
||||||
ap2.add_argument("--th-qv", metavar="N", type=int, default=40, help="thumbnail quality (10~90); higher is larger filesize and better quality (volflag=th_qv)")
|
ap2.add_argument("--th-qv", metavar="N", type=int, default=40, help="webp/jpg thumbnail quality (10~90); higher is larger filesize and better quality (volflag=th_qv)")
|
||||||
|
ap2.add_argument("--th-qvx", metavar="N", type=int, default=64, help="jxl thumbnail quality (10~90); higher is larger filesize and better quality (volflag=th_qvx)")
|
||||||
ap2.add_argument("--th-dec", metavar="LIBS", default="vips,pil,raw,ff", help="image decoders, in order of preference")
|
ap2.add_argument("--th-dec", metavar="LIBS", default="vips,pil,raw,ff", help="image decoders, in order of preference")
|
||||||
ap2.add_argument("--th-no-jpg", action="store_true", help="disable jpg output")
|
ap2.add_argument("--th-no-jpg", action="store_true", help="disable jpg output")
|
||||||
ap2.add_argument("--th-no-webp", action="store_true", help="disable webp output")
|
ap2.add_argument("--th-no-webp", action="store_true", help="disable webp output")
|
||||||
|
|
|
||||||
|
|
@ -2449,7 +2449,7 @@ class AuthSrv(object):
|
||||||
if vf not in vol.flags:
|
if vf not in vol.flags:
|
||||||
vol.flags[vf] = getattr(self.args, ga)
|
vol.flags[vf] = getattr(self.args, ga)
|
||||||
|
|
||||||
zs = "forget_ip gid nrand tail_who th_qv th_spec_p u2abort u2ow uid unp_who ups_who zip_who"
|
zs = "forget_ip gid nrand tail_who th_qv th_qvx th_spec_p u2abort u2ow uid unp_who ups_who zip_who"
|
||||||
for k in zs.split():
|
for k in zs.split():
|
||||||
if k in vol.flags:
|
if k in vol.flags:
|
||||||
vol.flags[k] = int(vol.flags[k])
|
vol.flags[k] = int(vol.flags[k])
|
||||||
|
|
|
||||||
|
|
@ -148,6 +148,7 @@ def vf_vmap() -> dict[str, str]:
|
||||||
"tail_who",
|
"tail_who",
|
||||||
"tcolor",
|
"tcolor",
|
||||||
"th_qv",
|
"th_qv",
|
||||||
|
"th_qvx",
|
||||||
"th_spec_p",
|
"th_spec_p",
|
||||||
"txt_eol",
|
"txt_eol",
|
||||||
"unlist",
|
"unlist",
|
||||||
|
|
@ -307,7 +308,8 @@ flagcats = {
|
||||||
"thsize": "thumbnail res; WxH",
|
"thsize": "thumbnail res; WxH",
|
||||||
"crop": "center-cropping (y/n/fy/fn)",
|
"crop": "center-cropping (y/n/fy/fn)",
|
||||||
"th3x": "3x resolution (y/n/fy/fn)",
|
"th3x": "3x resolution (y/n/fy/fn)",
|
||||||
"th_qv=40": "thumbnail quality (10~90)",
|
"th_qv=40": "webp/jpg thumbnail quality (10~90)",
|
||||||
|
"th_qvx=40": "jxl thumbnail quality (10~90)",
|
||||||
"convt": "convert-to-image timeout in seconds",
|
"convt": "convert-to-image timeout in seconds",
|
||||||
"aconvt": "convert-to-audio timeout in seconds",
|
"aconvt": "convert-to-audio timeout in seconds",
|
||||||
"th_spec_p=1": "make spectrograms? 0=never 1=fallback 2=always",
|
"th_spec_p=1": "make spectrograms? 0=never 1=fallback 2=always",
|
||||||
|
|
|
||||||
|
|
@ -52,9 +52,9 @@ class ThumbCli(object):
|
||||||
self.fmt_ffa = c["ffa"]
|
self.fmt_ffa = c["ffa"]
|
||||||
|
|
||||||
# defer args.th_ff_jpg, can change at runtime
|
# defer args.th_ff_jpg, can change at runtime
|
||||||
d = next((x for x in self.args.th_dec if x in ("vips", "pil")), None)
|
nonpil = next((x for x in self.args.th_dec if x in ("vips", "ff")), None)
|
||||||
self.can_webp = HAVE_WEBP or d == "vips"
|
self.can_webp = HAVE_WEBP or nonpil
|
||||||
self.can_jxl = HAVE_JXL or d == "vips"
|
self.can_jxl = HAVE_JXL or nonpil
|
||||||
|
|
||||||
def log(self, msg: str, c: Union[int, str] = 0) -> None:
|
def log(self, msg: str, c: Union[int, str] = 0) -> None:
|
||||||
self.log_func("thumbcli", msg, c)
|
self.log_func("thumbcli", msg, c)
|
||||||
|
|
@ -104,18 +104,14 @@ class ThumbCli(object):
|
||||||
if sfmt == "w":
|
if sfmt == "w":
|
||||||
if (
|
if (
|
||||||
self.args.th_no_webp
|
self.args.th_no_webp
|
||||||
or (is_img and not self.can_webp)
|
or not self.can_webp
|
||||||
or (self.args.th_ff_jpg and (not is_img or preferred == "ff"))
|
or (self.args.th_ff_jpg and (not is_img or preferred == "ff"))
|
||||||
):
|
):
|
||||||
sfmt = "j"
|
sfmt = "j"
|
||||||
|
|
||||||
if sfmt == "x":
|
if sfmt == "x":
|
||||||
if (
|
if self.args.th_no_jxl or not self.can_jxl:
|
||||||
self.args.th_no_jxl
|
sfmt = "w"
|
||||||
or (is_img and not self.can_jxl)
|
|
||||||
or (self.args.th_ff_jpg and (not is_img or preferred == "ff"))
|
|
||||||
):
|
|
||||||
sfmt = "j"
|
|
||||||
|
|
||||||
vf_crop = dbv.flags["crop"]
|
vf_crop = dbv.flags["crop"]
|
||||||
vf_th3x = dbv.flags["th3x"]
|
vf_th3x = dbv.flags["th3x"]
|
||||||
|
|
@ -144,9 +140,12 @@ class ThumbCli(object):
|
||||||
|
|
||||||
tpath = thumb_path(histpath, rem, mtime, fmt, self.fmt_ffa)
|
tpath = thumb_path(histpath, rem, mtime, fmt, self.fmt_ffa)
|
||||||
tpaths = [tpath]
|
tpaths = [tpath]
|
||||||
if fmt[:1] == "w" and fmt != "wav":
|
fmtc = fmt[:1]
|
||||||
|
if fmtc == "w" and fmt != "wav":
|
||||||
# also check for jpg (maybe webp is unavailable)
|
# also check for jpg (maybe webp is unavailable)
|
||||||
tpaths.append(tpath.rsplit(".", 1)[0] + ".jpg")
|
tpaths.append(tpath.rsplit(".", 1)[0] + ".jpg")
|
||||||
|
elif fmtc == "x":
|
||||||
|
tpaths.append(tpath.rsplit(".", 1)[0] + ".webp")
|
||||||
|
|
||||||
ret = None
|
ret = None
|
||||||
abort = False
|
abort = False
|
||||||
|
|
|
||||||
|
|
@ -432,7 +432,7 @@ class ThumbSrv(object):
|
||||||
zs = "th_dec th_no_webp th_no_jpg"
|
zs = "th_dec th_no_webp th_no_jpg"
|
||||||
for zs in zs.split(" "):
|
for zs in zs.split(" "):
|
||||||
ret.append("%s(%s)\n" % (zs, getattr(self.args, zs)))
|
ret.append("%s(%s)\n" % (zs, getattr(self.args, zs)))
|
||||||
zs = "th_qv thsize th_spec_p convt"
|
zs = "th_qv th_qvx thsize th_spec_p convt"
|
||||||
for zs in zs.split(" "):
|
for zs in zs.split(" "):
|
||||||
ret.append("%s(%s)\n" % (zs, vn.flags.get(zs)))
|
ret.append("%s(%s)\n" % (zs, vn.flags.get(zs)))
|
||||||
return "".join(ret)
|
return "".join(ret)
|
||||||
|
|
@ -646,7 +646,8 @@ class ThumbSrv(object):
|
||||||
im.thumbnail(self.getres(vn, fmt))
|
im.thumbnail(self.getres(vn, fmt))
|
||||||
|
|
||||||
fmts = ["RGB", "L"]
|
fmts = ["RGB", "L"]
|
||||||
args = {"quality": vn.flags["th_qv"]}
|
zs = "th_qvx" if tpath.endswith(".jxl") else "th_qv"
|
||||||
|
args = {"quality": vn.flags[zs]}
|
||||||
|
|
||||||
if tpath.endswith(".webp"):
|
if tpath.endswith(".webp"):
|
||||||
# quality 80 = pillow-default
|
# quality 80 = pillow-default
|
||||||
|
|
@ -697,6 +698,10 @@ class ThumbSrv(object):
|
||||||
if tpath.endswith("jpg"):
|
if tpath.endswith("jpg"):
|
||||||
qv = VIPS_JPG_Q[qv // 5]
|
qv = VIPS_JPG_Q[qv // 5]
|
||||||
args["optimize_coding"] = True
|
args["optimize_coding"] = True
|
||||||
|
elif tpath.endswith("jxl"):
|
||||||
|
qv = vn.flags["th_qvx"]
|
||||||
|
# args["effort"] = 8
|
||||||
|
# `- not worth it; twice as slow, size drops 12%, no visual improvement unlike ffmpeg
|
||||||
img.write_to_file(tpath, Q=qv, strip=True, **args)
|
img.write_to_file(tpath, Q=qv, strip=True, **args)
|
||||||
img.invalidate()
|
img.invalidate()
|
||||||
|
|
||||||
|
|
@ -787,11 +792,21 @@ class ThumbSrv(object):
|
||||||
]
|
]
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
|
self._ffmpeg_im_o(tpath, vn, cmd)
|
||||||
|
|
||||||
|
def _ffmpeg_im_o(self, tpath: str, vn: VFS, cmd: list[bytes]) -> None:
|
||||||
if tpath.endswith(".jpg"):
|
if tpath.endswith(".jpg"):
|
||||||
cmd += [
|
cmd += [
|
||||||
b"-q:v",
|
b"-q:v",
|
||||||
FF_JPG_Q[vn.flags["th_qv"] // 5], # default=??
|
FF_JPG_Q[vn.flags["th_qv"] // 5], # default=??
|
||||||
]
|
]
|
||||||
|
elif tpath.endswith(".jxl"):
|
||||||
|
cmd += [
|
||||||
|
b"-q:v",
|
||||||
|
unicode(vn.flags["th_qvx"]).encode("ascii"), # default=??
|
||||||
|
b"-effort:v",
|
||||||
|
b"8", # default=7, 1=fast, 9=max, 9~=8 but slower
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
cmd += [
|
cmd += [
|
||||||
b"-q:v",
|
b"-q:v",
|
||||||
|
|
@ -996,21 +1011,7 @@ class ThumbSrv(object):
|
||||||
]
|
]
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
if tpath.endswith(".jpg"):
|
self._ffmpeg_im_o(tpath, vn, cmd)
|
||||||
cmd += [
|
|
||||||
b"-q:v",
|
|
||||||
FF_JPG_Q[vn.flags["th_qv"] // 5], # default=??
|
|
||||||
]
|
|
||||||
else:
|
|
||||||
cmd += [
|
|
||||||
b"-q:v",
|
|
||||||
unicode(vn.flags["th_qv"]).encode("ascii"), # default=75
|
|
||||||
b"-compression_level:v",
|
|
||||||
b"6", # default=4, 0=fast, 6=max
|
|
||||||
]
|
|
||||||
|
|
||||||
cmd += [fsenc(tpath)]
|
|
||||||
self._run_ff(cmd, vn, "convt")
|
|
||||||
|
|
||||||
def conv_mp3(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
def conv_mp3(self, abspath: str, tpath: str, fmt: str, vn: VFS) -> None:
|
||||||
quality = self.args.q_mp3.lower()
|
quality = self.args.q_mp3.lower()
|
||||||
|
|
|
||||||
|
|
@ -158,7 +158,7 @@ class Cfg(Namespace):
|
||||||
ex = "hash_mt hsortn qdel safe_dedup scan_pr_r scan_pr_s scan_st_r srch_time tail_fd tail_rate th_spec_p u2abort u2j u2sz unp_who"
|
ex = "hash_mt hsortn qdel safe_dedup scan_pr_r scan_pr_s scan_st_r srch_time tail_fd tail_rate th_spec_p u2abort u2j u2sz unp_who"
|
||||||
ka.update(**{k: 1 for k in ex.split()})
|
ka.update(**{k: 1 for k in ex.split()})
|
||||||
|
|
||||||
ex = "ac_convt au_vol dl_list du_iwho mtab_age reg_cap s_thead s_tbody tail_tmax tail_who th_convt th_qv ups_who ver_iwho zip_who"
|
ex = "ac_convt au_vol dl_list du_iwho mtab_age reg_cap s_thead s_tbody tail_tmax tail_who th_convt th_qv th_qvx ups_who ver_iwho zip_who"
|
||||||
ka.update(**{k: 9 for k in ex.split()})
|
ka.update(**{k: 9 for k in ex.split()})
|
||||||
|
|
||||||
ex = "ctl_re db_act forget_ip idp_cookie idp_store k304 loris no304 nosubtle qr_pin qr_wait re_maxage rproxy rsp_jtr rsp_slp s_wr_slp snap_wri theme themes turbo u2ow zipmaxn zipmaxs"
|
ex = "ctl_re db_act forget_ip idp_cookie idp_store k304 loris no304 nosubtle qr_pin qr_wait re_maxage rproxy rsp_jtr rsp_slp s_wr_slp snap_wri theme themes turbo u2ow zipmaxn zipmaxs"
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue