add waveform seekbar

This commit is contained in:
ed 2022-09-17 23:40:37 +02:00
parent fad1449259
commit 6bec4c28ba
4 changed files with 82 additions and 5 deletions

View file

@ -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:

View file

@ -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

View file

@ -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);

View file

@ -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();