rtsp,java实现简单的rtsp报文交换(代码片段)

梦鸢MoYuan 梦鸢MoYuan     2023-04-04     745

关键词:

这里写目录标题

  1. 了解RTSP协议
  2. 使用Java程序编写RTSP客户端 访问 RTSP服务端,实现拉流

RTSP协议是什么

RTSP是一种基于文本的协议,用CRLF(回车换行)作为每一行的结束符,其好处是,在使用过程中可以方便地增加自定义参数,也方便抓包分析。从消息传送方向上来分,RTSP的报文有两类:请求报文和响应报文。请求报文是指从客户端向服务器发送的请求(也有少量从服务器向客户端发送的请求),响应报文是指从服务器到客户端的回应。

RTSP请求报文的常用方法与作用

一次基本的RTSP交互过程如下,C表示客户端,S表示服务端。

  1. OPTION请求
    -> 响应
  2. DESCRIBE请求
    -> 响应
    如果响应无权限, 那么需要带上用户名密码
  3. SETUP请求
    -> 响应
  4. PLAY请求
    -> 响应

-> 流数据
-> 流数据
-> 流数据

报文实例:

1. OPTIONS

OPTIONS rtsp://39.170.35.150:1554/h264/ch0/1 RTSP/1.0
CSeq: 2
User-Agent: LibVLC/3.0.16 (LIVE555 Streaming Media v2016.11.28)
RTSP/1.0 200 OK
CSeq: 2
Public: OPTIONS, DESCRIBE, PLAY, PAUSE, SETUP, TEARDOWN, SET_PARAMETER, GET_PARAMETER
Date:  Sat, Mar 05 2022 15:39:55 GMT

2. DESCRIBE

DESCRIBE rtsp://39.170.35.150:1554/h264/ch0/1 RTSP/1.0
CSeq: 3
User-Agent: LibVLC/3.0.16 (LIVE555 Streaming Media v2016.11.28)
Accept: application/sdp
RTSP/1.0 401 Unauthorized
CSeq: 3
WWW-Authenticate: Digest realm="2857be191e08", nonce="5b960b3d4673be2908666321f64d2bff", stale="FALSE"
WWW-Authenticate: Basic realm="2857be191e08"
Date:  Sat, Mar 05 2022 15:39:55 GMT

发现无权, 使用用户名密码进行授权

DESCRIBE rtsp://39.170.35.150:1554/h264/ch0/1 RTSP/1.0
CSeq: 4
Authorization: Digest username="admin", realm="2857be191e08", nonce="5b960b3d4673be2908666321f64d2bff", uri="rtsp://39.170.35.150:1554/h264/ch0/1", response="3cfc28bcf70670c2120acc3b5d1357d3"
User-Agent: LibVLC/3.0.16 (LIVE555 Streaming Media v2016.11.28)
Accept: application/sdp
RTSP/1.0 200 OK
CSeq: 4
Content-Type: application/sdp
Content-Base: rtsp://39.170.35.150:1554/h264/ch0/1/
Content-Length: 569

v=0
o=- 1646494795935543 1646494795935543 IN IP4 10.2.144.4
s=Media Presentation
e=NONE
b=AS:5050
t=0 0
a=control:rtsp://39.170.35.150:1554/h264/ch0/1/
m=video 0 RTP/AVP 96
c=IN IP4 0.0.0.0
b=AS:5000
a=recvonly
a=x-dimensions:1920,1080
a=control:rtsp://39.170.35.150:1554/h264/ch0/1/trackID=1
a=rtpmap:96 H264/90000
a=fmtp:96 profile-level-id=420029; packetization-mode=1; sprop-parameter-sets=Z00AKpWoHgCJ+WbgICAgQA==,aO48gA==
a=Media_header:MEDIAINFO=494D4B48010100000400000100000000000000000000000000000000000000000000000000000000;
a=appversion:1.0

4. SETUP

这里得URL后会带上control后的trackID
这里的Transport表示要使用的传输方式, TCP表示使用tcp传输, 也可以使用UDP

