diff --git a/copyparty/th_cli.py b/copyparty/th_cli.py index 33bc43b8..5496ad47 100644 --- a/copyparty/th_cli.py +++ b/copyparty/th_cli.py @@ -75,7 +75,7 @@ class ThumbCli(object): preferred = self.args.th_dec[0] if self.args.th_dec else "" - if rem.startswith(".hist/th/") and rem.split(".")[-1] in ["webp", "jpg"]: + if rem.startswith(".hist/th/") and rem.split(".")[-1] in ["webp", "jpg", "png"]: return os.path.join(ptop, rem) if fmt == "j" and self.args.th_no_jpg: diff --git a/copyparty/th_srv.py b/copyparty/th_srv.py index 2585a517..8fb7e6e9 100644 --- a/copyparty/th_srv.py +++ b/copyparty/th_srv.py @@ -14,7 +14,7 @@ from queue import Queue from .__init__ import TYPE_CHECKING from .bos import bos from .mtag import HAVE_FFMPEG, HAVE_FFPROBE, ffprobe -from .util import BytesIO, Cooldown, fsenc, min_ex, runcmd, statdir, vsplit +from .util import BytesIO, Cooldown, Pebkac, fsenc, min_ex, runcmd, statdir, vsplit try: from typing import Optional, Union @@ -82,7 +82,7 @@ def thumb_path(histpath: str, rem: str, mtime: float, fmt: str) -> str: if fmt in ("opus", "caf"): cat = "ac" else: - fmt = "webp" if fmt == "w" else "jpg" + fmt = "webp" if fmt == "w" else "png" if fmt == "p" else "jpg" cat = "th" return "{}/{}/{}/{}.{:x}.{}".format(histpath, cat, rd, fn, int(mtime), fmt) @@ -239,6 +239,7 @@ class ThumbSrv(object): abspath, tpath = task ext = abspath.split(".")[-1].lower() + png_ok = False fun = None if not bos.path.exists(tpath): for lib in self.args.th_dec: @@ -253,9 +254,15 @@ class ThumbSrv(object): elif lib == "ff" and ext in self.fmt_ffa: if tpath.endswith(".opus") or tpath.endswith(".caf"): fun = self.conv_opus + elif tpath.endswith(".png"): + fun = self.conv_waves + png_ok = True else: fun = self.conv_spec + if not png_ok and tpath.endswith(".png"): + raise Pebkac(400, "png only allowed for waveforms") + if fun: try: fun(abspath, tpath) @@ -439,6 +446,37 @@ class ThumbSrv(object): self.log(t + txt, c=c) raise sp.CalledProcessError(ret, (cmd[0], b"...", cmd[-1])) + def conv_waves(self, abspath: str, tpath: str) -> None: + ret, _ = ffprobe(abspath, int(self.args.th_convt / 2)) + if "ac" not in ret: + raise Exception("not audio") + + flt = ( + b"[0:a:0]" + b"compand=.3|.3:1|1:-90/-60|-60/-40|-40/-30|-20/-20:6:0:-90:0.2" + b",volume=2" + b",showwavespic=s=2048x64:colors=white" + b",convolution=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:0 -1 0 -1 5 -1 0 -1 0" # idk what im doing but it looks ok + b",unsharp=7:7:5" + b"[o]" + ) + + # fmt: off + cmd = [ + b"ffmpeg", + b"-nostdin", + b"-v", b"error", + b"-hide_banner", + b"-i", fsenc(abspath), + b"-filter_complex", flt, + b"-map", b"[o]", + b"-frames:v", b"1", + ] + # fmt: on + + cmd += [fsenc(tpath)] + self._run_ff(cmd) + def conv_spec(self, abspath: str, tpath: str) -> None: ret, _ = ffprobe(abspath, int(self.args.th_convt / 2)) if "ac" not in ret: @@ -462,6 +500,7 @@ class ThumbSrv(object): b"-i", fsenc(abspath), b"-filter_complex", fc.encode("utf-8"), b"-map", b"[o]" + b"-frames:v", b"1", ] # fmt: on diff --git a/copyparty/web/browser.css b/copyparty/web/browser.css index ea4c2086..f2eb5d0f 100644 --- a/copyparty/web/browser.css +++ b/copyparty/web/browser.css @@ -246,6 +246,7 @@ html.b { --u2-o-1h-bg: var(--a-hil); --f-sh1: 0.1; + --mp-b-bg: transparent; } html.bz { --fg: #cce; @@ -278,6 +279,7 @@ html.bz { --f-h-b1: #34384e; --mp-sh: #11121d; + /*--mp-b-bg: #2c3044;*/ } html.by { --bg: #f2f2f2; @@ -321,6 +323,7 @@ html.c { --u2-o-1-bg: #4cf; --srv-1: #ea0; + --mp-b-bg: transparent; } html.cz { --bgg: var(--bg-u2); @@ -470,7 +473,6 @@ html.dz { --fm-off: #f6c; --mp-sh: var(--bg-d3); - --mp-b-bg: rgba(0,0,0,0.2); --err-fg: #fff; --err-bg: #a20; @@ -2741,7 +2743,6 @@ html.b #barpos, html.b #barbuf, html.b #pvol { border-radius: .2em; - background: none; } html.b #barpos { box-shadow: 0 0 0 1px rgba(0,0,0,0.4); diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js index 35aec9c5..2804c1a0 100644 --- a/copyparty/web/browser.js +++ b/copyparty/web/browser.js @@ -144,6 +144,7 @@ var Ls = { "mt_preload": "start loading the next song near the end for gapless playback\">preload", "mt_fullpre": "try to preload the entire song;$N✅ enable on unreliable connections,$N❌ disable on slow connections probably\">full", + "mt_waves": "waveform seekbar:$Nshow audio amplitude in the scrubber\">~s", "mt_npclip": "show buttons for clipboarding the currently playing song\">/np", "mt_octl": "os integration (media hotkeys / osd)\">os-ctl", "mt_oseek": "allow seeking through os integration\">seek", @@ -497,6 +498,7 @@ var Ls = { "mt_preload": "hent ned litt av neste sang i forkant,$Nslik at pausen i overgangen blir mindre\">forles", "mt_fullpre": "hent ned hele neste sang, ikke bare litt:$N✅ skru på hvis nettet ditt er ustabilt,$N❌ skru av hvis nettet ditt er tregt\">full", + "mt_waves": "waveform seekbar:$Nvis volumkart i avspillingsindikatoren\">~s", "mt_npclip": "vis knapper for å kopiere info om sangen du hører på\">/np", "mt_octl": "integrering med operativsystemet (fjernkontroll, info-skjerm)\">os-ctl", "mt_oseek": "tillat spoling med fjernkontroll\">spoling", @@ -1057,6 +1059,7 @@ var mpl = (function () { '