thumbnails: per-decoder filetype config

This commit is contained in:
ed 2022-04-10 22:59:45 +02:00
parent b64cabc3c9
commit cc4a063695
4 changed files with 52 additions and 46 deletions

View file

@ -509,6 +509,13 @@ def run_argparse(argv, formatter):
ap2.add_argument("--th-clean", metavar="SEC", type=int, default=43200, help="cleanup interval; 0=disabled") ap2.add_argument("--th-clean", metavar="SEC", type=int, default=43200, help="cleanup interval; 0=disabled")
ap2.add_argument("--th-maxage", metavar="SEC", type=int, default=604800, help="max folder age") ap2.add_argument("--th-maxage", metavar="SEC", type=int, default=604800, help="max folder age")
ap2.add_argument("--th-covers", metavar="N,N", type=u, default="folder.png,folder.jpg,cover.png,cover.jpg", help="folder thumbnails to stat for") ap2.add_argument("--th-covers", metavar="N,N", type=u, default="folder.png,folder.jpg,cover.png,cover.jpg", help="folder thumbnails to stat for")
# https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html
# https://github.com/libvips/libvips
# ffmpeg -formats
ap2.add_argument("--th-r-pil", metavar="T,T", type=u, default="bmp,dib,gif,icns,ico,jpg,jpeg,jp2,jpx,pcx,png,pbm,pgm,ppm,pnm,sgi,tga,tif,tiff,webp,xbm,dds,xpm,heif,heifs,heic,heics,avif,avifs", help="image formats to decode using pillow")
ap2.add_argument("--th-r-vips", metavar="T,T", type=u, default="jpg,jpeg,jp2,jpx,jxl,tif,tiff,png,webp,heic,avif,fit,fits,fts,exr,pdf,svg,hdr,ppm,pgm,pfm,gif,nii,dzi", help="image formats to decode using pyvips")
ap2.add_argument("--th-r-ffv", metavar="T,T", type=u, default="av1,asf,avi,flv,m4v,mkv,mjpeg,mjpg,mpg,mpeg,mpg2,mpeg2,h264,avc,mts,h265,hevc,mov,3gp,mp4,ts,mpegts,nut,ogv,ogm,rm,vob,webm,wmv", help="video formats to decode using ffmpeg")
ap2.add_argument("--th-r-ffa", metavar="T,T", type=u, default="aac,m4a,ogg,opus,flac,alac,mp3,mp2,ac3,dts,wma,ra,wav,aif,aiff,au,alaw,ulaw,mulaw,amr,gsm,ape,tak,tta,wv,mpc", help="audio formats to decode using ffmpeg")
ap2 = ap.add_argument_group('transcoding options') ap2 = ap.add_argument_group('transcoding options')
ap2.add_argument("--no-acode", action="store_true", help="disable audio transcoding") ap2.add_argument("--no-acode", action="store_true", help="disable audio transcoding")

View file