SETUP rtsp://39.170.35.150:1554/h264/ch0/1/trackID=1 RTSP/1.0
CSeq: 5
Authorization: Digest username="admin", realm="2857be191e08", nonce="5b960b3d4673be2908666321f64d2bff", uri="rtsp://39.170.35.150:1554/h264/ch0/1/", response="80324f6c8f797633475816843f329b61"
User-Agent: LibVLC/3.0.16 (LIVE555 Streaming Media v2016.11.28)
Transport: RTP/AVP/TCP;unicast;interleaved=0-1
RTSP/1.0 200 OK
CSeq: 5
Session:       2007782907;timeout=60
Transport: RTP/AVP/TCP;unicast;interleaved=0-1;ssrc=762c0e39;mode="play"
Date:  Sat, Mar 05 2022 15:39:55 GMT

5. PLAY

PLAY rtsp://39.170.35.150:1554/h264/ch0/1/ RTSP/1.0
CSeq: 6
Authorization: Digest username="admin", realm="2857be191e08", nonce="5b960b3d4673be2908666321f64d2bff", uri="rtsp://39.170.35.150:1554/h264/ch0/1/", response="f88f707756441a9437f162d68ec5adbb"
User-Agent: LibVLC/3.0.16 (LIVE555 Streaming Media v2016.11.28)
Session: 2007782907
Range: npt=0.000-
RTSP/1.0 200 OK
CSeq: 6
Session:       2007782907
RTP-Info: url=rtsp://39.170.35.150:1554/h264/ch0/1/trackID=1;seq=40895;rtptime=1378373026
Date:  Sat, Mar 05 2022 15:39:56 GMT

后续就会有二进制流进来.

Java实现简单的RTSP报文交换

RTSP端口默认为:1554
通过TCP对目标主机端口发起连接,然后使用RTSP格式的报文进行交换信息即可。

下面是报文拼凑的代码,使用建立TCP连接后安装RTSP规定的通讯顺序发送即可。

	// 定义协议头和通用信息
    private String transport = "RTP/AVP/TCP;unicast;interleaved=0-1";
    private static final String VERSION = " RTSP/1.0";
    private static final String RTSP_OK = "RTSP/1.0 200 OK";  
        private String address =  "rtsp://admin:shinemo123@39.170.35.150:1554/h264/ch0/1";  // RTSP URI 包含目标ip和账号密码
        private String sessionid;  // RTSP 是有状态的,通讯成功后需要记录 sessionId
    private void doTeardown()   
        StringBuilder sb = new StringBuilder();  
        sb.append("TEARDOWN ");  
        sb.append(this.address);  
        sb.append("/");  
        sb.append(VERSION);
        sb.append(System.lineSeparator());
        sb.append("Cseq: ");
        sb.append(seq++);  
        sb.append(System.lineSeparator());
        sb.append("User-Agent: RealMedia Player HelixDNAClient/10.0.0.11279 (win32)");
        sb.append(System.lineSeparator());
        sb.append("Session: ");  
        sb.append(sessionid);
        sb.append(System.lineSeparator());
        sb.append(System.lineSeparator());
        send(sb.toString().getBytes());  
    
  
    private void doPlay()   
        StringBuilder sb = new StringBuilder();  
        sb.append("PLAY ");  
        sb.append(this.address);  
        sb.append(VERSION);
        sb.append(System.lineSeparator());
        sb.append("Session: ");
        sb.append(sessionid);  
        sb.append(System.lineSeparator());
        sb.append("Cseq: ");
        sb.append(seq++);
        sb.append(System.lineSeparator());
        sb.append("Range: npt=0.000-");
        sb.append(System.lineSeparator());
        sb.append(System.lineSeparator());
        send(sb.toString().getBytes());  
    
  
    private void doSetup()   
        StringBuilder sb = new StringBuilder();  
        sb.append("SETUP ");  
        sb.append(this.address);  
        sb.append("/");  
        sb.append(trackInfo);  
        sb.append(VERSION);
        sb.append(System.lineSeparator());

        sb.append("Cseq: ");  
        sb.append(seq++);  
        sb.append(System.lineSeparator());
        sb.append("Transport: ");
        sb.append(transport);
        sb.append(System.lineSeparator());
        sb.append(System.lineSeparator());
        send(sb.toString().getBytes());  
      
  
    private void doOption()   
        StringBuilder sb = new StringBuilder();  
        sb.append("OPTIONS ");  
        sb.append(this.address.substring(0, address.lastIndexOf("/")));  
        sb.append(VERSION);
        sb.append(System.lineSeparator());

        sb.append("Cseq: ");  
        sb.append(seq++);  
        sb.append(System.lineSeparator());
        sb.append(System.lineSeparator());
        send(sb.toString().getBytes());  
      
  
    private void doDescribe()   
        StringBuilder sb = new StringBuilder();  
        sb.append("DESCRIBE ").append(this.address).append(VERSION).append(System.lineSeparator());
        sb.append("Cseq: ").append(seq++).append(System.lineSeparator());
        sb.append("Accept: application/sdp").append(System.lineSeparator());

        sb.append(System.lineSeparator());
        System.out.println(sb.toString());  
        send(sb.toString().getBytes());  
      
      
    private void doPause()   
        StringBuilder sb = new StringBuilder();  
        sb.append("PAUSE ");  
        sb.append(this.address);  
        sb.append("/");  
        sb.append(VERSION);
        sb.append(System.lineSeparator());

        sb.append("Cseq: ");  
        sb.append(seq++);  
        sb.append(System.lineSeparator());
        sb.append("Session: ");  
        sb.append(sessionid);
        sb.append(System.lineSeparator());
        sb.append(System.lineSeparator());
        send(sb.toString().getBytes());  
    

完整的垃圾代码:
这里使用的是netty。

package loki.rtsp;

import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;

import java.io.IOException;
import java.net.InetSocketAddress;  
import java.nio.ByteBuffer;  
import java.nio.channels.SelectionKey;  
import java.nio.channels.Selector;  
import java.nio.channels.SocketChannel;  
import java.util.Iterator;
import java.util.concurrent.atomic.AtomicBoolean;
  
public class RTSPClient extends Thread implements IEvent   
  
    private static final String VERSION = " RTSP/1.0";
    private static final String RTSP_OK = "RTSP/1.0 200 OK";  
  
    /** *//** 远程地址 */  
    private final InetSocketAddress remoteAddress;  
  
    /** *//** * 本地地址 */  
    private final InetSocketAddress localAddress;  
  
    /** *//** * 连接通道 */  
    private SocketChannel socketChannel;  
  
    /** *//** 发送缓冲区 */  
    private final ByteBuffer sendBuf;  
  
    /** *//** 接收缓冲区 */  
    private final ByteBuffer receiveBuf;  
  
    private static final int BUFFER_SIZE = 8192;  
  
    /** *//** 端口选择器 */  
    private Selector selector;  
  
    private String address;  
  
    private Status sysStatus;  
  
    private String sessionid;  
    private String transport = "RTP/AVP/TCP;unicast;interleaved=0-1";

    /** *//** 线程是否结束的标志 */  
    private AtomicBoolean shutdown;
      
    private int seq=2;
      
    private boolean isSended;  
      
    private String trackInfo;  
      
  
    private enum Status   
        init, options, describe, setup, play, pause, teardown  
      
  
    public RTSPClient(InetSocketAddress remoteAddress,  
            InetSocketAddress localAddress, String address)   
        this.remoteAddress = remoteAddress;  
        this.localAddress = localAddress;  
        this.address = address;  
  
        // 初始化缓冲区  
        sendBuf = ByteBuffer.allocateDirect(BUFFER_SIZE);  
        receiveBuf = ByteBuffer.allocateDirect(BUFFER_SIZE);  
        if (selector == null)   
            // 创建新的Selector  
            try   
                selector = Selector.open();  
             catch (final IOException e)   
                e.printStackTrace();  
              
          
  
        startup();  
        sysStatus = Status.init;  
        shutdown=new AtomicBoolean(false);  
        isSended=false;  
      
  
    public void startup()   
        try   
            // 打开通道  
            socketChannel = SocketChannel.open();  
            // 绑定到本地端口  
            socketChannel.socket().setSoTimeout(30000);  
            socketChannel.configureBlocking(false);  
            socketChannel.socket().bind(localAddress);
            if (socketChannel.connect(remoteAddress)) 
                System.out.println("开始建立连接:" + remoteAddress);  
              
            socketChannel.register(selector, SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE, this);
            System.out.println("端口打开成功" + socketChannel.getLocalAddress() + " -> " + socketChannel.getRemoteAddress());
  
         catch (final IOException e1)   
            e1.printStackTrace();  
          
      
  
    public void send(byte[] out)   
        if (out == null || out.length < 1)   
            return;  
          
        synchronized (sendBuf)   
            sendBuf.clear();  
            sendBuf.put(out);  
            sendBuf.flip();  
          
  
        // 发送出去  
        try   
            write();  
            isSended=true;  
         catch (final IOException e)   
            e.printStackTrace();  
          
      
  
    public void write() throws IOException   
        if (isConnected())   
            try   
                socketChannel.write(sendBuf);  
             catch (final IOException e)   
              
         else   
            System.out.println("通道为空或者没有连接上");  
          
      
  
    public byte[] recieve()   
        if (isConnected())   
            try   
                int len = 0;  
                int readBytes = 0;  
  
                synchronized (receiveBuf)   
                    receiveBuf.clear();  
                    try   
                        while ((len = socketChannel.read(receiveBuf)) > 0)   
                            readBytes += len;  
                          
                     finally   
                        receiveBuf.flip();  
                      
                    if (readBytes > 0)   
                        final byte[] tmp = new byte[readBytes];  
                        receiveBuf.get(tmp);  
                        return tmp;  
                     else   
                        System.out.println("接收到数据为空,重新启动连接");  
                        return null;  
                      
                  
             catch (final IOException e)   
                System.out.println("接收消息错误:");  
              
         else   
            System.out.println("端口没有连接");  
          
        return null;  
      
  
    public boolean isConnected()   
        return socketChannel != null && socketChannel.isConnected();  
      
  
    private void select()   
        int n = 0;  
        try   
            if (selector == null)   
                return;  
              
            n = selector.select(1000);  
  
         catch (final Exception e)   
            e.printStackTrace();  
          
  
        // 如果select返回大于0,处理事件  
        if (n > 0)   
            for (final Iterator<SelectionKey> i = selector.selectedKeys()  
                    .iterator(); i.hasNext();)   
                // 得到下一个Key  
                final SelectionKey sk = i.next();  
                i.remove();  
                // 检查其是否还有效  
                if (!sk.isValid())   
                    continue;  
                  
  
                // 处理事件  
                final IEvent handler = (IEvent) sk.attachment();  
                try   
                    if (sk.isConnectable())   
                        handler.connect(sk);  
                     else if (sk.isReadable())   
                        handler.read(sk);  
                     else   
                        // System.err.println("Ooops");  
                      
                 catch (final Exception e)   
                    handler.error(e);  
                    sk.cancel();  
                  
              
          
      
  
    public void shutdown()   
        if (isConnected())   
            try   
                socketChannel.close();  
                System.out.println("端口关闭成功");  
             catch (final IOException e)   
                System.out.println("端口关闭错误:");  
             finally   
                socketChannel = null;  
              
         else   
            System.out.println("通道为空或者没有连接");  
          
      
  
    @Override  
    public void run() 
        // 启动主循环流程  
        while (!shutdown.get())   
            try   
                if (isConnected()&&(!isSended)) 
                    switch (sysStatus) 
                    case init:
                        doOption();
                        break;
                    case options:
                        doDescribe();
                        break;
                    case describe:
                        doSetup();
                        break;
                    case setup:
                        if(sessionid==null&&sessionid.length()>0)
                            System.out.println("setup还没有正常返回");
                        else
                            doPlay();
                        
                        break;
                    case play:
