mirror of
https://github.com/9001/copyparty.git
synced 2026-02-26 05:23:10 -07:00
parent
93ffc65c14
commit
a65a30b1b4
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
for (var a = 0; a < files.length; a++) {
|
for (var a = 0; a < files.length; a++) {
|
||||||
var file = files[a],
|
var file = files[a],
|
||||||
is_pic = /\.(jpe?g|png|gif|webp)$/i.exec(file.vp),
|
is_pic = /\.(jpe?g|png|gif|webp|jxl)$/i.exec(file.vp),
|
||||||
is_audio = re_au_all.exec(file.vp),
|
is_audio = re_au_all.exec(file.vp),
|
||||||
basename = file.vp.replace(/\.[^\.]+$/, ""),
|
basename = file.vp.replace(/\.[^\.]+$/, ""),
|
||||||
entry = pairs[basename];
|
entry = pairs[basename];
|
||||||
|
|
|
||||||
|
|
@ -1668,7 +1668,7 @@ def add_logging(ap):
|
||||||
ap2.add_argument("--log-htp", action="store_true", help="debug: print http-server threadpool scaling")
|
ap2.add_argument("--log-htp", action="store_true", help="debug: print http-server threadpool scaling")
|
||||||
ap2.add_argument("--ihead", metavar="HEADER", type=u, action='append', help="print request \033[33mHEADER\033[0m; [\033[32m*\033[0m]=all")
|
ap2.add_argument("--ihead", metavar="HEADER", type=u, action='append', help="print request \033[33mHEADER\033[0m; [\033[32m*\033[0m]=all")
|
||||||
ap2.add_argument("--ohead", metavar="HEADER", type=u, action='append', help="print response \033[33mHEADER\033[0m; [\033[32m*\033[0m]=all")
|
ap2.add_argument("--ohead", metavar="HEADER", type=u, action='append', help="print response \033[33mHEADER\033[0m; [\033[32m*\033[0m]=all")
|
||||||
ap2.add_argument("--lf-url", metavar="RE", type=u, default=r"^/\.cpr/|[?&]th=[wjp]|/\.(_|ql_|DS_Store$|localized$)", help="dont log URLs matching regex \033[33mRE\033[0m")
|
ap2.add_argument("--lf-url", metavar="RE", type=u, default=r"^/\.cpr/|[?&]th=[xwjp]|/\.(_|ql_|DS_Store$|localized$)", help="dont log URLs matching regex \033[33mRE\033[0m")
|
||||||
ap2.add_argument("--scan-st-r", metavar="SEC", type=float, default=0.1, help="fs-indexing: wait \033[33mSEC\033[0m between each status-message")
|
ap2.add_argument("--scan-st-r", metavar="SEC", type=float, default=0.1, help="fs-indexing: wait \033[33mSEC\033[0m between each status-message")
|
||||||
ap2.add_argument("--scan-pr-r", metavar="SEC", type=float, default=10, help="fs-indexing: wait \033[33mSEC\033[0m between each 'progress:' message")
|
ap2.add_argument("--scan-pr-r", metavar="SEC", type=float, default=10, help="fs-indexing: wait \033[33mSEC\033[0m between each 'progress:' message")
|
||||||
ap2.add_argument("--scan-pr-s", metavar="MiB", type=float, default=1, help="fs-indexing: say 'file: <name>' when a file larger than \033[33mMiB\033[0m is about to be hashed")
|
ap2.add_argument("--scan-pr-s", metavar="MiB", type=float, default=1, help="fs-indexing: say 'file: <name>' when a file larger than \033[33mMiB\033[0m is about to be hashed")
|
||||||
|
|
@ -1706,6 +1706,7 @@ def add_thumbnail(ap):
|
||||||
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")
|
||||||
|
ap2.add_argument("--th-no-jxl", action="store_true", help="disable jpeg-xl output")
|
||||||
ap2.add_argument("--th-ff-jpg", action="store_true", help="force jpg output for video thumbs (avoids issues on some FFmpeg builds)")
|
ap2.add_argument("--th-ff-jpg", action="store_true", help="force jpg output for video thumbs (avoids issues on some FFmpeg builds)")
|
||||||
ap2.add_argument("--th-ff-swr", action="store_true", help="use swresample instead of soxr for audio thumbs (faster, lower accuracy, avoids issues on some FFmpeg builds)")
|
ap2.add_argument("--th-ff-swr", action="store_true", help="use swresample instead of soxr for audio thumbs (faster, lower accuracy, avoids issues on some FFmpeg builds)")
|
||||||
ap2.add_argument("--th-poke", metavar="SEC", type=int, default=300, help="activity labeling cooldown -- avoids doing keepalive pokes (updating the mtime) on thumbnail folders more often than \033[33mSEC\033[0m seconds")
|
ap2.add_argument("--th-poke", metavar="SEC", type=int, default=300, help="activity labeling cooldown -- avoids doing keepalive pokes (updating the mtime) on thumbnail folders more often than \033[33mSEC\033[0m seconds")
|
||||||
|
|
|
||||||
|
|
@ -95,7 +95,7 @@ def enthumb(
|
||||||
if not thp:
|
if not thp:
|
||||||
raise Exception()
|
raise Exception()
|
||||||
|
|
||||||
ext = "jpg" if fmt == "j" else "webp" if fmt == "w" else fmt
|
ext = "jpg" if fmt == "j" else "webp" if fmt == "w" else "jxl" if fmt == "x" else fmt
|
||||||
sz = bos.path.getsize(thp)
|
sz = bos.path.getsize(thp)
|
||||||
st: os.stat_result = f["st"]
|
st: os.stat_result = f["st"]
|
||||||
ts = st.st_mtime
|
ts = st.st_mtime
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import stat
|
||||||
from .__init__ import TYPE_CHECKING
|
from .__init__ import TYPE_CHECKING
|
||||||
from .authsrv import VFS
|
from .authsrv import VFS
|
||||||
from .bos import bos
|
from .bos import bos
|
||||||
from .th_srv import EXTS_AC, HAVE_WEBP, thumb_path
|
from .th_srv import EXTS_AC, HAVE_WEBP, HAVE_JXL, thumb_path
|
||||||
from .util import Cooldown, Pebkac
|
from .util import Cooldown, Pebkac
|
||||||
|
|
||||||
if True: # pylint: disable=using-constant-test
|
if True: # pylint: disable=using-constant-test
|
||||||
|
|
@ -20,7 +20,7 @@ if TYPE_CHECKING:
|
||||||
|
|
||||||
IOERROR = "reading the file was denied by the server os; either due to filesystem permissions, selinux, apparmor, or similar:\n%r"
|
IOERROR = "reading the file was denied by the server os; either due to filesystem permissions, selinux, apparmor, or similar:\n%r"
|
||||||
|
|
||||||
IMG_EXTS = set(["webp", "jpg", "png"])
|
IMG_EXTS = set(["webp", "jpg", "png", "jxl"])
|
||||||
|
|
||||||
|
|
||||||
class ThumbCli(object):
|
class ThumbCli(object):
|
||||||
|
|
@ -54,6 +54,7 @@ class ThumbCli(object):
|
||||||
# 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)
|
d = next((x for x in self.args.th_dec if x in ("vips", "pil")), None)
|
||||||
self.can_webp = HAVE_WEBP or d == "vips"
|
self.can_webp = HAVE_WEBP or d == "vips"
|
||||||
|
self.can_jxl = HAVE_JXL or d == "vips"
|
||||||
|
|
||||||
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)
|
||||||
|
|
@ -94,7 +95,7 @@ class ThumbCli(object):
|
||||||
if rem.startswith(".hist/th/") and rem.split(".")[-1] in IMG_EXTS:
|
if rem.startswith(".hist/th/") and rem.split(".")[-1] in IMG_EXTS:
|
||||||
return os.path.join(ptop, rem)
|
return os.path.join(ptop, rem)
|
||||||
|
|
||||||
if fmt[:1] in "jw" and fmt != "wav":
|
if fmt[:1] in "jwx" and fmt != "wav":
|
||||||
sfmt = fmt[:1]
|
sfmt = fmt[:1]
|
||||||
|
|
||||||
if sfmt == "j" and self.args.th_no_jpg:
|
if sfmt == "j" and self.args.th_no_jpg:
|
||||||
|
|
@ -108,6 +109,14 @@ class ThumbCli(object):
|
||||||
):
|
):
|
||||||
sfmt = "j"
|
sfmt = "j"
|
||||||
|
|
||||||
|
if sfmt == "x":
|
||||||
|
if (
|
||||||
|
self.args.th_no_jxl
|
||||||
|
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"]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -49,8 +49,9 @@ HAVE_PILF = False
|
||||||
HAVE_HEIF = False
|
HAVE_HEIF = False
|
||||||
HAVE_AVIF = False
|
HAVE_AVIF = False
|
||||||
HAVE_WEBP = False
|
HAVE_WEBP = False
|
||||||
|
HAVE_JXL = False
|
||||||
|
|
||||||
EXTS_TH = set(["jpg", "webp", "png"])
|
EXTS_TH = set(["jpg", "webp", "jxl", "png"])
|
||||||
EXTS_AC = set(["opus", "owa", "caf", "mp3", "flac", "wav"])
|
EXTS_AC = set(["opus", "owa", "caf", "mp3", "flac", "wav"])
|
||||||
EXTS_SPEC_SAFE = set("aif aiff flac mp3 opus wav".split())
|
EXTS_SPEC_SAFE = set("aif aiff flac mp3 opus wav".split())
|
||||||
|
|
||||||
|
|
@ -132,6 +133,20 @@ try:
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
if os.environ.get("PRTY_NO_PIL_JXL"):
|
||||||
|
raise Exception()
|
||||||
|
|
||||||
|
try:
|
||||||
|
import pillow_jxl
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
Image.new("RGB", (2, 2)).save(BytesIO(), format="jxl")
|
||||||
|
HAVE_JXL = True
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if os.environ.get("PRTY_NO_PIL_HEIF"):
|
if os.environ.get("PRTY_NO_PIL_HEIF"):
|
||||||
raise Exception()
|
raise Exception()
|
||||||
|
|
@ -203,7 +218,7 @@ def thumb_path(histpath: str, rem: str, mtime: float, fmt: str, ffa: set[str]) -
|
||||||
|
|
||||||
# spectrograms are never cropped; strip fullsize flag
|
# spectrograms are never cropped; strip fullsize flag
|
||||||
ext = rem.split(".")[-1].lower()
|
ext = rem.split(".")[-1].lower()
|
||||||
if ext in ffa and fmt[:2] in ("wf", "jf"):
|
if ext in ffa and fmt[:2] in ("wf", "jf", "xf"):
|
||||||
fmt = fmt.replace("f", "")
|
fmt = fmt.replace("f", "")
|
||||||
|
|
||||||
dcache = th_dir_cache
|
dcache = th_dir_cache
|
||||||
|
|
@ -225,7 +240,7 @@ def thumb_path(histpath: str, rem: str, mtime: float, fmt: str, ffa: set[str]) -
|
||||||
cat = "ac"
|
cat = "ac"
|
||||||
else:
|
else:
|
||||||
fc = fmt[:1]
|
fc = fmt[:1]
|
||||||
fmt = "webp" if fc == "w" else "png" if fc == "p" else "jpg"
|
fmt = "webp" if fc == "w" else "png" if fc == "p" else "jxl" if fc == "x" else "jpg"
|
||||||
cat = "th"
|
cat = "th"
|
||||||
|
|
||||||
return "%s/%s/%s/%s.%x.%s" % (histpath, cat, rd, fn, int(mtime), fmt)
|
return "%s/%s/%s/%s.%x.%s" % (histpath, cat, rd, fn, int(mtime), fmt)
|
||||||
|
|
@ -304,6 +319,10 @@ class ThumbSrv(object):
|
||||||
for f in "webp".split(" "):
|
for f in "webp".split(" "):
|
||||||
self.fmt_pil.discard(f)
|
self.fmt_pil.discard(f)
|
||||||
|
|
||||||
|
if not HAVE_JXL:
|
||||||
|
for f in "jxl".split(" "):
|
||||||
|
self.fmt_pil.discard(f)
|
||||||
|
|
||||||
self.thumbable: set[str] = set()
|
self.thumbable: set[str] = set()
|
||||||
|
|
||||||
if "pil" in self.args.th_dec:
|
if "pil" in self.args.th_dec:
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ window.baguetteBox = (function () {
|
||||||
touchFlag = false, // busy
|
touchFlag = false, // busy
|
||||||
scrollCSS = ['', ''],
|
scrollCSS = ['', ''],
|
||||||
scrollTimer = 0,
|
scrollTimer = 0,
|
||||||
re_i = /^[^?]+\.(a?png|avif|bmp|gif|heif|jfif|jpe?g|svg|tiff?|webp)(\?|$)/i,
|
re_i = /^[^?]+\.(a?png|avif|bmp|gif|heif|jfif|jpe?g|jxl|svg|tiff?|webp)(\?|$)/i,
|
||||||
re_v = /^[^?]+\.(webm|mkv|mp4|m4v|mov)(\?|$)/i,
|
re_v = /^[^?]+\.(webm|mkv|mp4|m4v|mov)(\?|$)/i,
|
||||||
re_cbz = /^[^?]+\.(cbz)(\?|$)/i,
|
re_cbz = /^[^?]+\.(cbz)(\?|$)/i,
|
||||||
cbz_pics = ["png", "jpg", "jpeg", "gif", "bmp", "tga", "tif", "tiff", "webp", "avif"],
|
cbz_pics = ["png", "jpg", "jpeg", "gif", "bmp", "tga", "tif", "tiff", "webp", "avif"],
|
||||||
|
|
|
||||||
|
|
@ -1154,22 +1154,26 @@ function read_sbw() {
|
||||||
onresize100.add(read_sbw, true);
|
onresize100.add(read_sbw, true);
|
||||||
|
|
||||||
|
|
||||||
var have_webp = sread('have_webp');
|
function check_image_support(format, uri) {
|
||||||
(function () {
|
var cached
|
||||||
if (have_webp !== null)
|
= window['have_' + format]
|
||||||
|
= sread('have_' + format);
|
||||||
|
if (cached !== null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var img = new Image();
|
var img = new Image();
|
||||||
img.onload = function () {
|
img.onload = function () {
|
||||||
have_webp = img.width > 0 && img.height > 0;
|
window['have_' + format] = img.width > 0 && img.height > 0;
|
||||||
swrite('have_webp', 'ya');
|
swrite('have_' + format, 'ya');
|
||||||
};
|
};
|
||||||
img.onerror = function () {
|
img.onerror = function () {
|
||||||
have_webp = false;
|
window['have_' + format] = false;
|
||||||
swrite('have_webp', '');
|
swrite('have_' + format, '');
|
||||||
};
|
};
|
||||||
img.src = "data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==";
|
img.src = uri;
|
||||||
})();
|
}
|
||||||
|
check_image_support('webp', "data:image/webp;base64,UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==");
|
||||||
|
check_image_support('jxl', "data:image/jxl;base64,/woIAAAMABKIAgC4AF3lEgA=");
|
||||||
|
|
||||||
|
|
||||||
function set_files_html(html) {
|
function set_files_html(html) {
|
||||||
|
|
@ -5685,7 +5689,7 @@ var thegrid = (function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
function loadgrid() {
|
function loadgrid() {
|
||||||
if (have_webp === null)
|
if (have_webp === null || have_jxl === null)
|
||||||
return setTimeout(loadgrid, 50);
|
return setTimeout(loadgrid, 50);
|
||||||
|
|
||||||
r.setvis();
|
r.setvis();
|
||||||
|
|
@ -5738,7 +5742,11 @@ var thegrid = (function () {
|
||||||
ihref = ext_th[ext] || ext_th[ext0];
|
ihref = ext_th[ext] || ext_th[ext0];
|
||||||
}
|
}
|
||||||
else if (r.thumbs) {
|
else if (r.thumbs) {
|
||||||
ihref = addq(ihref, 'th=' + (have_webp ? 'w' : 'j'));
|
ihref = addq(ihref, 'th=' + (
|
||||||
|
have_jxl ? 'x' :
|
||||||
|
have_webp ? 'w' :
|
||||||
|
'j'
|
||||||
|
));
|
||||||
if (!r.crop)
|
if (!r.crop)
|
||||||
ihref += 'f';
|
ihref += 'f';
|
||||||
if (r.x3)
|
if (r.x3)
|
||||||
|
|
|
||||||
|
|
@ -1015,7 +1015,7 @@
|
||||||
ohead: set-cooke # hint; default is unset
|
ohead: set-cooke # hint; default is unset
|
||||||
|
|
||||||
# dont log URLs matching regex RE
|
# dont log URLs matching regex RE
|
||||||
lf-url: ^/\.cpr/|[?&]th=[wjp]|/\.(_|ql_|DS_Store$|localized$) # default
|
lf-url: ^/\.cpr/|[?&]th=[xwjp]|/\.(_|ql_|DS_Store$|localized$) # default
|
||||||
|
|
||||||
###000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
###000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\
|
||||||
###// admin panel options \\000000000000000000000000000000000000000000000000000000000000000000\
|
###// admin panel options \\000000000000000000000000000000000000000000000000000000000000000000\
|
||||||
|
|
@ -1091,6 +1091,9 @@
|
||||||
# disable webp output
|
# disable webp output
|
||||||
th-no-webp
|
th-no-webp
|
||||||
|
|
||||||
|
# disable jpeg-xl output
|
||||||
|
th-no-jxl
|
||||||
|
|
||||||
# force jpg output for video thumbs (avoids issues on some FFmpeg builds)
|
# force jpg output for video thumbs (avoids issues on some FFmpeg builds)
|
||||||
th-ff-jpg
|
th-ff-jpg
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue