transcoding option for web-video added
authorRoman Bazalevsky <rvb@rvb.name>
Thu, 23 Jul 2015 22:52:42 +0000 (01:52 +0300)
committerRoman Bazalevsky <rvb@rvb.name>
Thu, 23 Jul 2015 22:52:42 +0000 (01:52 +0300)
README.md~ [new file with mode: 0644]
clientcounter.py
plugins/m3u_plugin.py
plugins/modules/PlaylistGenerator.py
vlcclient/vlcclient.py
vlcclient/vlcmessages.py
vpconfig.py
vphttp.py

diff --git a/README.md~ b/README.md~
new file mode 100644 (file)
index 0000000..24b72df
--- /dev/null
@@ -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)
index bcfd0b2eff746eb230f48297f6a1edf2e65d6d8e..bd86cbeeeb01c499dec022991b1b032fb56a9a29 100644 (file)
@@ -34,5 +34,6 @@ class ClientCounter(object):
         else:
             return False
 
         else:
             return False
 
+        print "Total:", self.total
         return self.clients[id][0]
 
         return self.clients[id][0]
 
index 4104e43240ea63e8d6e81fc5b8332d2834e66850..cc614f2ef130095c4349a12ff902f1dd12903274 100644 (file)
@@ -17,7 +17,7 @@ import os
 
 class M3u(VPProxyPlugin):
 
 
 class M3u(VPProxyPlugin):
 
-    handlers = ('m3u', )
+    handlers = ('m3u', 'm3ut' )
 
     logger = logging.getLogger('plugin_m3u')
     playlist = None
 
     logger = logging.getLogger('plugin_m3u')
     playlist = None
@@ -28,6 +28,13 @@ class M3u(VPProxyPlugin):
 
         self.splitted_path=connection.path.split('/')
         
 
         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
         if len(self.splitted_path)>3:
             connection.dieWithError()
             return
@@ -61,7 +68,7 @@ class M3u(VPProxyPlugin):
         try:
             playlist=parseM3U(m3u_file)
         except:
         try:
             playlist=parseM3U(m3u_file)
         except:
-            connection.dieWithError()
+            connection.dieWithError(404)
             return    
 
         if not playlist:
             return    
 
         if not playlist:
@@ -76,7 +83,7 @@ class M3u(VPProxyPlugin):
             channel['url']=record.path.decode('utf-8')            
             playlistgen.addItem(channel)
 
             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)
 
         exported = exported.encode('utf-8')
         connection.wfile.write(exported)
 
index e5402b25fcec55b2cdc2dc02424358d8b1aabd48..c46197f35d6a20711efa6d359dc0718e920a269d 100644 (file)
@@ -38,7 +38,7 @@ class PlaylistGenerator(object):
             item.get('group', ''), item.get('tvg', ''), item.get('logo', ''),
             item.get('name'), item.get('url'))
 
             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
         '''
         '''
         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['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
             itemlist += PlaylistGenerator._generatem3uline(item)
 
         return itemlist
index ebe83f7c59553368bec9b1cfd9d43c2ae636ae3a..b2226997e7a2d38d4cfdb0b3b2bc45ebdc122ff9 100644 (file)
@@ -109,7 +109,7 @@ class VlcClient(object):
         except EOFError as e:
             raise VlcException("Vlc Write error! ERROR: " + repr(e))
 
         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
 
         if self._shuttingDown.isSet():
             return
 
@@ -127,8 +127,8 @@ class VlcClient(object):
         self._resultlock.acquire()
         # Write message to VLC socket
         if brtype == True:
         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))
 
         else:
             self._write(VlcMessage.request.stopBroadcast(stream_name))
 
@@ -149,8 +149,9 @@ class VlcClient(object):
         else:
             logger.debug("Broadcast stopped")
 
         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)
 
     def stopBroadcast(self, stream_name):
         return self._broadcast(False, stream_name)
index 10de03dc521d8781e3c1a215922fc28678463121..da8606c1d3ac578d47b3ae22ba105d5a8187d42a 100644 (file)
@@ -9,11 +9,14 @@ class VlcMessage(object):
         SHUTDOWN = 'shutdown'
 
         @staticmethod
         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'
                 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):
 
         @staticmethod
         def stopBroadcast(stream_name):
index ca11dd53d8e7b9baabb6b4e1f24af6779033db3d..05ecbbfa94ca23c899b7b976b1b62c72b31c193a 100644 (file)
@@ -15,7 +15,7 @@ class VPConfig():
     httpport = 8001
     # If started as root, drop privileges to this user.
     # Leave empty to disable.
     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
     # 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/'
     # Logging to a file
     loggingtoafile = False
     # Path for logs, default is current directory. For example '/tmp/'
-    logpath = ''
+    logpath = '/var/log/vpproxy/'
     #
     # ----------------------------------------------------
     # VLC configuration
     #
     # ----------------------------------------------------
     # VLC configuration
@@ -42,10 +42,10 @@ class VPConfig():
     # Spawn VLC automaticaly
     vlcspawn = True
     # VLC cmd line (use `--file-logging --logfile=filepath` to write log)
     # 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!'
     # 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
     # 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)',
     # 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',
                      )
                      )
index 904656368a089d160b6524b3c09521fcdcbbc3e4..5670965c84638b5c31807658631677c132ec3c01 100644 (file)
--- 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
             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:
                 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
     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
         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')
 
         # 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:
         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
                 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 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
 
             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:
 
         # 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()
 
             logger.debug("hangDetector spawned")
             gevent.sleep()
 
-            # Initializing VPClient
-
             # Getting URL
             self.errorhappened = False
 
             # Getting URL
             self.errorhappened = False
 
-            print shouldcreatevp
             if shouldcreatevp:
                 logger.debug("Got url " + self.path_unquoted)
                 # Force ffmpeg demuxing if set in config
             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 = ''
 
                 else:
                     self.vlcprefix = ''
 
+                logger.debug("Ready to start broadcast....")                    
                 VPStuff.vlcclient.startBroadcast(
                 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)
                 # 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
             # Unknown exception
             logger.error(traceback.format_exc())
             self.errorhappened = True
-            raise
             self.dieWithError()
         finally:
             logger.debug("END REQUEST")
             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)
                 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:
 # 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:
         gevent.sleep(delay)
         return True
     except:
@@ -430,7 +429,6 @@ def connectVLC():
             out_port=VPConfig.vlcoutport)
         return True
     except vlcclient.VlcException as e:
             out_port=VPConfig.vlcoutport)
         return True
     except vlcclient.VlcException as e:
-        print repr(e)
         return False
 
 def isRunning(process):
         return False
 
 def isRunning(process):