//                        doPause();
//                        doPlay();
                        System.out.println("PLAY start");
                        break;

                    case pause:
                        doTeardown();
                        break;
                    default:
                        break;
                    
                
                // do select
                select();  
                try 
                    Thread.sleep(1000);
                 catch (final Exception e) 
                
             catch (final Exception e) 
                e.printStackTrace();  
              
          
          
        shutdown();  
      
  
    public void connect(SelectionKey key) throws IOException   
        if (isConnected())   
            return;  
          
        // 完成SocketChannel的连接  
        socketChannel.finishConnect();  
        while (!socketChannel.isConnected())   
            try   
                Thread.sleep(300);  
             catch (final InterruptedException e)   
                e.printStackTrace();  
              
            socketChannel.finishConnect();  
          
  
      
  
    public void error(Exception e)   
        e.printStackTrace();  
      
  
    public void read(SelectionKey key) throws IOException   
        // 接收消息  
        final byte[] msg = recieve();  
        if (msg != null)   
            handle(msg);  
         else   
            key.cancel();  
          
      
  
    private void handle(byte[] msg)   
        String tmp = new String(msg);  
        System.out.println("返回内容:");  
        System.out.println(tmp);  
        if (tmp.startsWith(RTSP_OK))   
            switch (sysStatus)   
            case init:  
                sysStatus = Status.options;  
                break;  
            case options:  
                sysStatus = Status.describe;  
                String temp =tmp.substring(tmp.indexOf("trackID"));
                trackInfo = temp.split("\\r\\n")[0];
                break;  
            case describe:  
                String tempSessionId = tmp.substring(tmp.indexOf("Session: ") + 9);
                sessionid = tempSessionId.split("\\r\\n")[0];
                sessionid = tempSessionId.split(";")[0];
                sessionid = sessionid.trim();
                if(sessionid!=null&&sessionid.length()>0)
                    sysStatus = Status.setup;  
                  
                break;  
            case setup:  
                sysStatus = Status.play;  
                break;  
            case play:  
//                sysStatus = Status.pause;
                break;  
            case pause:  
                sysStatus = Status.teardown;  
                shutdown.set(true);  
                break;  
            case teardown:  
                sysStatus = Status.init;  
                break;  
            default:  
                break;  
              
            isSended=false;  
         else   
            System.out.println("返回错误:" + tmp);  
          
  
      
  
    private void doTeardown()   
        StringBuilder sb = new StringBuilder();  
        sb.append("TEARDOWN ");  
        sb.append(this.address);  
        sb.append("/");  
        sb.append(VERSION);
        sb.append(System.lineSeparator());
        sb.append("Cseq: ");
        sb.append(seq++);  
        sb.append(System.lineSeparator());
        sb.append("User-Agent: RealMedia Player HelixDNAClient/10.0.0.11279 (win32)");
        sb.append(System.lineSeparator());
        sb.append("Session: ");  
        sb.append(sessionid);
        sb.append(System.lineSeparator());
        sb.append(System.lineSeparator());
        send(sb.toString().getBytes());  
        System.out.println(sb.toString());  
    
  
    private void doPlay()   
        StringBuilder sb = new StringBuilder();  
        sb.append("PLAY ");  
        sb.append(this.address);  
        sb.append(VERSION);
        sb.append(System.lineSeparator());
        sb.append("Session: ");
        sb.append(sessionid);  
        sb.append(System.lineSeparator());
        sb.append("Cseq: ");
        sb.append(seq++);
        sb.append(System.lineSeparator());
        sb.append("Range: npt=0.000-");
        sb.append(System.lineSeparator());
        sb.append(System.lineSeparator());
        System.out.println(sb.toString());
        send(sb.toString().getBytes());  
    
  
    private void doSetup()   
        StringBuilder sb = new StringBuilder();  
        sb.append("SETUP ");  
        sb.append(this.address);  
        sb.append("/");  
        sb.append(trackInfo);  
        sb.append(VERSION);
        sb.append(System.lineSeparator());

        sb.append("Cseq: ");  
        sb.append(seq++);  
        sb.append(System.lineSeparator());
        sb.append("Transport: ");
        sb.append(transport);
        sb.append(System.lineSeparator());
        sb.append(System.lineSeparator());
        System.out.println(sb.toString());  
        send(sb.toString().getBytes());  
      
  
    private void doOption()   
        StringBuilder sb = new StringBuilder();  
        sb.append("OPTIONS ");  
        sb.append(this.address.substring(0, address.lastIndexOf("/")));  
        sb.append(VERSION);
        sb.append(System.lineSeparator());

        sb.append("Cseq: ");  
        sb.append(seq++);  
        sb.append(System.lineSeparator());
        sb.append(System.lineSeparator());
        System.out.println(sb.toString());  
        send(sb.toString().getBytes());  
      
  
    private void doDescribe()   
        StringBuilder sb = new StringBuilder();  
        sb.append("DESCRIBE ").append(this.address).append(VERSION).append(System.lineSeparator());
        sb.append("Cseq: ").append(seq++).append(System.lineSeparator());
        sb.append("Accept: application/sdp").append(System.lineSeparator());

        sb.append(System.lineSeparator());
        System.out.println(sb.toString());  
        send(sb.toString().getBytes());  
      
      
    private void doPause()   
        StringBuilder sb = new StringBuilder();  
        sb.append("PAUSE ");  
        sb.append(this.address);  
        sb.append("/");  
        sb.append(VERSION);
        sb.append(System.lineSeparator());

        sb.append("Cseq: ");  
        sb.append(seq++);  
        sb.append(System.lineSeparator());
        sb.append("Session: ");  
        sb.append(sessionid);
        sb.append(System.lineSeparator());
        sb.append(System.lineSeparator());
        send(sb.toString().getBytes());  
        System.out.println(sb.toString());
    

    public static void main(String[] args)   
        try   
            // RTSPClient(InetSocketAddress remoteAddress,  
            // InetSocketAddress localAddress, String address)
            // rtsp://admin:shinemo123@39.170.35.150:1554/h264/ch0/1
            RTSPClient client = new RTSPClient(  
                    new InetSocketAddress("39.170.35.150", 1554),
                    new InetSocketAddress("10.1.65.48", 0),
                    "rtsp://admin:shinemo123@39.170.35.150:1554/h264/ch0/1");
            client.start();  
         catch (Exception e)   
            e.printStackTrace();  
        

    
  

