mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -06:00
support macos ffmpeg
This commit is contained in:
parent
972a56e738
commit
a45a53fdce
8
.vscode/launch.json
vendored
8
.vscode/launch.json
vendored
|
@ -43,5 +43,13 @@
|
|||
"${file}"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Python: Current File",
|
||||
"type": "python",
|
||||
"request": "launch",
|
||||
"program": "${file}",
|
||||
"console": "integratedTerminal",
|
||||
"justMyCode": false
|
||||
},
|
||||
]
|
||||
}
|
|
@ -122,6 +122,7 @@ summary: all planned features work! now please enjoy the bloatening
|
|||
* Windows: python 3.7 and older cannot read tags with ffprobe, so use mutagen or upgrade
|
||||
* Windows: python 2.7 cannot index non-ascii filenames with `-e2d`
|
||||
* Windows: python 2.7 cannot handle filenames with mojibake
|
||||
* MacOS: `--th-ff-jpg` may fix thumbnails using macports-FFmpeg
|
||||
|
||||
## general bugs
|
||||
|
||||
|
|
|
@ -277,6 +277,7 @@ def run_argparse(argv, formatter):
|
|||
ap2.add_argument("--th-poke", metavar="SEC", type=int, default=300, help="activity labeling cooldown")
|
||||
ap2.add_argument("--th-clean", metavar="SEC", type=int, default=43200, help="cleanup interval")
|
||||
ap2.add_argument("--th-maxage", metavar="SEC", type=int, default=604800, help="max folder age")
|
||||
ap2.add_argument("--th-ff-jpg", action="store_true", help="force jpg for video thumbs")
|
||||
|
||||
ap2 = ap.add_argument_group('database options')
|
||||
ap2.add_argument("-e2d", action="store_true", help="enable up2k database")
|
||||
|
|
|
@ -21,13 +21,15 @@ class ThumbCli(object):
|
|||
if ext not in THUMBABLE:
|
||||
return None
|
||||
|
||||
if self.args.no_vthumb and ext in FMT_FF:
|
||||
is_vid = ext in FMT_FF
|
||||
if is_vid and self.args.no_vthumb:
|
||||
return None
|
||||
|
||||
if fmt == "j" and self.args.th_no_jpg:
|
||||
fmt = "w"
|
||||
|
||||
if fmt == "w" and self.args.th_no_webp:
|
||||
if fmt == "w":
|
||||
if self.args.th_no_webp or (is_vid and self.args.th_ff_jpg):
|
||||
fmt = "j"
|
||||
|
||||
hist = self.hist[ptop]
|
||||
|
|
|
@ -11,7 +11,7 @@ import threading
|
|||
import subprocess as sp
|
||||
|
||||
from .__init__ import PY2
|
||||
from .util import fsenc, mchkcmd, Queue, Cooldown, BytesIO
|
||||
from .util import fsenc, runcmd, Queue, Cooldown, BytesIO, min_ex
|
||||
from .mtag import HAVE_FFMPEG, HAVE_FFPROBE, ffprobe
|
||||
|
||||
|
||||
|
@ -213,9 +213,9 @@ class ThumbSrv(object):
|
|||
if fun:
|
||||
try:
|
||||
fun(abspath, tpath)
|
||||
except Exception as ex:
|
||||
msg = "{} failed on {}\n {!r}"
|
||||
self.log(msg.format(fun.__name__, abspath, ex), 3)
|
||||
except:
|
||||
msg = "{} failed on {}\n{}"
|
||||
self.log(msg.format(fun.__name__, abspath, min_ex()), 3)
|
||||
with open(tpath, "wb") as _:
|
||||
pass
|
||||
|
||||
|
@ -263,8 +263,13 @@ class ThumbSrv(object):
|
|||
def conv_ffmpeg(self, abspath, tpath):
|
||||
ret, _ = ffprobe(abspath)
|
||||
|
||||
ext = abspath.rsplit(".")[-1]
|
||||
if ext in ["h264", "h265"]:
|
||||
seek = []
|
||||
else:
|
||||
dur = ret[".dur"][1] if ".dur" in ret else 4
|
||||
seek = "{:.0f}".format(dur / 3)
|
||||
seek = [b"-ss", seek.encode("utf-8")]
|
||||
|
||||
scale = "scale={0}:{1}:force_original_aspect_ratio="
|
||||
if self.args.th_no_crop:
|
||||
|
@ -273,19 +278,20 @@ class ThumbSrv(object):
|
|||
scale += "increase,crop={0}:{1},setsar=1:1"
|
||||
|
||||
scale = scale.format(*list(self.res)).encode("utf-8")
|
||||
# fmt: off
|
||||
cmd = [
|
||||
b"ffmpeg",
|
||||
b"-nostdin",
|
||||
b"-hide_banner",
|
||||
b"-ss",
|
||||
seek,
|
||||
b"-i",
|
||||
fsenc(abspath),
|
||||
b"-vf",
|
||||
scale,
|
||||
b"-vframes",
|
||||
b"1",
|
||||
b"-v", b"error",
|
||||
b"-hide_banner"
|
||||
]
|
||||
cmd += seek
|
||||
cmd += [
|
||||
b"-i", fsenc(abspath),
|
||||
b"-vf", scale,
|
||||
b"-vframes", b"1",
|
||||
]
|
||||
# fmt: on
|
||||
|
||||
if tpath.endswith(".jpg"):
|
||||
cmd += [
|
||||
|
@ -302,7 +308,11 @@ class ThumbSrv(object):
|
|||
|
||||
cmd += [fsenc(tpath)]
|
||||
|
||||
mchkcmd(cmd)
|
||||
ret, sout, serr = runcmd(*cmd)
|
||||
if ret != 0:
|
||||
msg = ["ff: {}".format(x) for x in serr.split("\n")]
|
||||
self.log("FFmpeg failed:\n" + "\n".join(msg), c="1;30")
|
||||
raise sp.CalledProcessError(ret, (cmd[0], b"...", cmd[-1]))
|
||||
|
||||
def poke(self, tdir):
|
||||
if not self.poke_cd.poke(tdir):
|
||||
|
|
|
@ -998,8 +998,8 @@ def guess_mime(url, fallback="application/octet-stream"):
|
|||
def runcmd(*argv):
|
||||
p = sp.Popen(argv, stdout=sp.PIPE, stderr=sp.PIPE)
|
||||
stdout, stderr = p.communicate()
|
||||
stdout = stdout.decode("utf-8")
|
||||
stderr = stderr.decode("utf-8")
|
||||
stdout = stdout.decode("utf-8", "replace")
|
||||
stderr = stderr.decode("utf-8", "replace")
|
||||
return [p.returncode, stdout, stderr]
|
||||
|
||||
|
||||
|
|
|
@ -46,20 +46,22 @@ def main():
|
|||
with open(vidp, "rb") as f:
|
||||
ovid = f.read()
|
||||
|
||||
args = ["-p", "4321"]
|
||||
args = ["-p", "4321", "-e2dsa", "-e2tsr"]
|
||||
pdirs = []
|
||||
|
||||
for d1 in ["r", "w", "a"]:
|
||||
pdirs.append("{}/{}".format(td, d1))
|
||||
pdirs.append("{}/{}/j".format(td, d1))
|
||||
for d2 in ["r", "w", "a"]:
|
||||
d = os.path.join(td, d1, "j", d2)
|
||||
pdirs.append(d.replace("\\", "/"))
|
||||
os.makedirs(d)
|
||||
|
||||
udirs = [x.split("/", 2)[2] for x in pdirs]
|
||||
for pd, ud in zip(pdirs, udirs):
|
||||
perms = [x.rstrip("j/")[-1] for x in pdirs]
|
||||
for pd, ud, p in zip(pdirs, udirs, perms):
|
||||
# args += ["-v", "{}:{}:{}".format(d.split("/", 1)[1], d, d[-1])]
|
||||
args += ["-v", "{}:{}:{}".format(pd, ud, ud[-1])]
|
||||
args += ["-v", "{}:{}:{}".format(pd, ud, p)]
|
||||
|
||||
cpp = Cpp(args)
|
||||
|
||||
|
@ -74,14 +76,36 @@ def main():
|
|||
pass
|
||||
|
||||
assert up
|
||||
# for d in dirs:
|
||||
# rd, fn = d.rsplit("/", 1)
|
||||
# requests.post(ub + rd, files={"act": "mkdir", "name": fn})
|
||||
|
||||
for d in udirs:
|
||||
vid = ovid + "\n{}".format(d).encode("utf-8")
|
||||
requests.post(ub + d, data={"act": "bput"}, files={"f": ("a.h264", vid)})
|
||||
time.sleep(3)
|
||||
|
||||
for d, p in zip(udirs, perms):
|
||||
u = "{}{}/a.h264".format(ub, d)
|
||||
r = requests.get(u)
|
||||
ok = bool(r)
|
||||
if ok != (p in ["a"]):
|
||||
raise Exception("get {} with perm {} at {}".format(ok, p, u))
|
||||
|
||||
for d, p in zip(pdirs, perms):
|
||||
u = "{}/a.h264".format(d)
|
||||
ok = os.path.exists(u)
|
||||
if ok != (p in ["a", "w"]):
|
||||
raise Exception("stat {} with perm {} at {}".format(ok, p, u))
|
||||
|
||||
for d, p in zip(udirs, perms):
|
||||
u = "{}{}/a.h264?th=j".format(ub, d)
|
||||
r = requests.get(u)
|
||||
ok = False
|
||||
if r:
|
||||
r.raw.decode_content = True
|
||||
buf = r.raw.read(256)
|
||||
if buf[:3] == b"\xff\xd8\xff":
|
||||
ok = True
|
||||
if ok != (p in ["a"]):
|
||||
raise Exception("thumb {} with perm {} at {}".format(ok, p, u))
|
||||
|
||||
cpp.stop(True)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue