在Unity中搭建RTSP服务器

这篇具有很好参考价值的文章主要介绍了在Unity中搭建RTSP服务器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

简介

最近做的项目需要Unity把摄像机推流到服务器上,具体推流比较简单可以看上一篇文章Unity中摄像机的RTSP推流。考虑到推流时需要先创建服务器,为了项目使用起来方便就把服务器也集成到了Unity工程中,这样运行程序就会自动创建服务器。此外还考虑到一些细节上的问题,比如rtsp地址输错时进行推流,程序会直接卡死。

目录

简介

1. 添加服务器

1.1 下载并导入rtsp-simple-server

1.2 写服务器脚本

1.3 开启服务器

2. 推流过程的一些细节优化

2.1 防止服务器未开启时就推流摄像机画面

2.2 防止RTSP地址输错导致程序卡死

2.3 显示相机推流的RTSP地址

2.4 添加复制功能


1. 添加服务器

1.1 下载并导入rtsp-simple-server

首先下载rtsp-simple-server,并导入到Unity中。

https://github.com/bluenviron/mediamtx/releases新版本改名了,我用的之前的版本,往后翻几页就能找到rtsp-simple-server,下载windows版本即可,如下图

unity 接rtsp,unity,服务器,游戏引擎,ffmpeg,c#,实时音视频

里面有如下三个文件:

unity 接rtsp,unity,服务器,游戏引擎,ffmpeg,c#,实时音视频

在Unity工程中创建一个文件夹,命名为RTSPServer,把上面三个文件复制进去。其中yml配置文件可以设置一些服务器的参数,比如端口号等(默认端口号为8554),这里不再赘述。

1.2 写服务器脚本

创建一个RTSPServer脚本,放到FFmpegOut/Runtime文件夹中。

先声明几个变量:

public static RTSPServerLoader instance;
public bool RTSPServerloaded = false;
public bool CoroutineStarted = false;
private Process process;
private StreamWriter messageStream;
  • instance:该类的唯一实例。
  • RTSPServerloaded:RTSP服务器是否已经加载。
  • CoroutineStarted:协程是否已经启动。
  • process:与RTSP服务器进程相关的进程对象。
  • messageStream:用于向RTSP服务器进程发送消息的流写入器。

在脚本中,使用Process类启动rtsp-simple-server.exe应用程序,并设置相关属性,具体代码如下:

try
{
    process = new Process();
    process.EnableRaisingEvents = false;
    process.StartInfo.FileName = Application.dataPath + "./RTSPServer/rtsp-simple-server.exe";
    process.StartInfo.WorkingDirectory = Application.dataPath + "./RTSPServer";
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.CreateNoWindow = true;
    process.StartInfo.RedirectStandardOutput = true;
    process.StartInfo.RedirectStandardInput = true;
    process.StartInfo.RedirectStandardError = true;
    process.OutputDataReceived += new DataReceivedEventHandler(DataReceived);
    process.ErrorDataReceived += new DataReceivedEventHandler(ErrorReceived);
    process.Start();
    process.BeginOutputReadLine();
    messageStream = process.StandardInput;

    UnityEngine.Debug.Log("Starting RTSP Server");
}
catch (Exception e)
{
    UnityEngine.Debug.LogError("Unable to launch app: " + e.Message);
}

然后创建一个协程方法,用于等待RTSP服务器启动并在启动后将RTSPServerloaded变量设置为true。具体代码如下:

        public IEnumerator WaitForServerToStart()
        {
            CoroutineStarted = true;
            yield return (new WaitForSeconds(2));

            RTSPServerloaded = true;
            UnityEngine.Debug.Log("Started RTSP Server");
        }

还有一些用于警告的方法:

        void DataReceived(object sender, DataReceivedEventArgs eventArgs)
        {
            UnityEngine.Debug.Log(eventArgs.Data);
        }

        void ErrorReceived(object sender, DataReceivedEventArgs eventArgs)
        {
            UnityEngine.Debug.LogError(eventArgs.Data);
        }

在程序结束后,需要杀死服务器进程:

        public void Kill()
        {
            if (process != null && !process.HasExited)
            {
                process.Kill();
            }
        }

        void OnApplicationQuit()
        {
            Kill();
        }

最后还有一个获取唯一实例的代码,即如果GetInstance()方法被多次调用,只会返回同一个实例。代码如下:

        public static RTSPServerLoader GetInstance()
        {
            if (instance == null)
            {
                instance = new RTSPServerLoader();
                UnityEngine.Debug.Log("new RTSPServerLoader");
            }
            return (instance);
        }

1.3 开启服务器

上面的脚本只是创建服务器的代码,并没有去调用。需要在CameraCapture脚本中调用这个脚本的方法来开启服务器。我没有把服务器脚本直接挂载的物体上,而是选择通过CameraCapture脚本调用,主要原因是CameraCapture脚本中需要用到服务器脚本里的一些东西,具体见2章节。

在CameraCapture脚本中声明变量:

RTSPServerLoader loader;

在Start()里面添加:

            loader = RTSPServerLoader.GetInstance();

            if (!loader.CoroutineStarted)
            {
                StartCoroutine(loader.WaitForServerToStart());
            }

用loader获取到了RTSPServerLoader的唯一实例,然后启动一个协程等待服务器启动。

最后别忘了在关闭程序的时候杀死服务器进程,在OnDisable()里面添加

loader.Kill();//关闭程序时杀死process

2. 推流过程的一些细节优化

2.1 防止服务器未开启时就推流摄像机画面

由于开启服务器需要几秒的时间,而摄像机推流是直接开始的,所以最开始的几秒会报出推流画面失败的错误,为了避免这个问题添加一个标志位,等开启服务器后再推流。

 使用loader.RTSPServerloaded来判断服务器是否已经开启。RTSPServerloaded是在服务器脚本中根据服务器状态进行赋值的。将这个标志位添加到Update()中的推流之前的if判断语句中,一共两个地方:

            // Lazy initialization 懒惰初始化
            if (_session == null && loader.RTSPServerloaded && isServerAccesible)
            {
                // Give a newly created temporary render texture to the camera
                // if it's set to render to a screen. Also create a bli)ter
                // object to keep frames presented on the screen.

                if (camera.targetTexture == null)
                {
                    _tempRT = new RenderTexture(_width, _height, 24, GetTargetFormat(camera)); 
                    _tempRT.antiAliasing = GetAntiAliasingLevel(camera);
                    camera.targetTexture = _tempRT;
                    _blitter = Blitter.CreateInstance(camera);
                }

                // Start an FFmpeg session.

                _session = FFmpegSession.Create(
                    gameObject.name,
                    camera.targetTexture.width,
                    camera.targetTexture.height,
                    _frameRate, url, preset
                );

                _startTime = Time.time;
                _frameCount = 0;
                _frameDropCount = 0;    
            }
            if (loader.RTSPServerloaded && isServerAccesible)
            {
                if (gap < 0)
                {
                    // Update without frame data.
                    _session.PushFrame(null);
                }
                else if (gap < delta)
                {
                    // Single-frame behind from the current time:
                    // Push the current frame to FFmpeg.
                    _session.PushFrame(camera.targetTexture);
                    _frameCount++;
                }
                else if (gap < delta * 2)
                {
                    // Two-frame behind from the current time:
                    // Push the current frame twice to FFmpeg. Actually this is not
                    // an efficient way to catch up. We should think about
                    // implementing frame duplication in a more proper way. #fixme
                    _session.PushFrame(camera.targetTexture);
                    _session.PushFrame(camera.targetTexture);
                    _frameCount += 2;
                }
                else
                {
                    // Show a warning message about the situation.
                    WarnFrameDrop();

                    // Push the current frame to FFmpeg.
                    _session.PushFrame(camera.targetTexture);

                    // Compensate the time delay.
                    _frameCount += Mathf.FloorToInt(gap * _frameRate);
                }
            }

这样就可以在推流之前先判断服务器有没有开启,开启了才开始推流。

另外,可以看到判断语句中还有一个标志位isServerAccesible,这个是下面要讲的。

2.2 防止RTSP地址输错导致程序卡死

这块也是在CameraCapture脚本中写的,主要是用到isServerAccesible标志位,上面已经提到。

我做的判断比较简单,因为服务器开启的地址是基于自己电脑ip+端口8554的,所以只需要判断输入的地址字符串中有没有包含电脑ip。