用 Java 实现 RTSP 媒体服务器

】用Java实现RTSP媒体服务器【英文标题】:ImplementingRTSPmediaserverinJava【发布时间】:2011-07-2107:43:07【问题描述】:我正在尝试在java中实现一个简单的RTSP服务器,它将使用android手机作为接收客户端。我已经在互联网上搜寻答案并... 查看详情

rtsp协议格式解析(代码片段)

...开发系列文章。rtsp协议开发指南rtsp协议格式解析rtsp协议报文解析-请求行解析rtsp协议报文解析-首部字段解析1RTSP与HTTP协议比较rtsp协议在语法及一些消息参数等方面与http协议类似,这里之所以引入http的相关内容,是为... 查看详情

关于rtsp-over-http

...概述RTSP-Over-HTTP的关键(同时也是全部内容)在于:让RTSP报文通过HTTP端口(即80端口)通信。我们知道RTSP的标准端口是554,但是由于各种不同的防火墙等安全策略配置的原因,客户端在访问554端口时可能存在限制,从而无法正... 查看详情

ffmpeg搭建一个简单的rtsp推流方案(代码片段)

文章目录ffmpeg搭建一个简单的rtsp推流方案基础环境要求开始demoffmpeg搭建一个简单的rtsp推流方案基础环境要求ffmpegffplay/VLCrtsp服务器开始首先我们必须要安装好ffmpeg,不管是源码编译还是直接安装网上都有很多教程,这里不多展开.... 查看详情

unity下如何实现rtmp或rtsp流播放和录制(代码片段)

...RTSP直播播放模块;iOS平台RTMP|RTSP直播播放模块。技术实现本文主要介绍流数据录制,实际上,录制相对直播播放来说,更简单一些,毕竟不需要解码 查看详情

ffmpeg代码实现流媒体推流(rtsp)

...务器,并不符合我的要求。接着我找到另一篇文章:ffmpeg实现H264压缩并且推流至RTSP,这篇文章只有图像编码,并没有音频编码,并且推流之后并没有播放成功。我综合上面两位大佬的思路,和查找一些资料实现了这个功能。RTSP... 查看详情

