Audio/video stream recording forums 
 | 
| Attention Visitor: | 
You may have to register or log in before you can post: 
  | 
		
			
  | 	
	
	
		
		|||||||
     
		  
 
	
	 | 
| 
		 | 
	Thread Tools | Display Modes | 
| 
		 
			 
			#1  
			
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
	
	
		
			
			librtmp and pythonHi everybody, 
		
	
		
		
		
		
		
	
		
		
	
	
	since a few days I'm facing a very stressful issue with librtmp and python 2.7 (my os is Windows 7). I'm trying to connect to a stream on justin tv but I've probably an encoding issue with jtv token string. Here is my code: Code: 
	        print 'instantiate rtmp connection'
        r = dll.RTMP_Alloc()
        dll.RTMP_Init(r)
        dll.RTMP_SetupURL(r, c_char_p(tcUrl))
        
        print 'connect to stream'
        dll.RTMP_Connect(r, None)
        
        print 'read stream'
        dll.RTMP_Read(r)
tcUrl=rtmp://199.9.255.143/app/jtv_toTs9DzRvV8WPazW swfUrl=http://www-cdn.jtvnw.net/widgets/live_site_player.ra3170e7f148ff63b2f1b4dfef2840842 de54e7f8 .swf token=a6faa3f74e0927e80039bb612522d637530d6395:{\" swfDomains\": [\"justin.tv\", \"jtvx.com\", \"xarth.com\", \"twitchtv.com\", \"twitch.tv\", \"n ewjtv.com\", \"jtvnw.net\", \"wdtinc.com\", \"imapweather.com\", \"facebook.com\", \"starcrafting.com\"], \"streamName\": \"jtv_toTs9DzRvV8WPazW\", \" expiration\": 1332084704.643841, \"geo_ip\": \"82.243.172.91\", \"server\": \"lhr01-video3-2\"} does anybody knows how to fix this? Thanks Regards, Gontran  | 
| 
		 
			 
			#2  
			
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
	
	
		
			
			Re: librtmp and pythonQuote: 
	
 Code: 
	Special characters in values may need to be escaped to prevent misinterpretation by the option parser. The escape encoding uses a backslash followed by two hexadecimal digits representing the ASCII value of the character. E.g., spaces must be escaped as \20 and backslashes must be escaped as \5c. Code: 
	jtv=a6faa3f74e0927e80039bb612522d637530d6395:{\22\20swfDomains\22:\20[\22justin.tv\22,\20\22jtvx.com\22,\20\22xarth.com\22,\20\22twitchtv.com\22,\20\22twitch.tv\22,\20\22newjtv.com\22,\20\22jtvnw.net\22,\20\22wdtinc.com\22,\20\22imapweather.com\22,\20\22facebook.com\22,\20\22starcrafting.com\22],\20\22streamName\22:\20\22jtv_toTs9DzRvV8WPazW\22,\20\22expiration\22:\201332084704.643841,\20\22geo_ip\22:\20\2282.243.172.91\22,\20\22server\22:\20\22lhr01-video3-2\22}
 | 
| 
		 
			 
			#3  
			
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
	
	
		
			
			Re: librtmp and pythonThank you KSV, you made my day. 
		
	
		
		
		
		
		
	
		
		
	
	
	Though I read the doc, I dont understand how I missed that!  | 
| 
		 
			 
			#4  
			
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
	
	
		
			
			Re: librtmp and pythonNow that I managed to retrieve a stream, I would like to get log from librtmp. 
		
	
		
		
		
		
		
		
			According to ctypes documentation and given functions signatures from log.h/log.c, I wrote this in my code: Code: 
	CMPFUNC = CFUNCTYPE(c_int, c_int, c_char_p, c_void_p)
def logCallBack(level, message, va_list):
    dll.RTMP_LogPrintf(message, va_list)
    return 0
mLogCallBack = CMPFUNC(logCallBack)
...
dll.RTMP_LogSetCallback(mLogCallBack)
Code: 
	Parsed host    : ☺Parsed app     : ☺connect to stream
