mirror of
https://github.com/9001/copyparty.git
synced 2025-08-18 01:22:13 -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 ""
|
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)
|
return os.path.join(ptop, rem)
|
||||||
|
|
||||||
if fmt == "j" and self.args.th_no_jpg:
|
if fmt == "j" and self.args.th_no_jpg:
|
||||||
|
|
|
@ -14,7 +14,7 @@ from queue import Queue
|
||||||
from .__init__ import TYPE_CHECKING
|
from .__init__ import TYPE_CHECKING
|
||||||
from .bos import bos
|
from .bos import bos
|
||||||
from .mtag import HAVE_FFMPEG, HAVE_FFPROBE, ffprobe
|
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:
|
try:
|
||||||
from typing import Optional, Union
|
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"):
|
if fmt in ("opus", "caf"):
|
||||||
cat = "ac"
|
cat = "ac"
|
||||||
else:
|
else:
|
||||||
fmt = "webp" if fmt == "w" else "jpg"
|
fmt = "webp" if fmt == "w" else "png" if fmt == "p" else "jpg"
|
||||||
cat = "th"
|
cat = "th"
|
||||||
|
|
||||||
return "{}/{}/{}/{}.{:x}.{}".format(histpath, cat, rd, fn, int(mtime), fmt)
|
return "{}/{}/{}/{}.{:x}.{}".format(histpath, cat, rd, fn, int(mtime), fmt)
|
||||||
|
@ -239,6 +239,7 @@ class ThumbSrv(object):
|
||||||
|
|
||||||
abspath, tpath = task
|
abspath, tpath = task
|
||||||
ext = abspath.split(".")[-1].lower()
|
ext = abspath.split(".")[-1].lower()
|
||||||
|
png_ok = False
|
||||||
fun = None
|
fun = None
|
||||||
if not bos.path.exists(tpath):
|
if not bos.path.exists(tpath):
|
||||||
for lib in self.args.th_dec:
|
for lib in self.args.th_dec:
|
||||||
|
@ -253,9 +254,15 @@ class ThumbSrv(object):
|
||||||
elif lib == "ff" and ext in self.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
|
||||||
|
elif tpath.endswith(".png"):
|
||||||
|
fun = self.conv_waves
|
||||||
|
png_ok = True
|
||||||
else:
|
else:
|
||||||
fun = self.conv_spec
|
fun = self.conv_spec
|
||||||
|
|
||||||
|
if not png_ok and tpath.endswith(".png"):
|
||||||
|
raise Pebkac(400, "png only allowed for waveforms")
|
||||||
|
|
||||||
if fun:
|
if fun:
|
||||||
try:
|
try:
|
||||||
fun(abspath, tpath)
|
fun(abspath, tpath)
|
||||||
|
@ -439,6 +446,37 @@ class ThumbSrv(object):
|
||||||
self.log(t + txt, c=c)
|
self.log(t + txt, c=c)
|
||||||
raise sp.CalledProcessError(ret, (cmd[0], b"...", cmd[-1]))
|
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:
|
def conv_spec(self, abspath: str, tpath: str) -> None:
|
||||||
ret, _ = ffprobe(abspath, int(self.args.th_convt / 2))
|
ret, _ = ffprobe(abspath, int(self.args.th_convt / 2))
|
||||||
if "ac" not in ret:
|
if "ac" not in ret:
|
||||||
|
@ -462,6 +500,7 @@ class ThumbSrv(object):
|
||||||
b"-i", fsenc(abspath),
|
b"-i", fsenc(abspath),
|
||||||
b"-filter_complex", fc.encode("utf-8"),
|
b"-filter_complex", fc.encode("utf-8"),
|
||||||
b"-map", b"[o]"
|
b"-map", b"[o]"
|
||||||
|
b"-frames:v", b"1",
|
||||||
]
|
]
|
||||||
# fmt: on
|
# fmt: on
|
||||||
|
|
||||||
|
|
|
@ -246,6 +246,7 @@ html.b {
|
||||||
--u2-o-1h-bg: var(--a-hil);
|
--u2-o-1h-bg: var(--a-hil);
|
||||||
|
|
||||||
--f-sh1: 0.1;
|
--f-sh1: 0.1;
|
||||||
|
--mp-b-bg: transparent;
|
||||||
}
|
}
|
||||||
html.bz {
|
html.bz {
|
||||||
--fg: #cce;
|
--fg: #cce;
|
||||||
|
@ -278,6 +279,7 @@ html.bz {
|
||||||
|
|
||||||
--f-h-b1: #34384e;
|
--f-h-b1: #34384e;
|
||||||
--mp-sh: #11121d;
|
--mp-sh: #11121d;
|
||||||
|
/*--mp-b-bg: #2c3044;*/
|
||||||
}
|
}
|
||||||
html.by {
|
html.by {
|
||||||
--bg: #f2f2f2;
|
--bg: #f2f2f2;
|
||||||
|
@ -321,6 +323,7 @@ html.c {
|
||||||
--u2-o-1-bg: #4cf;
|
--u2-o-1-bg: #4cf;
|
||||||
|
|
||||||
--srv-1: #ea0;
|
--srv-1: #ea0;
|
||||||
|
--mp-b-bg: transparent;
|
||||||
}
|
}
|
||||||
html.cz {
|
html.cz {
|
||||||
--bgg: var(--bg-u2);
|
--bgg: var(--bg-u2);
|
||||||
|
@ -470,7 +473,6 @@ html.dz {
|
||||||
|
|
||||||
--fm-off: #f6c;
|
--fm-off: #f6c;
|
||||||
--mp-sh: var(--bg-d3);
|
--mp-sh: var(--bg-d3);
|
||||||
--mp-b-bg: rgba(0,0,0,0.2);
|
|
||||||
|
|
||||||
--err-fg: #fff;
|
--err-fg: #fff;
|
||||||
--err-bg: #a20;
|
--err-bg: #a20;
|
||||||
|
@ -2741,7 +2743,6 @@ html.b #barpos,
|
||||||
html.b #barbuf,
|
html.b #barbuf,
|
||||||
html.b #pvol {
|
html.b #pvol {
|
||||||
border-radius: .2em;
|
border-radius: .2em;
|
||||||
background: none;
|
|
||||||
}
|
}
|
||||||
html.b #barpos {
|
html.b #barpos {
|
||||||
box-shadow: 0 0 0 1px rgba(0,0,0,0.4);
|
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_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_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_npclip": "show buttons for clipboarding the currently playing song\">/np",
|
||||||
"mt_octl": "os integration (media hotkeys / osd)\">os-ctl",
|
"mt_octl": "os integration (media hotkeys / osd)\">os-ctl",
|
||||||
"mt_oseek": "allow seeking through os integration\">seek",
|
"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_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_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_npclip": "vis knapper for å kopiere info om sangen du hører på\">/np",
|
||||||
"mt_octl": "integrering med operativsystemet (fjernkontroll, info-skjerm)\">os-ctl",
|
"mt_octl": "integrering med operativsystemet (fjernkontroll, info-skjerm)\">os-ctl",
|
||||||
"mt_oseek": "tillat spoling med fjernkontroll\">spoling",
|
"mt_oseek": "tillat spoling med fjernkontroll\">spoling",
|
||||||
|
@ -1057,6 +1059,7 @@ var mpl = (function () {
|
||||||
'<div><h3>' + L.cl_opts + '</h3><div>' +
|
'<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_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_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_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_ctl" tt="' + L.mt_octl + '</a>' +
|
||||||
'<a href="#" class="tgl btn" id="au_os_seek" tt="' + L.mt_oseek + '</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, 'preload', 'au_preload', true);
|
||||||
bcfg_bind(r, 'fullpre', 'au_fullpre', false);
|
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, 'os_seek', 'au_os_seek', !IPHONE, announce);
|
||||||
bcfg_bind(r, 'osd_cv', 'au_osd_cv', true, announce);
|
bcfg_bind(r, 'osd_cv', 'au_osd_cv', true, announce);
|
||||||
bcfg_bind(r, 'clip', 'au_npclip', false, function (v) {
|
bcfg_bind(r, 'clip', 'au_npclip', false, function (v) {
|
||||||
|
@ -1369,6 +1375,12 @@ function MPlayer() {
|
||||||
url += (url.indexOf('?') < 0 ? '?' : '&') + 'cache=987';
|
url += (url.indexOf('?') < 0 ? '?' : '&') + 'cache=987';
|
||||||
mpl.preload_url = full ? url : null;
|
mpl.preload_url = full ? url : null;
|
||||||
var t0 = Date.now();
|
var t0 = Date.now();
|
||||||
|
|
||||||
|
if (mpl.waves)
|
||||||
|
fetch(url + '&th=p').then(function (x) {
|
||||||
|
x.body.getReader().read();
|
||||||
|
});
|
||||||
|
|
||||||
if (full)
|
if (full)
|
||||||
return fetch(url).then(function (x) {
|
return fetch(url).then(function (x) {
|
||||||
var rd = x.body.getReader(), n = 0;
|
var rd = x.body.getReader(), n = 0;
|
||||||
|
@ -1562,6 +1574,20 @@ var pbar = (function () {
|
||||||
r.pos = canvas_cfg(ebi('barpos'));
|
r.pos = canvas_cfg(ebi('barpos'));
|
||||||
r.drawbuf();
|
r.drawbuf();
|
||||||
r.drawpos();
|
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 () {
|
r.drawbuf = function () {
|
||||||
|
@ -1591,6 +1617,13 @@ var pbar = (function () {
|
||||||
|
|
||||||
bctx.fillRect(x1, 0, x2 - x1, bc.h);
|
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 () {
|
r.drawpos = function () {
|
||||||
|
@ -2358,6 +2391,10 @@ function play(tid, is_ev, seek) {
|
||||||
o.setAttribute('id', oid);
|
o.setAttribute('id', oid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pbar.unwave();
|
||||||
|
if (mpl.waves)
|
||||||
|
pbar.loadwaves(url + '&th=p');
|
||||||
|
|
||||||
mpui.progress_updater();
|
mpui.progress_updater();
|
||||||
pbar.onresize();
|
pbar.onresize();
|
||||||
vbar.onresize();
|
vbar.onresize();
|
||||||
|
|
Loading…
Reference in a new issue