首先是获取电脑ip地址的代码,可以放到Start()中:

            //获取电脑ip
            // 获取计算机的所有网络接口
            NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
            // 遍历每个接口
            foreach (NetworkInterface iface in interfaces)
            {
                // 如果找到 WiFi 接口,并且该接口处于活动状态
                if (iface.NetworkInterfaceType == NetworkInterfaceType.Wireless80211 &&
                    iface.OperationalStatus == OperationalStatus.Up)
                {
                    // 遍历该接口上的所有 IP 地址
                    foreach (UnicastIPAddressInformation addr in iface.GetIPProperties().UnicastAddresses)
                    {
                        // 如果找到 IPv4 地址,输出并结束
                        if (addr.Address.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                        {
                            Debug.Log("IPv4 Address: " + addr.Address.ToString());
                            ipv4Address = addr.Address.ToString();
                            break;
                        }
                    }
                }
            }

然后是判断输入的地址是否包含该ip

            //判断输入的rtsp是否包含该ip
            if(url.Contains(ipv4Address))
            {
                isServerAccesible = true;
            }
            else
            {
                isServerAccesible = false;
            }

isServerAccesible标志位的位置在2.1中已经给出,不再赘述。

其实还有另一个更直接的解决方法,就是自动设置摄像机的推流地址。之前已经将服务器地址设置成了电脑ip+端口8554,和电脑ip捆绑了,所以可以直接使用之前获取电脑ip的方法去设置摄像机的推流地址,这样可以避免判断。具体使用哪种方法都可以,按照需求选择。

2.3 显示相机推流的RTSP地址

相机推流的地址是在脚本中写的,其实也可以设置一个public变量,让它在检查器中能够修改。但在用户使用的时候是看不到这个推流地址的,因此需要把它在游戏画面中显示出来。

主要是使用了UI里面的Canvas和Panel,在Panel上添加一个TextMeshPro和一个Button。TextMeshPro用于显示rtsp地址,Button用于实现复制地址功能(省的使用时一个一个敲地址了)。

在TextMeshPro上需要写一个脚本,用于获取RTSP地址,其实思路很简单,就是用获取到的ip和端口号,做一个字符串拼接,然后显示出来。在Start()里面添加:

Text = transform.GetComponent<TextMeshProUGUI>();

以及之前写过的获取ip的代码。

在Update()里面写如下代码:

Text.text = ("rtsp://" + ipv4Address + ":8554/camera");

这样就能够显示形如于“rtsp://电脑ip:8554/camera”的推流地址。

2.4 添加复制功能

接下来给Button添加复制功能,能够通过按下Button自动复制RTSP地址,编写TextMeshProCopy脚本:

using UnityEngine.UI;
using TMPro;

public class TextMeshProCopy : MonoBehaviour
{
    public TextMeshProUGUI textMeshPro;

    // Start is called before the first frame update
    void Start()
    {
        GetComponent<Button>().onClick.AddListener(CopyText);
    }

    // Update is called once per frame
    void Update()
    {
        
    }

    private void CopyText()
    {
        GUIUtility.systemCopyBuffer = textMeshPro.text;
        Debug.Log("Text has been copied");
    }
}

然后在检查器里面把上面的TextMeshPro拖到这个脚本的Public变量里面,如下图:

unity 接rtsp,unity,服务器,游戏引擎,ffmpeg,c#,实时音视频

Url1就是之前创建的TextMeshPro。

效果如下图:

unity 接rtsp,unity,服务器,游戏引擎,ffmpeg,c#,实时音视频

点击复制按钮就可以复制下来这个RTSP地址。文章来源地址https://www.toymoban.com/news/detail-764565.html

到了这里,关于在Unity中搭建RTSP服务器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 从零搭建自己的公网RTSP、RTMP、FLV、HLS、WS-FLV、WS-RTSP流媒体服务器解决方案

    环境准备 操作系统: 内存:2G以上 CPU: 双核2.0GHz以上 下载并安装SkeyeVSS综合安防视频云流媒体服务 下载SkeyeVSS 下载地址:http://www.openskeye.cn/download/vss.html?id=c24a0a06-6d38-45a5-8623-a1fa3f406ab1 安装SkeyeVSS Windows系统安装 双击下载的windows平台SkeyeVSS_Server_Setup_Vx.x.xx_buildxxxxxxxx.exe安装包

    2023年04月17日
    浏览(76)
  • Monibucav4(开源流媒体服务器)在Windows上搭建rtmp服务器并实现拉取rtsp视频流以及转换flv播放

    开源流媒体服务器ZLMediaKit在Windows上运行、配置、按需拉流拉取摄像头rtsp视频流)并使用http-flv网页播放: 开源流媒体服务器ZLMediaKit在Windows上运行、配置、按需拉流拉取摄像头rtsp视频流)并使用http-flv网页播放_srs按需拉流_霸道流氓气质的博客-CSDN博客 上面讲了ZLMediaKit的使用流

    2024年02月11日
    浏览(58)
  • 【rtsp推流】rtsp服务器+ffmpeg+Python+VLC

    本地摄像头实时监控/mp4视频文件 通过rtsp服务器转为rtsp地址 通过VLC将rtsp地址传入Python Python检测并标记好检测框(人脸识别/是否佩戴口罩) 通过ffmpeg推流,抛出一个新的rtsp地址 VLC即可访问新的rtsp地址 Python接收rtsp地址 1. 系统 2. 查看本机设备规格和WIndows规格 1. 下载 ① 官

    2024年02月16日
    浏览(32)
  • 从零开始写一个RTSP服务器(一)RTSP协议讲解

    为什么要写这个系列? 因为我自己在学习rtsp协议想自己从零写一个rtsp服务器的时候,由于rtsp比较复杂,所以觉得这个过程非常的困难,网上许多相关文章或模棱两可,或是复制粘贴。所以想写这样一个系列,来帮助想要学习rtsp协议或者想要从零写一个rtsp服务器的初学者

    2024年04月17日
    浏览(46)
  • rtsp简单服务器

    RTSP是一个实时传输流协议,是一个应用层的协议 通常说的RTSP包括RTSP协议、RTP协议、RTCP协议 对于这些协议的作用简单的理解如下 RTSP协议 :负责服务器与客户端之间的请求与响应 RTP协议 :负责传输媒体数据 RTCP协议 :在RTP传输过程中提供传输信息 rtsp承载与rtp和rtcp之上,rtsp并

    2024年03月23日
    浏览(30)
  • Windows上搭建rtsp-simple-server流媒体服务器实现rtsp、rtmp等推流以及转流、前端html与Vue中播放hls(m3u8)视频流

    Nginx-http-flv-module流媒体服务器搭建+模拟推流+flv.js在前端html和Vue中播放HTTP-FLV视频流: Nginx-http-flv-module流媒体服务器搭建+模拟推流+flv.js在前端html和Vue中播放HTTP-FLV视频流_霸道流氓气质的博客-CSDN博客 上面讲了Nginx-http-flv-module+flv.js进行流媒体服务器搭建和前端播放视频流的过

    2024年02月01日
    浏览(49)
  • 从零开始写一个RTSP服务器(二)RTSP协议的实现

    此系列只追求精简,旨在学习RTSP协议的实现过程,不追求复杂完美,所以这里要实现的RTSP服务器为了简单,实现上同一时间只能有一个客户端,下面开始介绍实现过程 在写一个RTSP服务器之前,我们必须知道一个RTSP服务器最简单的包含两部分,一部分是RTSP的交互,一部分是

    2024年04月17日
    浏览(46)
  • 使用nginx和ffmpeg搭建HTTP FLV流媒体服务器(摄像头RTSP视频流->RTMP->http-flv)

    名词解释   RTSP (Real-Time Streaming Protocol) 是一种网络协议,用于控制实时流媒体的传输。它是一种应用层协议,通常用于在客户端和流媒体服务器之间建立和控制媒体流的传输。RTSP允许客户端向服务器发送请求,如播放、暂停、停止、前进、后退等,以控制媒体流的播放和

    2024年02月16日
    浏览(49)
  • zlmediakit实现rtsp流服务器

    本次实现是将内存中的H264数据经过zlmediakit实现为rtsp流。 我是用的是CAPI的方式,将zlmediakit作为一个sdk嵌入到自己的程序中而不是作为一个独立的进进程服务。 1.编译完成zkmedialit后会得到bin include lib三个文件夹如图 其中bin中的MediaServer是作为独立的进程使用的zlmediakit服务,

    2024年02月02日
    浏览(32)
  • RTSP 和 RTMP通过ffmpeg实现将本地摄像头推流到RTSP服务器

    一、流媒体:RTSP 和RTMP 1、RTSP 和 RTMP的工作原理 1)RTSP工作原理 用户设备向视频流平台发送 RTSP 请求 视频流平台返回可以操作的请求列表,比如播放、暂停等 用户设备向视频流平台发送具体的请求,比如播放 视频流平台解析请求并调用指定机制启动视频流处理 由于 RTSP 依

    2024年02月05日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包