rtsp协议详解(代码片段)

...RTSP又称为“因特网录像机遥控协议”。1.1.RTSP协议简介要实现RTSP的控制功能,不仅要有协议,而且要有专门的媒体播放器(mediaplayer)和媒体服务器(mediaserver)。媒体服务器与媒体播放器的关系是服务器与客户的关系。媒体... 查看详情

live555编译

项目里面需要简单的rtsp服务器来实现视频预览等功能;rtsp本来不是太复杂的东西,github上有很多功能都比较完善的项目可以随便拿来用,但是测试过程中发现live555还是有性能上的一些差异;具体如下:环境hisi3516cv200sd卡上读取... 查看详情

使用 rtsp 在 java me 中实现视频流

】使用rtsp在javame中实现视频流【英文标题】:Implementvideostreaminginjavameusingrtsp【发布时间】:2012-08-2706:27:09【问题描述】:我想使用rtspurl实现videostreaminginjavame。在设备上测试代码时,我得到媒体异常声明PrefetchError-33。这是我的... 查看详情

浏览器播放rtsp视频流:3rtsp转webrtc播放(代码片段)

...tc,这样我们就可以结合我们之前的cgo+onvif+gSoap实现方案来获取rtsp流,并且可以根据已经实现的ptz、预置点等功能接口做更多的扩展。2.rtsp转webRTC如下是找到的一个比较合适的开源方案,前端使用了jQuery、bootstr... 查看详情

windows平台unitycamera场景实现轻量级rtsp服务和rtmp推送

...开发者对Unity平台下的直播体验提出了更高的要求。技术实现Unity平台下的RTMP推流、RTMP、RTSP播放前几年已经覆盖了Windows、Linux、Android、iOS平台。本文主要介绍Windows平台Unity环境下的轻量级RTSP服务。通过对外提供RTSP拉流URL的形... 查看详情

用easyrtspserver模拟摄像机rtsp流实现rtsp摄像机模拟器

在很早之前的一篇博客《基于EasyIPCamera实现的数字网络摄像机IPCamera的模拟器IPCRTSPSimulator》,我们描述了如何模拟一个摄像机的RTSP流,但当时的RTSP流模拟器还只能读取固定的.264文件,而这种文件是很难找到的,... 查看详情

华为海康大华摄像头编译rtsp转rtmp和httpflv(代码片段)

...rtmp流方案二通过Java+Nginx-http-flv-module+FFmpeg+Flv.js实现rtsp转flv在vue项目中(采用)项目需求要看摄像头实时画面谷歌浏 查看详情

easynvr分发rtsp不标准导致客户端检查报错是什么原因?(代码片段)

...进行简单配置后即可直接使用,无需自建服务器即可实现网页无插件直播。EasyNVR主要是接入RTSP协议的前端设备,并且支持分发包含RTSP在内的多种协议视频流。有客户反馈EasyNVR的rtsp分发流不标准,如下图抓包所示... 查看详情

RTSP 隧道 HTTP、FFMPEG

...将control_transport设置为RTSP_MODE_TUNNEL来支持它。我的问题很简单,我该如何用 查看详情

easynvr如何获取rtsp格式的视频流?三种获取rtsp地址方式介绍

...xff0c;放到其他平台使用。其实这个需求可以直接在平台内实现,EasyNVR中提供了获取RTSP流的功能,本文我们就介绍一下具体操作方法。首先最简单的方法是在EasyNVR视频播放页面F12可以查看到当前播放的信息 查看详情

用easyrtspserver模拟摄像机rtsp流实现rtsp摄像机模拟器

在很早之前的一篇博客《基于EasyIPCamera实现的数字网络摄像机IPCamera的模拟器IPCRTSPSimulator》,我们描述了如何模拟一个摄像机的RTSP流,但当时的RTSP流模拟器还只能读取固定的.264文件,而这种文件是很难找到的,... 查看详情

java示例代码_从pcap文件中筛选rtsp数据包

java示例代码_从pcap文件中筛选rtsp数据包 查看详情