mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
add waveform seekbar
This commit is contained in:
parent
fad1449259
commit
6bec4c28ba
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 <b>unreliable</b> connections,$N❌ <b>disable</b> 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 <b>ustabilt</b>,$N❌ skru av hvis nettet ditt er <b>tregt</b>\">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 () {
|
|||
'<div><h3>' + L.cl_opts + '</h3><div>' +
|
||||
'<a href="#" class="tgl btn" id="au_preload" tt="' + L.mt_preload + '</a>' +
|
||||
'<a href="#" class="tgl btn" id="au_fullpre" tt="' + L.mt_fullpre + '</a>' +
|
||||
'<a href="#" class="tgl btn" id="au_waves" tt="' + L.mt_waves + '</a>' +
|
||||
'<a href="#" class="tgl btn" id="au_npclip" tt="' + L.mt_npclip + '</a>' +
|
||||
'<a href="#" class="tgl btn" id="au_os_ctl" tt="' + L.mt_octl + '</a>' +
|
||||
'<a href="#" class="tgl btn" id="au_os_seek" tt="' + L.mt_oseek + '</a>' +
|
||||
|
@ -1088,6 +1091,9 @@ var mpl = (function () {
|
|||
};
|
||||
bcfg_bind(r, 'preload', 'au_preload', true);
|
||||
bcfg_bind(r, 'fullpre', 'au_fullpre', false);
|
||||
bcfg_bind(r, 'waves', 'au_waves', true, function (v) {
|
||||
if (!v) pbar.unwave();
|
||||
});
|
||||
bcfg_bind(r, 'os_seek', 'au_os_seek', !IPHONE, announce);
|
||||
bcfg_bind(r, 'osd_cv', 'au_osd_cv', true, announce);
|
||||
bcfg_bind(r, 'clip', 'au_npclip', false, function (v) {
|
||||
|
@ -1369,6 +1375,12 @@ function MPlayer() {
|
|||
url += (url.indexOf('?') < 0 ? '?' : '&') + 'cache=987';
|
||||
mpl.preload_url = full ? url : null;
|
||||
var t0 = Date.now();
|
||||
|
||||
if (mpl.waves)
|
||||
fetch(url + '&th=p').then(function (x) {
|
||||
x.body.getReader().read();
|
||||
});
|
||||
|
||||
if (full)
|
||||
return fetch(url).then(function (x) {
|
||||
var rd = x.body.getReader(), n = 0;
|
||||
|
@ -1562,6 +1574,20 @@ var pbar = (function () {
|
|||
r.pos = canvas_cfg(ebi('barpos'));
|
||||
r.drawbuf();
|
||||
r.drawpos();
|
||||
};
|
||||
|
||||
r.loadwaves = function (url) {
|
||||
r.wurl = url;
|
||||
var img = new Image();
|
||||
img.onload = function () {
|
||||
r.wimg = img;
|
||||
r.onresize();
|
||||
};
|
||||
img.src = url;
|
||||
};
|
||||
|
||||
r.unwave = function () {
|
||||
r.wurl = r.wimg = null;
|
||||
}
|
||||
|
||||
r.drawbuf = function () {
|
||||
|
@ -1591,6 +1617,13 @@ var pbar = (function () {
|
|||
|
||||
bctx.fillRect(x1, 0, x2 - x1, bc.h);
|
||||
}
|
||||
if (r.wimg) {
|
||||
bctx.globalAlpha = 0.6;
|
||||
bctx.filter = light ? '' : 'invert(1)';
|
||||
bctx.drawImage(r.wimg, 0, 0, bc.w, bc.h);
|
||||
bctx.filter = 'invert(0)';
|
||||
bctx.globalAlpha = 1;
|
||||
}
|
||||
};
|
||||
|
||||
r.drawpos = function () {
|
||||
|
@ -2358,6 +2391,10 @@ function play(tid, is_ev, seek) {
|
|||
o.setAttribute('id', oid);
|
||||
}
|
||||
|
||||
pbar.unwave();
|
||||
if (mpl.waves)
|
||||
pbar.loadwaves(url + '&th=p');
|
||||
|
||||
mpui.progress_updater();
|
||||
pbar.onresize();
|
||||
vbar.onresize();
|
||||
|
|
Loading…
Reference in a new issue