ÄßGj♫¨', ... connected, handshaking?ßGj♥: Type Answer   : 27DBEC?ßGjä?┼♣: Server Uptime : 2612204?ßGj♥: FMS Version   : 2612204.2612100.488283845.4882
83530?ßGj♥: Handshaking finished....ÄßGj♫¨', handshaked│°Gj♀☻: fd=2614284, size=2614180Invoking ▒?'ä°Gj♀☻: fd=2618556`÷Gjá%&: server BW = 2618572ä°Gj♀
☻: fd=2618556o÷Gjá%&: client BW = 2618572 2618468ä°Gj♀☻: fd=2618556?÷Gj, received ctrl. type: 2618572, len: 2618468?÷Gj, Stream Begin 2618572ä°Gj♀☻: f
d=26185568÷Gj, received: chunk size change to 2618572ä°Gj♀☻: fd=2618556N÷Gj♣☺, received: invoke 2618572 bytes(object begin)Property: <|±'☺>Property: <
|±'☺>Property: <|±'OBJECT>(object begin)Property: <,´'☺>Property: <,´'☺>Property: <,´'☺>(object end)Property: <|±'OBJECT>(object begin)Property: <,´'☺
>Property: <,´'☺>Property: <,´'☺>Property: <,´'OBJECT>(object begin)Property: <▄ý'☺>(object end)Property: <,´'☺>Property: <,´'☺>(object end)(object en
d)~÷Gjmt;, server invoking <☺>~÷Gj, received result for method call <☺>│°Gj♀☻: fd=2616844, size=2616740sending ctrl. type: 0x27f264│°Gj♀☻: fd=2616828,
 size=2616724│°Gj♀☻: fd=2616828, size=2616724Invoking ?‗'UsherToken: ú?B☻,☺│°Gj♀☻: fd=2617164, size=2617060Invoking )¶'ä°Gj♀☻: fd=2618556N÷Gj↔, receiv
ed: invoke 2618572 bytes(object begin)Property: <|±'☺>Property: <|±'☺>Property: NULLProperty: <|±'☺>(object end)~÷Gj?⌂;, server invoking <☺>~÷Gj8¶;, r
eceived result for method call <☺>¶÷Gj, seekTime=2617308, stopTime=2617204, sending play: â─↑?♥â╚*?e¶╔├U?ýâý►SVW?¨?w►?E*ëE??F♦┴Ó☻?┌??↨│°Gj♀☻: fd=26171
64, size=2617060Invoking )¶'sending ctrl. type: 0x27f264│°Gj♀☻: fd=2616828, size=2616724ä°Gj♀☻: fd=2618556N÷Gj%, received: invoke 2618572 bytes(object
 begin)Property: <|±'☺>Property: <|±'☺>Property: NULLProperty: <|±'☺>(object end)~÷Gj?⌂;, server invoking <☺>~÷Gj, received result id 2617308 without
matching requestä°Gj♀☻: fd=2618556?÷Gj, received ctrl. type: 2618572, len: 2618468?÷Gj☺, Stream Begin 2618572ä°Gj♀☻: fd=2618556N÷Gjö, received: invoke
 2618572 bytes(object begin)Property: <|±'☺>Property: <|±'☺>Property: NULLProperty: <|±'OBJECT>(object begin)Property: <,´'☺>Property: <,´'☺>Property:
 <,´'☺>Property: <,´'☺>(object end)(object end)~÷Gj?t;, server invoking <☺>~÷Gj┴t;, onStatus: ☺ä°Gj♀☻: fd=2618556N÷Gj?, received: invoke 2618572 bytes
(object begin)Property: <|±'☺>Property: <|±'☺>Property: NULLProperty: <|±'OBJECT>(object begin)Property: <,´'☺>Property: <,´'☺>Property: <,´'☺>Propert
y: <,´'☺>Property: <,´'☺>Property: <,´'☺>(object end)(object end)~÷Gj?t;, server invoking <☺>~÷Gj┴t;, onStatus: ☺read stream
ä°Gj♀☻: fd=2618348N÷Gj,, received: notify 2618364 bytes(object begin)Property: <(§'☺>Property: <(§'OBJECT>(object begin)Property: <?‗'☺>(object end)(o
bject end)ä°Gj♀☻: fd=2618348ä°Gj♀☻: fd=2618348N÷Gj?♥, received: notify 2618364 bytes(object begin)Property: <(§'☺>Property: <(§'OBJECT>(object begin)P
roperty: <?‗'☺>Property: <?‗'☺>Property: <?‗'☺>Property: <?‗'☺>Property: <?‗'☺>Property: <?‗'☺>Property: <?‗'☺>Property: <?‗'☺>Property: <?‗'☺>Propert
y: <?‗'☺>Property: <?‗'☺>Property: <?‗'OBJECT>(object begin)Property: <?*'OBJECT>(object begin)Property: <8?'☺>Property: <8?'☺>Property: <8?'OBJECT>(o
bject begin)Property: <??'OBJECT>(object begin)Property: <?Ú'☺>(object end)(object end)Property: <8?'☺>(object end)Property: <?*'OBJECT>(object begin)
Property: <8?'☺>Property: <8?'☺>Property: <8?'OBJECT>(object begin)Property: <??'OBJECT>(object begin)Property: <?Ú'☺>(object end)(object end)Property
: <8?'☺>Property: <8?'☺>Property: <8?'☺>Property: <8?'☺>(object end)(object end)Property: <?‗'OBJECT>(object begin)Property: <?*'☺>Property: <?*'☺>Pro
perty: <?*'☺>Property: <?*'☺>Property: <?*'☺>Property: <?*'☺>Property: <?*'OBJECT>(object begin)Property: <8?'☺>Property: <8?'☺>Property: <8?'☺>(objec
t end)(object end)(object end)(object end)Metadata:  ☺                     ,±'  ☺                     ,±'  ☺                     ,±'  ☺
      ,±'  ☺                     ,±'  ☺                     ,±'  ☺                     ,±'  ☺                     ,±'  ☺                     ,±'  ☺
                  ,±'  ☺                     ,±'☺:  ☺                     î?'  ☺                     î?'☺:  ☺                     ý?'  ☺
       î?'  ☺                     î?'  ☺                     î?'☺:  ☺                     ý?'  ☺                     î?'  ☺                     î?'  ☺
                     î?'  ☺                     î?'☺:  ☺                     ▄´'  ☺                     ▄´'  ☺                     ▄´'  ☺
        ▄´'  ☺                     ▄´'  ☺                     ▄´'☺:  ☺                     î?'  ☺                     î?'  ☺                     î?'ä°
Gj♀☻: fd=2618348│°Gj♀☻: fd=2618172, size=2618068Invoking ı¸'
Code: 
	%s, ... connected, handshaking %s: Type Answer : %02X %s: Server Uptime : %d %s: FMS Version : %d.%d.%d.%d %s: Handshaking finished.... %s, handshaked %s: fd=%d, size=%d Invoking %s %s: fd=%d %s: server BW = %d %s: fd=%d %s: client BW = %d %d %s: fd=%d %s, received ctrl. type: %d, len: %d ... That 's why I'm asking for help. Thanks in advance. Regards, Gontran Last edited by Gontran : 03-20-2012 at 05:42 AM.  | 
| 
		 
			 
			#5  
			
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
	
	
		
			
			Re: librtmp and pythonI am not a python coder so i can't provide you a definite answer. but what you are referring as message in your code is actually format string. va_list contains the actual data to be filled in format string to create complete string. you can't pass va_list to another function. try to use PyArg_VaParse. 
		
	
		
		
		
		
		
	
		
		
	
	
	 | 
| 
		 
			 
			#6  
			
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
	
	
		
			
			Re: librtmp and pythonThank you KSV for your concern but as far as I know, PyArg_VaParse has to be used in c programms. 
		
	
		
		
		
		
		
	
		
		
	
	
	I tried to reproduce the same code as shown in this thread (http://stream-recorder.com/forum/usi...n-t11025.html? but this doesn't work. Anyway, I'll dig deeper tonight. Regards, Gontran  | 
| 
		 
			 
			#7  
			
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
	
	
		
			
			Re: librtmp and pythonJust don't pay attention to my last messages: I was tired and doing all wrong! 
		
	
		
		
		
		
		
	
		
		
	
	
	The only thing needed was to set the log level (by default nothing) in order to see logs in the standard output: Code: 
	#That's all!!!! dll.RTMP_LogSetLevel(c_int(6))  | 
| 
		 
			 
			#8  
			
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
	
	
		
			
			Re: librtmp and pythonAs I said earlier, here a little class that wraps librtmp in order to get streams: 
		
	
		
		
		
		
		
	
		
		
	
	
	Code: 
	# -*- coding: utf-8 -*-
import os
from ctypes import cdll, c_char_p, c_int, create_string_buffer, sizeof
class RTMP:
    """
    This class encapsulates librtmp.dll in order to connect to a RTMP server and get video stream.
    RTMPDUMP website : http://rtmpdump.mplayerhq.hu
    LIBRTMP manpage  : http://rtmpdump.mplayerhq.hu/librtmp.3.html
    """
    
    LogLevel = {
        "RTMP_LOGCRIT"      : c_int(0),
        "RTMP_LOGERROR"     : c_int(1),
        "RTMP_LOGWARNING"   : c_int(2),
        "RTMP_LOGINFO"      : c_int(3),
        "RTMP_LOGDEBUG"     : c_int(4),
        "RTMP_LOGDEBUG2"    : c_int(5),
        "RTMP_LOGALL"       : c_int(6)
    }
    
    def __init__(self, tcURL, output_file_path, log_level=LogLevel["RTMP_LOGINFO"], buffer_size=64 * 1024):
        # Load library
        if os.name == 'nt':
            self.lib = cdll.LoadLibrary('lib/librtmp.dll')
        elif os.name == 'posix':
            # TODO: load library for posix os
            pass
            
        # Initialize variables
        self.tcURL              = tcURL
        self.output_file_path   = output_file_path
        self.log_level          = log_level
        self.buffer_size        = buffer_size
    
    #************************************************************************
    # Wrap native library functions
        
    def Alloc(self):
        """Return a pointer to a new RTMP object"""
        return self.lib.RTMP_Alloc()
    
    def Init(self, r_pointer):
        """Init the RTMP object"""
        self.lib.RTMP_Init(r_pointer)
        return None
    
    def SetupURL(self, r_pointer, tcURL):
        """
        Setup the rtmp url
        The rtmp url format is of the form
        rtmp[t][e|s]://hostname[:port][/app[/playpath]]
        """
        self.lib.RTMP_SetupURL(r_pointer, c_char_p(tcURL))
        return None
    
    def Connect(self, r_pointer):
        """Established network connection"""
        self.lib.RTMP_Connect(r_pointer, None)
        return None
        
    def ConnectStream(self, r_pointer):
        """Established RTMP session"""
        self.lib.RTMP_ConnectStream(r_pointer, 0)
        return None
        
    def Read(self, r_pointer, buffer):
        """
        Reads bytes from the stream an write its into the buffer.
        Returns the number of bytes read
        When it returns 0 bytes, the stream is complete and may be closed
        """
        return self.lib.RTMP_Read(r_pointer, buffer, sizeof(buffer))
        
    def Close(self, r_pointer):
        """ Closes the connection """
        self.lib.RTMP_Close(r_pointer)
        return None
        
    def Free(self, r_pointer):
        """ Frees the session """
        self.lib.RTMP_Free(r_pointer)
        return None
        
    def LogSetLevel(self, log_level):
        """ Defines RTMP_LogLevel used by output """
        self.lib.RTMP_LogSetLevel(log_level)
        return None
        
    #************************************************************************
    
    def getVideoStream(self):
        """
        Get the video stream from the rtmp server
        """
        # Try to open the output file
        try:
            output_file = open(self.output_file_path, 'wb')
        except:
            print "Cannot open output file.\n Please check the output_file_path\n. Aborting."
            return None
            
        # Instantiate buffer
        buffer = create_string_buffer(self.buffer_size)
        
        # Set LogLevel
        self.LogSetLevel(self.log_level)
        
        # Setup RTMP connection
        r_pointer = self.Alloc()
        self.Init(r_pointer)
        self.SetupURL(r_pointer, self.tcURL)
        
        # Connect and establish session
        self.Connect(r_pointer)
        self.ConnectStream(r_pointer)
        
        # Read stream
        try:
            while True:
                # While result > 0, write buffer bytes into output_file
                result = self.Read(r_pointer, buffer)
                output_file.write(buffer[:result])
                if result == 0:
                    break
        except:
            # Handles exception in order to close session and file properly
            print "An exception occured. Ending session."
        
        # Ends session and closes output_file
        self.Close(r_pointer)
        self.Free(r_pointer)
        output_file.close()
Code: 
	# construct the url before as mentionned in librtmp manpage m_rtmp = RTMP(tcUrl, 'out_file.flv') m_rtmp.getVideoStream() Hope this will be usefull! Regards, Gontran  | 
| 
		 
			 
			#9  
			
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
	
	
		
			
			Re: librtmp and pythonQuote: 
	
 I started work on something similar about a month ago and I'm surpirsed your script works. I had to define custom ctype structure & union classes for my script, other wise it would complain about segmentation faults. I am running linux though, so maybe windows doesn't care as much.  | 
| 
		 
			 
			#10  
			
			
			
			
			
		 
		
		
	 | 
|||
		
		
  | 
|||
	
	
		
			
			Re: librtmp and pythongontran,i see your ip on 1 post or not? 
		
	
		
		
		
		
		
	
		
		
	
	
	 | 
 
 
 | 
		
	
		
| Tags: librtmp, python | 
| Thread Tools | |
| Display Modes | |
		
  | 
	
		
  |