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 04: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 | |
|
|