@ -70,6 +70,9 @@ class HttpSrv(object):
self.cb_ts = 0 self.cb_ts = 0
self.cb_v = 0 self.cb_v = 0
x = self.broker.put(True, "thumbsrv.getcfg")
self.th_cfg = x.get()
env = jinja2.Environment() env = jinja2.Environment()
env.loader = jinja2.FileSystemLoader(os.path.join(E.mod, "web")) env.loader = jinja2.FileSystemLoader(os.path.join(E.mod, "web"))
self.j2 = { self.j2 = {

View file

@ -4,7 +4,7 @@ from __future__ import print_function, unicode_literals
import os import os
from .util import Cooldown from .util import Cooldown
from .th_srv import thumb_path, THUMBABLE, FMT_FFV, FMT_FFA, HAVE_WEBP from .th_srv import thumb_path, HAVE_WEBP
from .bos import bos from .bos import bos
@ -18,6 +18,13 @@ class ThumbCli(object):
# cache on both sides for less broker spam # cache on both sides for less broker spam
self.cooldown = Cooldown(self.args.th_poke) self.cooldown = Cooldown(self.args.th_poke)
c = hsrv.th_cfg
self.thumbable = c["thumbable"]
self.fmt_pil = c["pil"]
self.fmt_vips = c["vips"]
self.fmt_ffv = c["ffv"]
self.fmt_ffa = c["ffa"]
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"
@ -26,15 +33,15 @@ class ThumbCli(object):
def get(self, ptop, rem, mtime, fmt): def get(self, ptop, rem, mtime, fmt):
ext = rem.rsplit(".")[-1].lower() ext = rem.rsplit(".")[-1].lower()
if ext not in THUMBABLE: if ext not in self.thumbable:
return None return None
is_vid = ext in FMT_FFV is_vid = ext in self.fmt_ffv
if is_vid and self.args.no_vthumb: if is_vid and self.args.no_vthumb:
return None return None
want_opus = fmt in ("opus", "caf") want_opus = fmt in ("opus", "caf")
is_au = ext in FMT_FFA is_au = ext in self.fmt_ffa
if is_au: if is_au:
if want_opus: if want_opus:
if self.args.no_acode: if self.args.no_acode:

View file

@ -54,37 +54,6 @@ try:
except: except:
HAVE_VIPS = False HAVE_VIPS = False
# https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html
# https://github.com/libvips/libvips
# ffmpeg -formats
FMT_PIL = "bmp dib gif icns ico jpg jpeg jp2 jpx pcx png pbm pgm ppm pnm sgi tga tif tiff webp xbm dds xpm"
FMT_VIPS = "jpg jpeg jp2 jpx jxl tif tiff png webp heic avif fit fits fts exr pdf svg hdr ppm pgm pfm gif nii dzi"
FMT_FFV = "av1 asf avi flv m4v mkv mjpeg mjpg mpg mpeg mpg2 mpeg2 h264 avc mts h265 hevc mov 3gp mp4 ts mpegts nut ogv ogm rm vob webm wmv"
FMT_FFA = "aac m4a ogg opus flac alac mp3 mp2 ac3 dts wma ra wav aif aiff au alaw ulaw mulaw amr gsm ape tak tta wv mpc"
if HAVE_HEIF:
FMT_PIL += " heif heifs heic heics"
if HAVE_AVIF:
FMT_PIL += " avif avifs"
FMT_PIL, FMT_VIPS, FMT_FFV, FMT_FFA = [
{x: True for x in y.split(" ") if x} for y in [FMT_PIL, FMT_VIPS, FMT_FFV, FMT_FFA]
]
THUMBABLE = {}
if HAVE_PIL:
THUMBABLE.update(FMT_PIL)
if HAVE_FFMPEG and HAVE_FFPROBE:
THUMBABLE.update(FMT_FFV)
THUMBABLE.update(FMT_FFA)
if HAVE_VIPS:
THUMBABLE.update(FMT_VIPS)
def thumb_path(histpath, rem, mtime, fmt): def thumb_path(histpath, rem, mtime, fmt):
# base16 = 16 = 256 # base16 = 16 = 256
@ -113,8 +82,6 @@ def thumb_path(histpath, rem, mtime, fmt):
class ThumbSrv(object): class ThumbSrv(object):
def __init__(self, hub): def __init__(self, hub):
global THUMBABLE
self.hub = hub self.hub = hub
self.asrv = hub.asrv self.asrv = hub.asrv
self.args = hub.args self.args = hub.args
@ -155,17 +122,30 @@ class ThumbSrv(object):
t.daemon = True t.daemon = True
t.start() t.start()
THUMBABLE = {} self.fmt_pil = {x: True for x in self.args.th_r_pil.split(",")}
self.fmt_vips = {x: True for x in self.args.th_r_vips.split(",")}
self.fmt_ffv = {x: True for x in self.args.th_r_ffv.split(",")}
self.fmt_ffa = {x: True for x in self.args.th_r_ffa.split(",")}
if not HAVE_HEIF:
for f in "heif heifs heic heics".split(" "):
self.fmt_pil.pop(f, None)
if not HAVE_AVIF:
for f in "avif avifs".split(" "):
self.fmt_pil.pop(f, None)
self.thumbable = {}
if "pil" in self.args.th_dec: if "pil" in self.args.th_dec:
THUMBABLE.update(FMT_PIL) self.thumbable.update(self.fmt_pil)
if "vips" in self.args.th_dec: if "vips" in self.args.th_dec:
THUMBABLE.update(FMT_VIPS) self.thumbable.update(self.fmt_vips)
if "ff" in self.args.th_dec: if "ff" in self.args.th_dec:
THUMBABLE.update(FMT_FFV) self.thumbable.update(self.fmt_ffv)
THUMBABLE.update(FMT_FFA) self.thumbable.update(self.fmt_ffa)
def log(self, msg, c=0): def log(self, msg, c=0):
self.log_func("thumb", msg, c) self.log_func("thumb", msg, c)
@ -227,6 +207,15 @@ class ThumbSrv(object):
return None return None
def getcfg(self):
return {
"thumbable": self.thumbable,
"pil": self.fmt_pil,
"vips": self.fmt_vips,
"ffv": self.fmt_ffv,
"ffa": self.fmt_ffa,
}
def worker(self): def worker(self):
while not self.stopping: while not self.stopping:
task = self.q.get() task = self.q.get()
@ -240,13 +229,13 @@ class ThumbSrv(object):
for lib in self.args.th_dec: for lib in self.args.th_dec:
if fun: if fun:
break break
elif lib == "pil" and ext in FMT_PIL: elif lib == "pil" and ext in self.fmt_pil:
fun = self.conv_pil fun = self.conv_pil
elif lib == "vips" and ext in FMT_VIPS: elif lib == "vips" and ext in self.fmt_vips:
fun = self.conv_vips fun = self.conv_vips
elif lib == "ff" and ext in FMT_FFV: elif lib == "ff" and ext in self.fmt_ffv:
fun = self.conv_ffmpeg fun = self.conv_ffmpeg
elif lib == "ff" and ext in FMT_FFA: elif lib == "ff" and ext in self.fmt_ffa:
if tpath.endswith(".opus") or tpath.endswith(".caf"): if tpath.endswith(".opus") or tpath.endswith(".caf"):
fun = self.conv_opus fun = self.conv_opus
else: else: