weixin_44276095 2019-12-16 16:38 采纳率: 0%
浏览 474
已采纳

使用python实现rtsp客户端遇见的setup消息发送的问题

使用python实现rtsp客户端的setup消息发送时返回状态码为503;现在不知如何解决,遂请求帮助。有偿+wx:ww1194609610(10rmb)

import socket
from urllib.parse import urlparse
config_dict = {
    'cseq': 2,
    'user_agent': 'LibVLC/3.0.2 (LIVE555 Streaming Media v2016.11.28)',
    'timeout': 3,
    'recvbite': 4096,
    'res_status': '200 OK',
    'rtsp_status': 'flase'
}

clientports=[60784, 60785]
def options_get(url):
    '''
    options请求检测
    url: rtsp流地址
    return: options请求相应
    '''
    url = urlparse(url)
    host = url.netloc
    hostname = url.hostname
    path = url.path
    port = url.port
    str_options = 'OPTIONS rtsp://' + str(host) + \
                         path + ' RTSP/1.0\r\n'
    str_options += 'CSeq: ' + str(config_dict['cseq']) + '\r\n'
    str_options += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
    str_options += '\r\n'
    print(str_options)
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.settimeout(config_dict['timeout'])
    client.connect((hostname, port))
    client.send(str_options.encode())
    d = client.recv(config_dict['recvbite'])
    return d
def describe_get(url):
    '''
    describe请求检测
    url: rtsp流地址
    return: describe请求相应
    '''
    url = urlparse(url)
    host = url.netloc
    hostname = url.hostname
    path = url.path
    port = url.port
    str_describe = 'DESCRIBE rtsp://' + str(host) + \
                         path + ' RTSP/1.0\r\n'
    str_describe += 'CSeq: ' + str(config_dict['cseq'] + 1) + '\r\n'
    str_describe += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
    str_describe += '\r\n'
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.settimeout(config_dict['timeout'])
    client.connect((hostname, port))
    client.send(str_describe.encode())
    d = client.recv(config_dict['recvbite'])
    return d
def setup_get(url):
    '''
    setup请求检测
    url: rtsp流地址
    return: setup请求相应
    '''
    url = urlparse(url)
    host = url.netloc
    hostname = url.hostname
    path = url.path
    port = url.port
    str_setup = 'SETUP rtsp://' + str(host) + path + '/' + 'streamid=0' + ' RTSP/1.0\r\n'
    str_setup += 'CSeq: ' + str(config_dict['cseq'] + 2) + '\r\n'
    str_setup += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
    # config_dict['user_agent']
    str_setup += 'Transport: RTP/AVP;unicast;client_port=61740-61741\r\n\r\n'
    str_setup += '\r\n'
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.settimeout(config_dict['timeout'])
    client.connect((hostname, port))
    client.send(str_setup.encode())
    d = client.recv(config_dict['recvbite'])
    return d
def teardown_get(url):
    '''
    teardown请求检测
    url: rtsp流地址
    return: teardown请求相应
    '''
    url = urlparse(url)
    host = url.netloc
    hostname = url.hostname
    path = url.path
    port = url.port
    str_teardown = 'TEARDOWN rtsp://' + str(host) + path + ' RTSP/1.0\r\n'
    str_teardown += 'CSeq: ' + str(config_dict['cseq'] + 4) + '\r\n'
    str_teardown += 'User-Agent: ' + config_dict['user_agent'] + '\r\n'
    str_teardown += '\r\n'
    print(str_teardown)
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.settimeout(config_dict['timeout'])
    client.connect((hostname, port))
    client.send(str_teardown.encode())
    d = client.recv(config_dict['recvbite'])
    return d
def send_main(url):
    try:
        str_options = str(options_get(url))
        print(str_options)
        if config_dict['res_status'] in str_options:
            str_des = str(describe_get(url))
            print(str_des)
            if config_dict['res_status'] in str_des:
                str_setup = str(setup_get(url))
                str_teardown = str(teardown_get(url))
                print(str_setup)
                print(str_teardown)
                if config_dict['res_status'] in str_teardown:
                    config_dict['rtsp_status'] = 'true'
                    return True
    except Exception:
        return False
    else:
        return False
print(send_main('rtsp://192.168.10.214:554/live/av0'))

上方为我的代码。
b'RTSP/1.0 503 Service Unavailable\r\nCSeq: 4\r\nDate: Thu, 01 Jan 1970 07:11:16 GMT\r\n\r\n' 此段消息为setup请求的返回信息,我看过rtsp的相关文档,说describe请求返回的sdp信息,客户端再分析该SDP描述,并为会话中的每一个流发送一个RTSP建立命令( SETUP)。这个我没搞懂,也不知道如何写,这里进行请教一下。
下面是我的一次正常的rtsp交互信息。

