mirror of
				https://github.com/9001/copyparty.git
				synced 2025-11-03 21:43:12 +00:00 
			
		
		
		
	Compare commits
	
		
			1 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					ff8313d0fb | 
@@ -324,6 +324,9 @@ def run_argparse(argv, formatter):
 | 
			
		||||
    ap2.add_argument("-mtp", metavar="M=[f,]bin", action="append", type=str, help="read tag M using bin")
 | 
			
		||||
    ap2.add_argument("--srch-time", metavar="SEC", type=int, default=30, help="search deadline")
 | 
			
		||||
 | 
			
		||||
    ap2 = ap.add_argument_group('video streaming options')
 | 
			
		||||
    ap2.add_argument("--vcr", action="store_true", help="enable video streaming")
 | 
			
		||||
 | 
			
		||||
    ap2 = ap.add_argument_group('appearance options')
 | 
			
		||||
    ap2.add_argument("--css-browser", metavar="L", help="URL to additional CSS to include")
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -18,6 +18,8 @@ from .util import *  # noqa  # pylint: disable=unused-wildcard-import
 | 
			
		||||
from .authsrv import AuthSrv
 | 
			
		||||
from .szip import StreamZip
 | 
			
		||||
from .star import StreamTar
 | 
			
		||||
from .vcr import VCR_Direct
 | 
			
		||||
from .th_srv import FMT_FF
 | 
			
		||||
 | 
			
		||||
if not PY2:
 | 
			
		||||
    unicode = str
 | 
			
		||||
@@ -229,7 +231,9 @@ class HttpCli(object):
 | 
			
		||||
    def send_headers(self, length, status=200, mime=None, headers={}):
 | 
			
		||||
        response = ["{} {} {}".format(self.http_ver, status, HTTPCODE[status])]
 | 
			
		||||
 | 
			
		||||
        if length is not None:
 | 
			
		||||
        if length is None:
 | 
			
		||||
            self.keepalive = False
 | 
			
		||||
        else:
 | 
			
		||||
            response.append("Content-Length: " + unicode(length))
 | 
			
		||||
 | 
			
		||||
        # close if unknown length, otherwise take client's preference
 | 
			
		||||
@@ -1563,6 +1567,15 @@ class HttpCli(object):
 | 
			
		||||
            if rem.startswith(".hist/up2k."):
 | 
			
		||||
                raise Pebkac(403)
 | 
			
		||||
 | 
			
		||||
            if "vcr" in self.uparam:
 | 
			
		||||
                ext = abspath.rsplit(".")[-1]
 | 
			
		||||
                if not self.args.vcr or ext not in FMT_FF:
 | 
			
		||||
                    raise Pebkac(403)
 | 
			
		||||
 | 
			
		||||
                vcr = VCR_Direct(self, abspath)
 | 
			
		||||
                vcr.run()
 | 
			
		||||
                return False
 | 
			
		||||
 | 
			
		||||
            is_dir = stat.S_ISDIR(st.st_mode)
 | 
			
		||||
            th_fmt = self.uparam.get("th")
 | 
			
		||||
            if th_fmt is not None:
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										80
									
								
								copyparty/vcr.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								copyparty/vcr.py
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,80 @@
 | 
			
		||||
# coding: utf-8
 | 
			
		||||
from __future__ import print_function, unicode_literals
 | 
			
		||||
 | 
			
		||||
import time
 | 
			
		||||
import shlex
 | 
			
		||||
import subprocess as sp
 | 
			
		||||
 | 
			
		||||
from .__init__ import PY2
 | 
			
		||||
from .util import fsenc
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class VCR_Direct(object):
 | 
			
		||||
    def __init__(self, cli, fpath):
 | 
			
		||||
        self.cli = cli
 | 
			
		||||
        self.fpath = fpath
 | 
			
		||||
 | 
			
		||||
        self.log_func = cli.log_func
 | 
			
		||||
        self.log_src = cli.log_src
 | 
			
		||||
 | 
			
		||||
    def log(self, msg, c=0):
 | 
			
		||||
        self.log_func(self.log_src, "vcr: {}".format(msg), c)
 | 
			
		||||
 | 
			
		||||
    def run(self):
 | 
			
		||||
        opts = self.cli.uparam
 | 
			
		||||
 | 
			
		||||
        # fmt: off
 | 
			
		||||
        cmd = [
 | 
			
		||||
            "ffmpeg",
 | 
			
		||||
            "-nostdin",
 | 
			
		||||
            "-hide_banner",
 | 
			
		||||
            "-v", "warning",
 | 
			
		||||
            "-i", fsenc(self.fpath),
 | 
			
		||||
            "-vf", "scale=640:-4",
 | 
			
		||||
            "-c:a", "libopus",
 | 
			
		||||
            "-b:a", "128k",
 | 
			
		||||
            "-c:v", "libvpx",
 | 
			
		||||
            "-deadline", "realtime",
 | 
			
		||||
            "-row-mt", "1"
 | 
			
		||||
        ]
 | 
			
		||||
        # fmt: on
 | 
			
		||||
 | 
			
		||||
        if "ss" in opts:
 | 
			
		||||
            cmd.extend(["-ss", opts["ss"]])
 | 
			
		||||
 | 
			
		||||
        if "crf" in opts:
 | 
			
		||||
            cmd.extend(["-b:v", "0", "-crf", opts["crf"]])
 | 
			
		||||
        else:
 | 
			
		||||
            cmd.extend(["-b:v", "{}M".format(opts.get("mbps", 1.2))])
 | 
			
		||||
 | 
			
		||||
        cmd.extend(["-f", "webm", "-"])
 | 
			
		||||
 | 
			
		||||
        comp = str if not PY2 else unicode
 | 
			
		||||
        cmd = [x.encode("utf-8") if isinstance(x, comp) else x for x in cmd]
 | 
			
		||||
 | 
			
		||||
        self.log(" ".join([shlex.quote(x.decode("utf-8", "replace")) for x in cmd]))
 | 
			
		||||
 | 
			
		||||
        p = sp.Popen(cmd, stdout=sp.PIPE)
 | 
			
		||||
 | 
			
		||||
        self.cli.send_headers(None, mime="video/webm")
 | 
			
		||||
 | 
			
		||||
        fails = 0
 | 
			
		||||
        while True:
 | 
			
		||||
            self.log("read")
 | 
			
		||||
            buf = p.stdout.read(1024 * 4)
 | 
			
		||||
            if not buf:
 | 
			
		||||
                fails += 1
 | 
			
		||||
                if p.poll() is not None or fails > 30:
 | 
			
		||||
                    self.log("ffmpeg exited")
 | 
			
		||||
                    return
 | 
			
		||||
 | 
			
		||||
                time.sleep(0.1)
 | 
			
		||||
                continue
 | 
			
		||||
 | 
			
		||||
            fails = 0
 | 
			
		||||
            try:
 | 
			
		||||
                self.cli.s.sendall(buf)
 | 
			
		||||
            except:
 | 
			
		||||
                self.log("client disconnected")
 | 
			
		||||
                p.kill()
 | 
			
		||||
                return
 | 
			
		||||
@@ -1552,6 +1552,7 @@ var thegrid = (function () {
 | 
			
		||||
			href = this.getAttribute('href'),
 | 
			
		||||
			aplay = ebi('a' + oth.getAttribute('id')),
 | 
			
		||||
			is_img = /\.(gif|jpe?g|png|webp)(\?|$)/i.test(href),
 | 
			
		||||
			is_vid = /\.(av1|asf|avi|flv|m4v|mkv|mjpeg|mjpg|mpg|mpeg|mpg2|mpeg2|h264|avc|h265|hevc|mov|3gp|mp4|ts|mpegts|nut|ogv|ogm|rm|vob|webm|wmv)(\?|$)/i.test(href),
 | 
			
		||||
			in_tree = null,
 | 
			
		||||
			have_sel = QS('#files tr.sel'),
 | 
			
		||||
			td = oth.closest('td').nextSibling,
 | 
			
		||||
@@ -1579,6 +1580,9 @@ var thegrid = (function () {
 | 
			
		||||
		else if (in_tree && !have_sel)
 | 
			
		||||
			in_tree.click();
 | 
			
		||||
 | 
			
		||||
		else if (is_vid)
 | 
			
		||||
			window.open(href + (href.indexOf('?') === -1 ? '?' : '&') + 'vcr', '_blank');
 | 
			
		||||
 | 
			
		||||
		else if (!is_img && have_sel)
 | 
			
		||||
			window.open(href, '_blank');
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user