From 53f1e3c91d0db2843196224c58bf3fee73dadef1 Mon Sep 17 00:00:00 2001 From: ed Date: Mon, 22 Jul 2024 22:30:21 +0000 Subject: [PATCH] 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 --- README.md | 2 ++ copyparty/th_cli.py | 5 +++-- copyparty/th_srv.py | 22 ++++++++++++++-------- copyparty/web/browser.js | 10 +++++++--- 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/README.md b/README.md index 8535bea5..786244d7 100644 --- a/README.md +++ b/README.md @@ -225,6 +225,7 @@ also see [comparison to similar software](./docs/versus.md) * ☑ [navpane](#navpane) (directory tree sidebar) * ☑ 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) + * ☑ play video files as audio (converted on server) * ☑ image gallery with webm player * ☑ textfile browser with syntax hilighting * ☑ [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)) * 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 +* 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) diff --git a/copyparty/th_cli.py b/copyparty/th_cli.py index 0c69be5f..6bebd3de 100644 --- a/copyparty/th_cli.py +++ b/copyparty/th_cli.py @@ -59,7 +59,8 @@ class ThumbCli(object): want_opus = fmt in ("opus", "caf", "mp3") 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 self.args.no_acode: return None @@ -107,7 +108,7 @@ class ThumbCli(object): 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" self.log(t % (rem), 6) return None diff --git a/copyparty/th_srv.py b/copyparty/th_srv.py index 88d03395..0f9dcf1f 100644 --- a/copyparty/th_srv.py +++ b/copyparty/th_srv.py @@ -304,23 +304,29 @@ class ThumbSrv(object): ap_unpk = abspath 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: + 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: funs.append(self.conv_pil) elif lib == "vips" and ext in self.fmt_vips: funs.append(self.conv_vips) - elif lib == "ff" and ext in self.fmt_ffi or ext in self.fmt_ffv: - funs.append(self.conv_ffmpeg) - elif lib == "ff" and ext in self.fmt_ffa: - if tpath.endswith(".opus") or tpath.endswith(".caf"): + elif can_au and (want_png or want_au): + if want_opus: funs.append(self.conv_opus) - elif tpath.endswith(".mp3"): + elif want_mp3: funs.append(self.conv_mp3) - elif tpath.endswith(".png"): + elif want_png: funs.append(self.conv_waves) png_ok = True - else: - funs.append(self.conv_spec) + elif lib == "ff" and (ext in self.fmt_ffi or ext in self.fmt_ffv): + 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) ttpath = os.path.join(tdir, "w", tfn) diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js index d4f54be8..99aa7b68 100644 --- a/copyparty/web/browser.js +++ b/copyparty/web/browser.js @@ -360,6 +360,7 @@ var Ls = { "tvt_sel": "select file   ( for cut / delete / ... )$NHotkey: S\">sel", "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_crop": "center-crop thumbnails\">crop", "gt_3x": "hi-res thumbnails\">3x", @@ -874,6 +875,7 @@ var Ls = { "tvt_sel": "markér filen   ( for utklipp / sletting / ... )$NSnarvei: S\">merk", "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_crop": "beskjær ikonene så de passer bedre\">✂", "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, - 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 @@ -4410,7 +4412,7 @@ var showfile = (function () { var td = ebi(link.id).closest('tr').getElementsByTagName('td')[0]; - if (lang == 'md' && td.textContent != '-') + if (lang == 'ts' || (lang == 'md' && td.textContent != '-')) continue; td.innerHTML = '' + + '