OPTIONS rtsp://192.168.10.214:554/live/av0 RTSP/1.0
CSeq: 2
User-Agent: LibVLC/3.0.5 (LIVE555 Streaming Media v2016.11.28)

RTSP/1.0 200 OK
CSeq: 2
Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE

DESCRIBE rtsp://192.168.10.214:554/live/av0 RTSP/1.0
CSeq: 3
User-Agent: LibVLC/3.0.5 (LIVE555 Streaming Media v2016.11.28)
Accept: application/sdp

RTSP/1.0 200 OK
CSeq: 3
Date: Thu, 01 Jan 1970 07:05:17 GMT
Content-Base: rtsp://192.168.10.214:554/live/av0/
Content-Type: application/sdp
Content-Length: 315

v=0
o=- 0 0 IN IP4 127.0.0.1
s=No Title
c=IN IP4 0.0.0.0
t=0 0
a=tool:libavformat 55.12.100
m=video 0 RTP/AVP 96
a=rtpmap:96 H264/90000
a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAKq2EAQwgCGEAQwgCGEAQwgCEK1A8ARPyzcBAQFAAAAMAEAAAAwPIQA==,aO48sA==; profile-level-id=64002A
a=control:streamid=0
SETUP rtsp://192.168.10.214:554/live/av0/streamid=0 RTSP/1.0
CSeq: 4
User-Agent: LibVLC/3.0.5 (LIVE555 Streaming Media v2016.11.28)
Transport: RTP/AVP;unicast;client_port=61740-61741

RTSP/1.0 200 OK
CSeq: 4
Date: Thu, 01 Jan 1970 07:05:17 GMT
Session: 093634014dba841b
Transport: RTP/AVP/UDP;unicast;client_port=61740-61741;server_port=20006-20007

PLAY rtsp://192.168.10.214:554/live/av0/ RTSP/1.0
CSeq: 5
User-Agent: LibVLC/3.0.5 (LIVE555 Streaming Media v2016.11.28)
Session: 093634014dba841b
Range: npt=0.000-

RTSP/1.0 200 OK
CSeq: 5
Date: Thu, 01 Jan 1970 07:05:17 GMT
Session: 093634014dba841b

TEARDOWN rtsp://192.168.10.214:554/live/av0/ RTSP/1.0
CSeq: 6
User-Agent: LibVLC/3.0.5 (LIVE555 Streaming Media v2016.11.28)
Session: 093634014dba841b

RTSP/1.0 200 OK
CSeq: 6
Date: Thu, 01 Jan 1970 07:05:21 GMT
Session: 093634014dba841b
  • 写回答

1条回答 默认 最新

  • bobhuang 2019-12-16 17:12
    关注

    如果只是要实现播放,建议用直接处理媒体功能的库,因为rtp/rtsp/sdp相关的协议解析和控制比较复杂,不是几百行代码能解决的问题。
    这是用vlc库实现播放的例子: https://www.cnblogs.com/zhangyi-studio/p/9164453.html
    这是用cv2库实现播放的例子: https://blog.csdn.net/jiadianyong12138/article/details/80433063

    这是解析sdp信息,并将媒体流保存为文件的例子: https://codeday.me/bug/20180823/226972.html

    如果是想理解rtsp从传输到播放,并通过python代码来逐步调试这个过程,并且目前卡在sdp解析上,那么从这里入手:
    你例子中的第三条消息,其中有个rtsp header域是“Content-Type: application/sdp”,说明后续的内容是sdp。具体就是“v=0”到“Transport: RTP/AVP;unicast;client_port=61740-61741”的内容。
    如何解析参考第三个链接,如果还不清楚,就要啃RFC文档了:RFC 4566

    解出sdp之后,用其中的媒体信息初始化本地播放环境,用其中的传输信息IP+port来创建rtp流。收数据也是参考链接3, 主要是这几行:

    s1=socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    s1.bind(("", clientports[0])
    s1.settimeout(5) 
    f=open(fname,'w')
    for i in range(rn):
      print
      print
      recst=s1.recv(4096)
      print "read",len(recst),"bytes"
      st=digestpacket(recst)
      print "dumping",len(st),"bytes"
      f.write(st)
    f.close()
    
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥100 微信小程序跑脚本授权的问题
  • ¥100 房产抖音小程序苹果搜不到安卓可以付费悬赏
  • ¥15 STM32串口接收问题
  • ¥15 腾讯IOA系统怎么在文件夹里修改办公网络的连接
  • ¥15 filenotfounderror:文件是存在的,权限也给了,但还一直报错
  • ¥15 MATLAB和mosek的求解问题
  • ¥20 修改中兴光猫sn的时候提示失败
  • ¥15 java大作业爬取网页
  • ¥15 怎么获取欧易的btc永续合约和交割合约的5m级的历史数据用来回测套利策略?
  • ¥15 有没有办法利用libusb读取usb设备数据