mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
ui option to play video as audio
audio extraction happens serverside to opus or mp3 depending on browser support remuxing (extracting audio without transcoding) is currently not supported, and is not planned
This commit is contained in:
parent
eeef80919f
commit
53f1e3c91d
|
@ -225,6 +225,7 @@ also see [comparison to similar software](./docs/versus.md)
|
||||||
* ☑ [navpane](#navpane) (directory tree sidebar)
|
* ☑ [navpane](#navpane) (directory tree sidebar)
|
||||||
* ☑ file manager (cut/paste, delete, [batch-rename](#batch-rename))
|
* ☑ file manager (cut/paste, delete, [batch-rename](#batch-rename))
|
||||||
* ☑ audio player (with [OS media controls](https://user-images.githubusercontent.com/241032/215347492-b4250797-6c90-4e09-9a4c-721edf2fb15c.png) and opus/mp3 transcoding)
|
* ☑ audio player (with [OS media controls](https://user-images.githubusercontent.com/241032/215347492-b4250797-6c90-4e09-9a4c-721edf2fb15c.png) and opus/mp3 transcoding)
|
||||||
|
* ☑ play video files as audio (converted on server)
|
||||||
* ☑ image gallery with webm player
|
* ☑ image gallery with webm player
|
||||||
* ☑ textfile browser with syntax hilighting
|
* ☑ textfile browser with syntax hilighting
|
||||||
* ☑ [thumbnails](#thumbnails)
|
* ☑ [thumbnails](#thumbnails)
|
||||||
|
@ -801,6 +802,7 @@ some hilights:
|
||||||
* OS integration; control playback from your phone's lockscreen ([windows](https://user-images.githubusercontent.com/241032/233213022-298a98ba-721a-4cf1-a3d4-f62634bc53d5.png) // [iOS](https://user-images.githubusercontent.com/241032/142711926-0700be6c-3e31-47b3-9928-53722221f722.png) // [android](https://user-images.githubusercontent.com/241032/233212311-a7368590-08c7-4f9f-a1af-48ccf3f36fad.png))
|
* OS integration; control playback from your phone's lockscreen ([windows](https://user-images.githubusercontent.com/241032/233213022-298a98ba-721a-4cf1-a3d4-f62634bc53d5.png) // [iOS](https://user-images.githubusercontent.com/241032/142711926-0700be6c-3e31-47b3-9928-53722221f722.png) // [android](https://user-images.githubusercontent.com/241032/233212311-a7368590-08c7-4f9f-a1af-48ccf3f36fad.png))
|
||||||
* shows the audio waveform in the seekbar
|
* shows the audio waveform in the seekbar
|
||||||
* not perfectly gapless but can get really close (see settings + eq below); good enough to enjoy gapless albums as intended
|
* not perfectly gapless but can get really close (see settings + eq below); good enough to enjoy gapless albums as intended
|
||||||
|
* videos can be played as audio, without wasting bandwidth on the video
|
||||||
|
|
||||||
click the `play` link next to an audio file, or copy the link target to [share it](https://a.ocv.me/pub/demo/music/Ubiktune%20-%20SOUNDSHOCK%202%20-%20FM%20FUNK%20TERRROR!!/#af-1fbfba61&t=18) (optionally with a timestamp to start playing from, like that example does)
|
click the `play` link next to an audio file, or copy the link target to [share it](https://a.ocv.me/pub/demo/music/Ubiktune%20-%20SOUNDSHOCK%202%20-%20FM%20FUNK%20TERRROR!!/#af-1fbfba61&t=18) (optionally with a timestamp to start playing from, like that example does)
|
||||||
|
|
||||||
|
|
|
@ -59,7 +59,8 @@ class ThumbCli(object):
|
||||||
|
|
||||||
want_opus = fmt in ("opus", "caf", "mp3")
|
want_opus = fmt in ("opus", "caf", "mp3")
|
||||||
is_au = ext in self.fmt_ffa
|
is_au = ext in self.fmt_ffa
|
||||||
if is_au:
|
is_vau = want_opus and ext in self.fmt_ffv
|
||||||
|
if is_au or is_vau:
|
||||||
if want_opus:
|
if want_opus:
|
||||||
if self.args.no_acode:
|
if self.args.no_acode:
|
||||||
return None
|
return None
|
||||||
|
@ -107,7 +108,7 @@ class ThumbCli(object):
|
||||||
|
|
||||||
fmt = sfmt
|
fmt = sfmt
|
||||||
|
|
||||||
elif fmt[:1] == "p" and not is_au:
|
elif fmt[:1] == "p" and not is_au and not is_vid:
|
||||||
t = "cannot thumbnail [%s]: png only allowed for waveforms"
|
t = "cannot thumbnail [%s]: png only allowed for waveforms"
|
||||||
self.log(t % (rem), 6)
|
self.log(t % (rem), 6)
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -304,23 +304,29 @@ class ThumbSrv(object):
|
||||||
ap_unpk = abspath
|
ap_unpk = abspath
|
||||||
|
|
||||||
if not bos.path.exists(tpath):
|
if not bos.path.exists(tpath):
|
||||||
|
want_mp3 = tpath.endswith(".mp3")
|
||||||
|
want_opus = tpath.endswith(".opus") or tpath.endswith(".caf")
|
||||||
|
want_png = tpath.endswith(".png")
|
||||||
|
want_au = want_mp3 or want_opus
|
||||||
for lib in self.args.th_dec:
|
for lib in self.args.th_dec:
|
||||||
|
can_au = lib == "ff" and (ext in self.fmt_ffa or ext in self.fmt_ffv)
|
||||||
|
|
||||||
if lib == "pil" and ext in self.fmt_pil:
|
if lib == "pil" and ext in self.fmt_pil:
|
||||||
funs.append(self.conv_pil)
|
funs.append(self.conv_pil)
|
||||||
elif lib == "vips" and ext in self.fmt_vips:
|
elif lib == "vips" and ext in self.fmt_vips:
|
||||||
funs.append(self.conv_vips)
|
funs.append(self.conv_vips)
|
||||||
elif lib == "ff" and ext in self.fmt_ffi or ext in self.fmt_ffv:
|
elif can_au and (want_png or want_au):
|
||||||
funs.append(self.conv_ffmpeg)
|
if want_opus:
|
||||||
elif lib == "ff" and ext in self.fmt_ffa:
|
|
||||||
if tpath.endswith(".opus") or tpath.endswith(".caf"):
|
|
||||||
funs.append(self.conv_opus)
|
funs.append(self.conv_opus)
|
||||||
elif tpath.endswith(".mp3"):
|
elif want_mp3:
|
||||||
funs.append(self.conv_mp3)
|
funs.append(self.conv_mp3)
|
||||||
elif tpath.endswith(".png"):
|
elif want_png:
|
||||||
funs.append(self.conv_waves)
|
funs.append(self.conv_waves)
|
||||||
png_ok = True
|
png_ok = True
|
||||||
else:
|
elif lib == "ff" and (ext in self.fmt_ffi or ext in self.fmt_ffv):
|
||||||
funs.append(self.conv_spec)
|
funs.append(self.conv_ffmpeg)
|
||||||
|
elif lib == "ff" and ext in self.fmt_ffa and not want_au:
|
||||||
|
funs.append(self.conv_spec)
|
||||||
|
|
||||||
tdir, tfn = os.path.split(tpath)
|
tdir, tfn = os.path.split(tpath)
|
||||||
ttpath = os.path.join(tdir, "w", tfn)
|
ttpath = os.path.join(tdir, "w", tfn)
|
||||||
|
|
|
@ -360,6 +360,7 @@ var Ls = {
|
||||||
"tvt_sel": "select file ( for cut / delete / ... )$NHotkey: S\">sel",
|
"tvt_sel": "select file ( for cut / delete / ... )$NHotkey: S\">sel",
|
||||||
"tvt_edit": "open file in text editor$NHotkey: E\">✏️ edit",
|
"tvt_edit": "open file in text editor$NHotkey: E\">✏️ edit",
|
||||||
|
|
||||||
|
"gt_vau": "don't show videos, just play the audio\">🎧",
|
||||||
"gt_msel": "enable file selection; ctrl-click a file to override$N$N<em>when active: doubleclick a file / folder to open it</em>$N$NHotkey: S\">multiselect",
|
"gt_msel": "enable file selection; ctrl-click a file to override$N$N<em>when active: doubleclick a file / folder to open it</em>$N$NHotkey: S\">multiselect",
|
||||||
"gt_crop": "center-crop thumbnails\">crop",
|
"gt_crop": "center-crop thumbnails\">crop",
|
||||||
"gt_3x": "hi-res thumbnails\">3x",
|
"gt_3x": "hi-res thumbnails\">3x",
|
||||||
|
@ -874,6 +875,7 @@ var Ls = {
|
||||||
"tvt_sel": "markér filen ( for utklipp / sletting / ... )$NSnarvei: S\">merk",
|
"tvt_sel": "markér filen ( for utklipp / sletting / ... )$NSnarvei: S\">merk",
|
||||||
"tvt_edit": "redigér filen$NSnarvei: E\">✏️ endre",
|
"tvt_edit": "redigér filen$NSnarvei: E\">✏️ endre",
|
||||||
|
|
||||||
|
"gt_vau": "ikke vis videofiler, bare spill lyden\">🎧",
|
||||||
"gt_msel": "markér filer istedenfor å åpne dem; ctrl-klikk filer for å overstyre$N$N<em>når aktiv: dobbelklikk en fil / mappe for å åpne</em>$N$NSnarvei: S\">markering",
|
"gt_msel": "markér filer istedenfor å åpne dem; ctrl-klikk filer for å overstyre$N$N<em>når aktiv: dobbelklikk en fil / mappe for å åpne</em>$N$NSnarvei: S\">markering",
|
||||||
"gt_crop": "beskjær ikonene så de passer bedre\">✂",
|
"gt_crop": "beskjær ikonene så de passer bedre\">✂",
|
||||||
"gt_3x": "høyere oppløsning på ikoner\">3x",
|
"gt_3x": "høyere oppløsning på ikoner\">3x",
|
||||||
|
@ -1709,7 +1711,7 @@ catch (ex) { }
|
||||||
|
|
||||||
|
|
||||||
var re_au_native = (can_ogg || have_acode) ? /\.(aac|flac|m4a|mp3|ogg|opus|wav)$/i : /\.(aac|flac|m4a|mp3|wav)$/i,
|
var re_au_native = (can_ogg || have_acode) ? /\.(aac|flac|m4a|mp3|ogg|opus|wav)$/i : /\.(aac|flac|m4a|mp3|wav)$/i,
|
||||||
re_au_all = /\.(aac|ac3|aif|aiff|alac|alaw|amr|ape|au|dfpwm|dts|flac|gsm|it|itgz|itxz|itz|m4a|mdgz|mdxz|mdz|mo3|mod|mp2|mp3|mpc|mptm|mt2|mulaw|ogg|okt|opus|ra|s3m|s3gz|s3xz|s3z|tak|tta|ulaw|wav|wma|wv|xm|xmgz|xmxz|xmz|xpk)$/i;
|
re_au_all = /\.(aac|ac3|aif|aiff|alac|alaw|amr|ape|au|dfpwm|dts|flac|gsm|it|itgz|itxz|itz|m4a|mdgz|mdxz|mdz|mo3|mod|mp2|mp3|mpc|mptm|mt2|mulaw|ogg|okt|opus|ra|s3m|s3gz|s3xz|s3z|tak|tta|ulaw|wav|wma|wv|xm|xmgz|xmxz|xmz|xpk|3gp|asf|avi|flv|m4v|mkv|mov|mp4|mpeg|mpeg2|mpegts|mpg|mpg2|nut|ogm|ogv|rm|ts|vob|webm|wmv)$/i;
|
||||||
|
|
||||||
|
|
||||||
// extract songs + add play column
|
// extract songs + add play column
|
||||||
|
@ -4410,7 +4412,7 @@ var showfile = (function () {
|
||||||
|
|
||||||
var td = ebi(link.id).closest('tr').getElementsByTagName('td')[0];
|
var td = ebi(link.id).closest('tr').getElementsByTagName('td')[0];
|
||||||
|
|
||||||
if (lang == 'md' && td.textContent != '-')
|
if (lang == 'ts' || (lang == 'md' && td.textContent != '-'))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
td.innerHTML = '<a href="#" id="t' +
|
td.innerHTML = '<a href="#" id="t' +
|
||||||
|
@ -4677,6 +4679,7 @@ var thegrid = (function () {
|
||||||
gfiles.style.display = 'none';
|
gfiles.style.display = 'none';
|
||||||
gfiles.innerHTML = (
|
gfiles.innerHTML = (
|
||||||
'<div id="ghead" class="ghead">' +
|
'<div id="ghead" class="ghead">' +
|
||||||
|
'<a href="#" class="tgl btn" id="gridvau" tt="' + L.gt_vau + '</a> ' +
|
||||||
'<a href="#" class="tgl btn" id="gridsel" tt="' + L.gt_msel + '</a> ' +
|
'<a href="#" class="tgl btn" id="gridsel" tt="' + L.gt_msel + '</a> ' +
|
||||||
'<a href="#" class="tgl btn" id="gridcrop" tt="' + L.gt_crop + '</a> ' +
|
'<a href="#" class="tgl btn" id="gridcrop" tt="' + L.gt_crop + '</a> ' +
|
||||||
'<a href="#" class="tgl btn" id="grid3x" tt="' + L.gt_3x + '</a> ' +
|
'<a href="#" class="tgl btn" id="grid3x" tt="' + L.gt_3x + '</a> ' +
|
||||||
|
@ -4838,7 +4841,7 @@ var thegrid = (function () {
|
||||||
else if (oth.hasAttribute('download'))
|
else if (oth.hasAttribute('download'))
|
||||||
oth.click();
|
oth.click();
|
||||||
|
|
||||||
else if (widget.is_open && aplay)
|
else if (aplay && (r.vau || !is_img))
|
||||||
aplay.click();
|
aplay.click();
|
||||||
|
|
||||||
else if (is_dir && !have_sel)
|
else if (is_dir && !have_sel)
|
||||||
|
@ -5129,6 +5132,7 @@ var thegrid = (function () {
|
||||||
|
|
||||||
bcfg_bind(r, 'thumbs', 'thumbs', true, r.setdirty);
|
bcfg_bind(r, 'thumbs', 'thumbs', true, r.setdirty);
|
||||||
bcfg_bind(r, 'ihop', 'ihop', true);
|
bcfg_bind(r, 'ihop', 'ihop', true);
|
||||||
|
bcfg_bind(r, 'vau', 'gridvau', false);
|
||||||
bcfg_bind(r, 'crop', 'gridcrop', !dcrop.endsWith('n'), r.set_crop);
|
bcfg_bind(r, 'crop', 'gridcrop', !dcrop.endsWith('n'), r.set_crop);
|
||||||
bcfg_bind(r, 'x3', 'grid3x', dth3x.endsWith('y'), r.set_x3);
|
bcfg_bind(r, 'x3', 'grid3x', dth3x.endsWith('y'), r.set_x3);
|
||||||
bcfg_bind(r, 'sel', 'gridsel', false, r.loadsel);
|
bcfg_bind(r, 'sel', 'gridsel', false, r.loadsel);
|
||||||
|
|
Loading…
Reference in a new issue