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}"
|
"${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 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 index non-ascii filenames with `-e2d`
|
||||||
* Windows: python 2.7 cannot handle filenames with mojibake
|
* Windows: python 2.7 cannot handle filenames with mojibake
|
||||||
|
* MacOS: `--th-ff-jpg` may fix thumbnails using macports-FFmpeg
|
||||||
|
|
||||||
## general bugs
|
## 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-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-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-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 = ap.add_argument_group('database options')
|
||||||
ap2.add_argument("-e2d", action="store_true", help="enable up2k database")
|
ap2.add_argument("-e2d", action="store_true", help="enable up2k database")
|
||||||
|
|
|
@ -21,14 +21,16 @@ class ThumbCli(object):
|
||||||
if ext not in THUMBABLE:
|
if ext not in THUMBABLE:
|
||||||
return None
|
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
|
return None
|
||||||
|
|
||||||
if fmt == "j" and self.args.th_no_jpg:
|
if fmt == "j" and self.args.th_no_jpg:
|
||||||
fmt = "w"
|
fmt = "w"
|
||||||
|
|
||||||
if fmt == "w" and self.args.th_no_webp:
|
if fmt == "w":
|
||||||
fmt = "j"
|
if self.args.th_no_webp or (is_vid and self.args.th_ff_jpg):
|
||||||
|
fmt = "j"
|
||||||
|
|
||||||
hist = self.hist[ptop]
|
hist = self.hist[ptop]
|
||||||
tpath = thumb_path(hist, rem, mtime, fmt)
|
tpath = thumb_path(hist, rem, mtime, fmt)
|
||||||
|
|
|
@ -11,7 +11,7 @@ import threading
|
||||||
import subprocess as sp
|
import subprocess as sp
|
||||||
|
|
||||||
from .__init__ import PY2
|
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
|
from .mtag import HAVE_FFMPEG, HAVE_FFPROBE, ffprobe
|
||||||
|
|
||||||
|
|
||||||
|
@ -213,9 +213,9 @@ class ThumbSrv(object):
|
||||||
if fun:
|
if fun:
|
||||||
try:
|
try:
|
||||||
fun(abspath, tpath)
|
fun(abspath, tpath)
|
||||||
except Exception as ex:
|
except:
|
||||||
msg = "{} failed on {}\n {!r}"
|
msg = "{} failed on {}\n{}"
|
||||||
self.log(msg.format(fun.__name__, abspath, ex), 3)
|
self.log(msg.format(fun.__name__, abspath, min_ex()), 3)
|
||||||
with open(tpath, "wb") as _:
|
with open(tpath, "wb") as _:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -263,8 +263,13 @@ class ThumbSrv(object):
|
||||||
def conv_ffmpeg(self, abspath, tpath):
|
def conv_ffmpeg(self, abspath, tpath):
|
||||||
ret, _ = ffprobe(abspath)
|
ret, _ = ffprobe(abspath)
|
||||||
|
|
||||||
dur = ret[".dur"][1] if ".dur" in ret else 4
|
ext = abspath.rsplit(".")[-1]
|
||||||
seek = "{:.0f}".format(dur / 3)
|
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="
|
scale = "scale={0}:{1}:force_original_aspect_ratio="
|
||||||
if self.args.th_no_crop:
|
if self.args.th_no_crop:
|
||||||
|
@ -273,19 +278,20 @@ class ThumbSrv(object):
|
||||||
scale += "increase,crop={0}:{1},setsar=1:1"
|
scale += "increase,crop={0}:{1},setsar=1:1"
|
||||||
|
|
||||||
scale = scale.format(*list(self.res)).encode("utf-8")
|
scale = scale.format(*list(self.res)).encode("utf-8")
|
||||||
|
# fmt: off
|
||||||
cmd = [
|
cmd = [
|
||||||
b"ffmpeg",
|
b"ffmpeg",
|
||||||
b"-nostdin",
|
b"-nostdin",
|
||||||
b"-hide_banner",
|
b"-v", b"error",
|
||||||
b"-ss",
|
b"-hide_banner"
|
||||||
seek,
|
|
||||||
b"-i",
|
|
||||||
fsenc(abspath),
|
|
||||||
b"-vf",
|
|
||||||
scale,
|
|
||||||
b"-vframes",
|
|
||||||
b"1",
|
|
||||||
]
|
]
|
||||||
|
cmd += seek
|
||||||
|
cmd += [
|
||||||
|
b"-i", fsenc(abspath),
|
||||||
|
b"-vf", scale,
|
||||||
|
b"-vframes", b"1",
|
||||||
|
]
|
||||||
|
# fmt: on
|
||||||
|
|
||||||
if tpath.endswith(".jpg"):
|
if tpath.endswith(".jpg"):
|
||||||
cmd += [
|
cmd += [
|
||||||
|
@ -302,7 +308,11 @@ class ThumbSrv(object):
|
||||||
|
|
||||||
cmd += [fsenc(tpath)]
|
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):
|
def poke(self, tdir):
|
||||||
if not self.poke_cd.poke(tdir):
|
if not self.poke_cd.poke(tdir):
|
||||||
|
|
|
@ -998,8 +998,8 @@ def guess_mime(url, fallback="application/octet-stream"):
|
||||||
def runcmd(*argv):
|
def runcmd(*argv):
|
||||||
p = sp.Popen(argv, stdout=sp.PIPE, stderr=sp.PIPE)
|
p = sp.Popen(argv, stdout=sp.PIPE, stderr=sp.PIPE)
|
||||||
stdout, stderr = p.communicate()
|
stdout, stderr = p.communicate()
|
||||||
stdout = stdout.decode("utf-8")
|
stdout = stdout.decode("utf-8", "replace")
|
||||||
stderr = stderr.decode("utf-8")
|
stderr = stderr.decode("utf-8", "replace")
|
||||||
return [p.returncode, stdout, stderr]
|
return [p.returncode, stdout, stderr]
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -46,20 +46,22 @@ def main():
|
||||||
with open(vidp, "rb") as f:
|
with open(vidp, "rb") as f:
|
||||||
ovid = f.read()
|
ovid = f.read()
|
||||||
|
|
||||||
args = ["-p", "4321"]
|
args = ["-p", "4321", "-e2dsa", "-e2tsr"]
|
||||||
pdirs = []
|
pdirs = []
|
||||||
|
|
||||||
for d1 in ["r", "w", "a"]:
|
for d1 in ["r", "w", "a"]:
|
||||||
pdirs.append("{}/{}".format(td, d1))
|
pdirs.append("{}/{}".format(td, d1))
|
||||||
|
pdirs.append("{}/{}/j".format(td, d1))
|
||||||
for d2 in ["r", "w", "a"]:
|
for d2 in ["r", "w", "a"]:
|
||||||
d = os.path.join(td, d1, "j", d2)
|
d = os.path.join(td, d1, "j", d2)
|
||||||
pdirs.append(d.replace("\\", "/"))
|
pdirs.append(d.replace("\\", "/"))
|
||||||
os.makedirs(d)
|
os.makedirs(d)
|
||||||
|
|
||||||
udirs = [x.split("/", 2)[2] for x in pdirs]
|
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(d.split("/", 1)[1], d, d[-1])]
|
||||||
args += ["-v", "{}:{}:{}".format(pd, ud, ud[-1])]
|
args += ["-v", "{}:{}:{}".format(pd, ud, p)]
|
||||||
|
|
||||||
cpp = Cpp(args)
|
cpp = Cpp(args)
|
||||||
|
|
||||||
|
@ -74,14 +76,36 @@ def main():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
assert up
|
assert up
|
||||||
# for d in dirs:
|
|
||||||
# rd, fn = d.rsplit("/", 1)
|
|
||||||
# requests.post(ub + rd, files={"act": "mkdir", "name": fn})
|
|
||||||
|
|
||||||
for d in udirs:
|
for d in udirs:
|
||||||
vid = ovid + "\n{}".format(d).encode("utf-8")
|
vid = ovid + "\n{}".format(d).encode("utf-8")
|
||||||
requests.post(ub + d, data={"act": "bput"}, files={"f": ("a.h264", vid)})
|
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)
|
cpp.stop(True)
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue