From 68a65fd06255411599601a0b9857be6ef2e8eba2 Mon Sep 17 00:00:00 2001 From: Roman Bazalevsky Date: Fri, 24 Jul 2015 01:52:42 +0300 Subject: [PATCH] transcoding option for web-video added --- README.md~ | 8 ++++++++ clientcounter.py | 1 + plugins/m3u_plugin.py | 13 ++++++++++--- plugins/modules/PlaylistGenerator.py | 4 ++-- vlcclient/vlcclient.py | 11 ++++++----- vlcclient/vlcmessages.py | 9 ++++++--- vpconfig.py | 10 +++++----- vphttp.py | 24 +++++++++++------------- 8 files changed, 49 insertions(+), 31 deletions(-) create mode 100644 README.md~ diff --git a/README.md~ b/README.md~ new file mode 100644 index 0000000..24b72df --- /dev/null +++ b/README.md~ @@ -0,0 +1,8 @@ +AceProxy: Ace Stream HTTP Proxy +=============================== +AceProxy allows you to watch [Ace Stream](http://acestream.org/) live streams or BitTorrent files over HTTP. +It's written in Python + gevent and should work on both Linux and Windows (Mac OS should work too, but was not tested) + +Currently it supports Ace Stream Content-ID hashes (PIDs), .acestream files and usual torrent files. + +**For installation, configuration and using info, visit** [Wiki](https://github.com/ValdikSS/aceproxy/wiki) diff --git a/clientcounter.py b/clientcounter.py index bcfd0b2..bd86cbe 100644 --- a/clientcounter.py +++ b/clientcounter.py @@ -34,5 +34,6 @@ class ClientCounter(object): else: return False + print "Total:", self.total return self.clients[id][0] diff --git a/plugins/m3u_plugin.py b/plugins/m3u_plugin.py index 4104e43..cc614f2 100644 --- a/plugins/m3u_plugin.py +++ b/plugins/m3u_plugin.py @@ -17,7 +17,7 @@ import os class M3u(VPProxyPlugin): - handlers = ('m3u', ) + handlers = ('m3u', 'm3ut' ) logger = logging.getLogger('plugin_m3u') playlist = None @@ -28,6 +28,13 @@ class M3u(VPProxyPlugin): self.splitted_path=connection.path.split('/') + if self.splitted_path[1]=='m3u': + prefix='get' + elif self.splitted_path[1]=='m3ut': + prefix='mp4' + else: + connection.dieWithError(404) + if len(self.splitted_path)>3: connection.dieWithError() return @@ -61,7 +68,7 @@ class M3u(VPProxyPlugin): try: playlist=parseM3U(m3u_file) except: - connection.dieWithError() + connection.dieWithError(404) return if not playlist: @@ -76,7 +83,7 @@ class M3u(VPProxyPlugin): channel['url']=record.path.decode('utf-8') playlistgen.addItem(channel) - exported = playlistgen.exportm3u(hostport) + exported = playlistgen.exportm3u(hostport,prefix) exported = exported.encode('utf-8') connection.wfile.write(exported) diff --git a/plugins/modules/PlaylistGenerator.py b/plugins/modules/PlaylistGenerator.py index e5402b2..c46197f 100644 --- a/plugins/modules/PlaylistGenerator.py +++ b/plugins/modules/PlaylistGenerator.py @@ -38,7 +38,7 @@ class PlaylistGenerator(object): item.get('group', ''), item.get('tvg', ''), item.get('logo', ''), item.get('name'), item.get('url')) - def exportm3u(self, hostport, add_ts=False, empty_header=False, archive=False): + def exportm3u(self, hostport, prefix="get", add_ts=False, empty_header=False, archive=False): ''' Exports m3u playlist ''' @@ -54,7 +54,7 @@ class PlaylistGenerator(object): item['tvg'] = item.get('tvg', '') if item.get('tvg') else \ item.get('name').replace(' ', '_') # For .acelive and .torrent - item['url'] = 'http://' + hostport + '/get/'+item['url'] + item['url'] = 'http://' + hostport + '/' + prefix + '/' + item['url'] itemlist += PlaylistGenerator._generatem3uline(item) return itemlist diff --git a/vlcclient/vlcclient.py b/vlcclient/vlcclient.py index ebe83f7..b222699 100644 --- a/vlcclient/vlcclient.py +++ b/vlcclient/vlcclient.py @@ -109,7 +109,7 @@ class VlcClient(object): except EOFError as e: raise VlcException("Vlc Write error! ERROR: " + repr(e)) - def _broadcast(self, brtype, stream_name, input=None, muxer='ts', pre_access=''): + def _broadcast(self, brtype, stream_name, input=None, muxer='ts', pre_access='', qtype='default'): if self._shuttingDown.isSet(): return @@ -127,8 +127,8 @@ class VlcClient(object): self._resultlock.acquire() # Write message to VLC socket if brtype == True: - self._write(VlcMessage.request.startBroadcast( - stream_name, input, self._out_port, muxer, pre_access)) + msg = VlcMessage.request.startBroadcast(stream_name, input, self._out_port, muxer, pre_access, qtype) + self._write(msg) else: self._write(VlcMessage.request.stopBroadcast(stream_name)) @@ -149,8 +149,9 @@ class VlcClient(object): else: logger.debug("Broadcast stopped") - def startBroadcast(self, stream_name, input, muxer='ts', pre_access=''): - return self._broadcast(True, stream_name, input, muxer, pre_access) + def startBroadcast(self, stream_name, input, muxer='ts', pre_access='', qtype='default'): + print "Starting broadcast......" + return self._broadcast(True, stream_name, input, muxer, pre_access, qtype) def stopBroadcast(self, stream_name): return self._broadcast(False, stream_name) diff --git a/vlcclient/vlcmessages.py b/vlcclient/vlcmessages.py index 10de03d..da8606c 100644 --- a/vlcclient/vlcmessages.py +++ b/vlcclient/vlcmessages.py @@ -9,11 +9,14 @@ class VlcMessage(object): SHUTDOWN = 'shutdown' @staticmethod - def startBroadcast(stream_name, input, out_port, muxer='ts', pre_access=''): - return 'new "' + stream_name + '" broadcast input "' + input + '" output ' + (pre_access + ':' if pre_access else '#') + \ - 'http{mux=' + muxer + ',dst=:' + \ + def startBroadcast(stream_name, input, out_port, muxer='ts', pre_access='',qtype='default'): + command = 'new "' + stream_name + '" broadcast input "' + input + '" output ' + (pre_access + ':' if pre_access else '#') + if qtype=='mp4': + command = command + 'transcode{vcodec=mp4v,acodec=mpga,vb=800,ab=128}:' + command = command +'http{mux=' + muxer + ',dst=:' + \ str(out_port) + '/' + stream_name + '} option sout-keep option sout-all enabled' + \ "\r\n" + 'control "' + stream_name + '" play' + return command @staticmethod def stopBroadcast(stream_name): diff --git a/vpconfig.py b/vpconfig.py index ca11dd5..05ecbbf 100644 --- a/vpconfig.py +++ b/vpconfig.py @@ -15,7 +15,7 @@ class VPConfig(): httpport = 8001 # If started as root, drop privileges to this user. # Leave empty to disable. - vpproxyuser = 'aceproxy' + vpproxyuser = 'vpproxy' # Enable firewall firewall = False # Firewall mode. True for blackilst, False for whitelist @@ -32,7 +32,7 @@ class VPConfig(): # Logging to a file loggingtoafile = False # Path for logs, default is current directory. For example '/tmp/' - logpath = '' + logpath = '/var/log/vpproxy/' # # ---------------------------------------------------- # VLC configuration @@ -42,10 +42,10 @@ class VPConfig(): # Spawn VLC automaticaly vlcspawn = True # VLC cmd line (use `--file-logging --logfile=filepath` to write log) - vlccmd = "vlc -I telnet --clock-jitter -1 --network-caching -1 --sout-mux-caching 2000 --telnet-password admin --telnet-port 4212" + vlccmd = "vlc -I telnet --clock-jitter 0 --network-caching 500 --sout-mux-caching 2000 --telnet-password admin --telnet-port 4212" # VLC spawn timeout # Adjust this if you get error 'Cannot spawn VLC!' - vlcspawntimeout = 4 + vlcspawntimeout = 15 # VLC host vlchost = '127.0.0.1' # VLC telnet interface port @@ -98,5 +98,5 @@ class VPConfig(): # before the headers sent. # We send them 200 OK and MPEG MIME-type right after connection has been initiated fakeheaderuas = ('HLS Client/2.0 (compatible; LG NetCast.TV-2012)', - 'Mozilla/5.0 (DirectFB; Linux armv7l) AppleWebKit/534.26+ (KHTML, like Gecko) Version/5.0 Safari/534.26+ LG Browser/5.00.00(+mouse+3D+SCREEN+TUNER; LGE; 42LM670T-ZA; 04.41.03; 0x00000001;); LG NetCast.TV-2012 0' + 'Mozilla/5.0 (DirectFB; Linux armv7l) AppleWebKit/534.26+ (KHTML, like Gecko) Version/5.0 Safari/534.26+ LG Browser/5.00.00(+mouse+3D+SCREEN+TUNER; LGE; 42LM670T-ZA; 04.41.03; 0x00000001;); LG NetCast.TV-2012 0', ) diff --git a/vphttp.py b/vphttp.py index 9046563..5670965 100644 --- a/vphttp.py +++ b/vphttp.py @@ -163,7 +163,7 @@ class HTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler): self.reqtype = self.splittedpath[1].lower() # If first parameter is 'pid' or 'torrent' or it should be handled # by plugin - if not (self.reqtype=='get' or self.reqtype in VPStuff.pluginshandlers): + if not (self.reqtype in ('get','mp4') or self.reqtype in VPStuff.pluginshandlers): self.dieWithError(400) # 400 Bad Request return except IndexError: @@ -186,6 +186,7 @@ class HTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler): def handleRequest(self, headers_only): # Limit concurrent connections + print VPStuff.clientcounter.total if 0 < VPConfig.maxconns <= VPStuff.clientcounter.total: logger.debug("Maximum connections reached, can't serve this") self.dieWithError(503) # 503 Service Unavailable @@ -193,6 +194,7 @@ class HTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler): # Pretend to work fine with Fake UAs or HEAD request. useragent = self.headers.get('User-Agent') + logger.debug("HTTP User Agent:"+useragent) fakeua = useragent and useragent in VPConfig.fakeuas if headers_only or fakeua: if fakeua: @@ -214,19 +216,19 @@ class HTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler): self.params.append('0') # Adding client to clientcounter - clients = VPStuff.clientcounter.add(self.path_unquoted, self.clientip) + clients = VPStuff.clientcounter.add(self.reqtype+'\\'+self.path_unquoted, self.clientip) # If we are the one client, but sucessfully got vp instance from clientcounter, # then somebody is waiting in the videodestroydelay state # Check if we are first client - if VPStuff.clientcounter.get(self.path_unquoted)==1: + if VPStuff.clientcounter.get(self.reqtype+'\\'+self.path_unquoted)==1: logger.debug("First client, should create VLC session") shouldcreatevp = True else: logger.debug("Can reuse existing session") shouldcreatevp = False - self.vlcid = hashlib.md5(self.path_unquoted).hexdigest() + self.vlcid = hashlib.md5(self.reqtype+'\\'+self.path_unquoted).hexdigest() # Send fake headers if this User-Agent is in fakeheaderuas tuple if fakeua: @@ -243,12 +245,9 @@ class HTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler): logger.debug("hangDetector spawned") gevent.sleep() - # Initializing VPClient - # Getting URL self.errorhappened = False - print shouldcreatevp if shouldcreatevp: logger.debug("Got url " + self.path_unquoted) # Force ffmpeg demuxing if set in config @@ -257,8 +256,9 @@ class HTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler): else: self.vlcprefix = '' + logger.debug("Ready to start broadcast....") VPStuff.vlcclient.startBroadcast( - self.vlcid, self.vlcprefix + self.path_unquoted, VPConfig.vlcmux, VPConfig.vlcpreaccess) + self.vlcid, self.vlcprefix + self.path_unquoted, VPConfig.vlcmux, VPConfig.vlcpreaccess, self.reqtype) # Sleep a bit, because sometimes VLC doesn't open port in # time gevent.sleep(0.5) @@ -311,12 +311,11 @@ class HTTPHandler(BaseHTTPServer.BaseHTTPRequestHandler): # Unknown exception logger.error(traceback.format_exc()) self.errorhappened = True - raise self.dieWithError() finally: logger.debug("END REQUEST") - VPStuff.clientcounter.delete(self.path_unquoted, self.clientip) - if not VPStuff.clientcounter.get(self.path_unquoted): + VPStuff.clientcounter.delete(self.reqtype+'\\'+self.path_unquoted, self.clientip) + if not VPStuff.clientcounter.get(self.reqtype+'\\'+self.path_unquoted): try: logger.debug("That was the last client, destroying VPClient") VPStuff.vlcclient.stopBroadcast(self.vlcid) @@ -417,7 +416,7 @@ DEVNULL = open(os.devnull, 'wb') # Spawning procedures def spawnVLC(cmd, delay = 0): try: - VPStuff.vlc = psutil.Popen(cmd, stdout=DEVNULL, stderr=DEVNULL) + VPStuff.vlc = psutil.Popen(cmd) #, stdout=DEVNULL, stderr=DEVNULL) gevent.sleep(delay) return True except: @@ -430,7 +429,6 @@ def connectVLC(): out_port=VPConfig.vlcoutport) return True except vlcclient.VlcException as e: - print repr(e) return False def isRunning(process): -- 2.34.1