ESP32-CAM网络摄像头系列-01-基于RTSP协议的局域网视频推流/拉流的简单实现

这篇具有很好参考价值的文章主要介绍了ESP32-CAM网络摄像头系列-01-基于RTSP协议的局域网视频推流/拉流的简单实现。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:

        由于项目需要,最近开始开坑关于ESP32-CAM系列的RTSP网络摄像头系列,该文章为该系列的第一篇文章。用于记录项目开发过程。

本文解决的问题:

        使用ESP32-CAM获取图像数据,并通过RTSP协议将获取到的视频流传输到上位机进行显示。

具体实现:

        使用ESP32-CAM进行视频推流,python端作为rtsp拉流,其中ESP32-CAM使用arduinoIDE开发,使用了安信可的支持库。支持包安装网址:

拉流效果:

ESP32-CAM网络摄像头系列-01-基于RTSP协议的局域网视频推流/拉流的简单实现

一、推流部分

官方示例代码:

#include "OV2640.h"
#include <WiFi.h>
#include <WebServer.h>
#include <WiFiClient.h>

#include "SimStreamer.h"
#include "OV2640Streamer.h"
#include "CRtspSession.h"

#define ENABLE_RTSPSERVER

OV2640 cam;

#ifdef ENABLE_WEBSERVER
WebServer server(80);
#endif

#ifdef ENABLE_RTSPSERVER
WiFiServer rtspServer(8554);
#endif


#ifdef SOFTAP_MODE
IPAddress apIP = IPAddress(192, 168, 1, 1);
#else
#include "wifikeys_template.h"
#endif

#ifdef ENABLE_WEBSERVER
void handle_jpg_stream(void)
{
    WiFiClient client = server.client();
    String response = "HTTP/1.1 200 OK\r\n";
    response += "Content-Type: multipart/x-mixed-replace; boundary=frame\r\n\r\n";
    server.sendContent(response);

    while (1)
    {
        cam.run();
        if (!client.connected())
            break;
        response = "--frame\r\n";
        response += "Content-Type: image/jpeg\r\n\r\n";
        server.sendContent(response);

        client.write((char *)cam.getfb(), cam.getSize());
        server.sendContent("\r\n");
        if (!client.connected())
            break;
    }
}

void handle_jpg(void)
{
    WiFiClient client = server.client();

    cam.run();
    if (!client.connected())
    {
        return;
    }
    String response = "HTTP/1.1 200 OK\r\n";
    response += "Content-disposition: inline; filename=capture.jpg\r\n";
    response += "Content-type: image/jpeg\r\n\r\n";
    server.sendContent(response);
    client.write((char *)cam.getfb(), cam.getSize());
}

void handleNotFound()
{
    String message = "Server is running!\n\n";
    message += "URI: ";
    message += server.uri();
    message += "\nMethod: ";
    message += (server.method() == HTTP_GET) ? "GET" : "POST";
    message += "\nArguments: ";
    message += server.args();
    message += "\n";
    server.send(200, "text/plain", message);
}
#endif

#ifdef ENABLE_OLED
#define LCD_MESSAGE(msg) lcdMessage(msg)
#else
#define LCD_MESSAGE(msg)
#endif

#ifdef ENABLE_OLED
void lcdMessage(String msg)
{
    if(hasDisplay) {
        display.clear();
        display.drawString(128 / 2, 32 / 2, msg);
        display.display();
    }
}
#endif

CStreamer *streamer;

void setup()
{
  #ifdef ENABLE_OLED
    hasDisplay = display.init();
    if(hasDisplay) {
        display.flipScreenVertically();
        display.setFont(ArialMT_Plain_16);
        display.setTextAlignment(TEXT_ALIGN_CENTER);
    }
  #endif
    LCD_MESSAGE("booting");

    Serial.begin(115200);
    while (!Serial)
    {
        ;
    }
    cam.init(esp32cam_aithinker_config);

    IPAddress ip;


#ifdef SOFTAP_MODE
    const char *hostname = "devcam";
    // WiFi.hostname(hostname); // FIXME - find out why undefined
    LCD_MESSAGE("starting softAP");
    WiFi.mode(WIFI_AP);
    WiFi.softAPConfig(apIP, apIP, IPAddress(255, 255, 255, 0));
    bool result = WiFi.softAP(hostname, "12345678", 1, 0);
    if (!result)
    {
        Serial.println("AP Config failed.");
        return;
    }
    else
    {
        Serial.println("AP Config Success.");
        Serial.print("AP MAC: ");
        Serial.println(WiFi.softAPmacAddress());

        ip = WiFi.softAPIP();
    }
#else
    LCD_MESSAGE(String("join ") + ssid);
    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(F("."));
    }
    ip = WiFi.localIP();
    Serial.println(F("WiFi connected"));
    Serial.println("");
    Serial.println(ip);
#endif

    LCD_MESSAGE(ip.toString());

#ifdef ENABLE_WEBSERVER
    server.on("/", HTTP_GET, handle_jpg_stream);
    server.on("/jpg", HTTP_GET, handle_jpg);
    server.onNotFound(handleNotFound);
    server.begin();
#endif

#ifdef ENABLE_RTSPSERVER
    rtspServer.begin();

    //streamer = new SimStreamer(true);             // our streamer for UDP/TCP based RTP transport
    streamer = new OV2640Streamer(cam);             // our streamer for UDP/TCP based RTP transport
#endif
}

void loop()
{
#ifdef ENABLE_WEBSERVER
    server.handleClient();
#endif

#ifdef ENABLE_RTSPSERVER
    uint32_t msecPerFrame = 100;
    static uint32_t lastimage = millis();

    // If we have an active client connection, just service that until gone
    streamer->handleRequests(0); // we don't use a timeout here,
    // instead we send only if we have new enough frames
    uint32_t now = millis();
    if(streamer->anySessions()) {
        if(now > lastimage + msecPerFrame || now < lastimage) { // handle clock rollover
            streamer->streamImage(now);
            lastimage = now;

            // check if we are overrunning our max frame rate
            now = millis();
            if(now > lastimage + msecPerFrame) {
                printf("warning exceeding max frame rate of %d ms\n", now - lastimage);
            }
        }
    }
    
    WiFiClient rtspClient = rtspServer.accept();
    if(rtspClient) {
        Serial.print("client: ");
        Serial.print(rtspClient.remoteIP());
        Serial.println();
        streamer->addSession(rtspClient);
    }
#endif
}

        对于ESP32的RTSP推流安信可官方已经给出了相应的示例代码,改代码使用宏定义的方式区分http和rtsp协议的不同代码。由于我们不需要用到基于http协议的视频推流,因此可以删去官方代码中不必要的部分。修改完的代码如下:

ESP32部分的代码由官方示例代码修改而来。只保留RTSP推流部分。

#include "OV2640.h"
#include <WiFi.h>
#include <WebServer.h>
#include <WiFiClient.h>

#include "SimStreamer.h"
#include "OV2640Streamer.h"
#include "CRtspSession.h"

// copy this file to wifikeys.h and edit
const char *ssid =     "YAN";         // Put your SSID here
const char *password = "qwertyuiop";     // Put your PASSWORD here

#define ENABLE_RTSPSERVER

OV2640 cam;

WiFiServer rtspServer(8554);

CStreamer *streamer;

void setup()
{
    Serial.begin(115200);
    while (!Serial);
    cam.init(esp32cam_aithinker_config);

    IPAddress ip;

    WiFi.mode(WIFI_STA);
    WiFi.begin(ssid, password);
    while (WiFi.status() != WL_CONNECTED)
    {
        delay(500);
        Serial.print(F("."));
    }
    ip = WiFi.localIP();
    Serial.println(F("WiFi connected"));
    Serial.println("");
    Serial.println(ip);

    rtspServer.begin();

    //streamer = new SimStreamer(true);             // our streamer for UDP/TCP based RTP transport
    streamer = new OV2640Streamer(cam);             // our streamer for UDP/TCP based RTP transport
}

void loop()
{
    uint32_t msecPerFrame = 100;
    static uint32_t lastimage = millis();

    // If we have an active client connection, just service that until gone
    streamer->handleRequests(0); // we don't use a timeout here,
    // instead we send only if we have new enough frames
    uint32_t now = millis();
    if(streamer->anySessions()) {
        if(now > lastimage + msecPerFrame || now < lastimage) { // handle clock rollover
            streamer->streamImage(now);
            lastimage = now;

            // check if we are overrunning our max frame rate
            now = millis();
            if(now > lastimage + msecPerFrame) {
                printf("warning exceeding max frame rate of %d ms\n", now - lastimage);
            }
        }
    }
    
    WiFiClient rtspClient = rtspServer.accept();
    if(rtspClient) {
        Serial.print("client: ");
        Serial.print(rtspClient.remoteIP());
        Serial.println();
        streamer->addSession(rtspClient);
    }
}

ArduinoIDE串口监视器输出的初始化信息,我们需要将ESP32的IP地址安装RTSP协议推流的格式填入Python拉流代码中。

# RTSP 地址
rtsp_url = "rtsp://192.168.168.238:8554/mjpeg/2"

ESP32-CAM网络摄像头系列-01-基于RTSP协议的局域网视频推流/拉流的简单实现

 二、拉流部分

        由于Opencv-python集成了RTSP协议拉流的库函数,因此我们需要下载Opencv-python的支持包。可以打开Pycharm的Terminal使用pip指令快速下载。

pip install opencv-python

 上位机python3拉流代码:

import cv2

# RTSP 地址
rtsp_url = "rtsp://192.168.168.238:8554/mjpeg/2"

# 打开 RTSP 视频流
cap = cv2.VideoCapture(rtsp_url)

# 检查视频是否成功打开
if not cap.isOpened():
    print("Failed to open RTSP stream")
    exit()

# 循环读取视频帧
while True:
    # 读取视频帧
    ret, frame = cap.read()

    # 检查是否成功读取视频帧
    if not ret:
        break

    # 显示视频帧
    cv2.imshow("RTSP Stream", frame)

    # 按 'q' 键退出循环
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# 释放资源
cap.release()
cv2.destroyAllWindows()

PS:需要注意的是,进行RTSP拉流的上位机和推流的下位机都需要位于同一个局域网下才能进行推拉流传输。文章来源地址https://www.toymoban.com/news/detail-512352.html

到了这里,关于ESP32-CAM网络摄像头系列-01-基于RTSP协议的局域网视频推流/拉流的简单实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【ESP32-CAM】20元就能搭建简易Web摄像头

    在首选项中,增加网址https://dl.espressif.com/dl/package_esp32_index.json 安装esp32资源包 选择ESP32-CAM开发板 选一个USB-TTL的串口工具,按照图示,RX接U0TXD,TX接U0RXD,GND和5V供电,其中GPIO0在烧录时需要短接到GND 在IDE上选择串口,可以取得开发板信息测试一下 在示例中选择WebServer 默认不

    2024年02月13日
    浏览(34)
  • ubuntu利用usb_cam打开摄像头

    想要标定多个相机,首先得把相机打开吧,usb_cam是针对usb摄像头的ros驱动包,简单来说就是得有这个功能包,才能在ros中把摄像头打开。 首先打开终端,输入: 这里melodic应该根据自己Ubuntu系统进行灵活变换,例如我使用的Ubuntu18.04,那么我对应的就是melodic版本。 驱动安装

    2024年02月03日
    浏览(44)
  • 【完全开源】小安派-Cam-D200(AiPi-Cam-D200)200W摄像头开发板

    AiPi-Cam-D200 是安信可科技基于AiPi-Cam-D开发板 开发的一款兼容200W 摄像头的开发板,相当于给AiPi-Cam-D 做了升级迭代。 摄像头型号:GC2145 摄像头尺寸:13*13*21.57 mm(长 宽 高,不含排线) 像素大小:1600*1200 视角:140° 焦距:2米 功耗:180mA(200uA) 接口:DVP(24Pin间距0.5mm) IO名称 功能

    2024年02月19日
    浏览(36)
  • 基于海康SDK实现Python调用海康威视网络摄像头

    本文参考博客,写得很好: Python调用海康威视网络相机之——python调用海康威视C++的SDK Python调用海康威视网络相机C++的SDK 写本文的目的,也是快速复盘,所以没有很详细 保存视频流到本地可参考下一篇:基于海康SDK实现Python保存海康威视网络摄像头拍摄的视频 Windows11 Vis

    2024年02月02日
    浏览(62)
  • 基于TCP/IP协议的网络摄像头的QT项目

    目录 项目简述: 1.服务器  步骤一:首先搭建一个基本的服务器框架。  1.初始化服务器的函数主体  2.等待连接 步骤二:数据库的使用,本次项目使用的Sqlite3数据库 1.数据库初始化 2.登录时使用数据库  3.注册时使用数据库 步骤三:摄像头的调用与数据传输 1.V4L2框架的使

    2024年02月03日
    浏览(37)
  • 33、基于STM32单片机车牌识别系统摄像头图像处理系统设计

    毕设帮助、开题指导、技术解答(有偿)见文末。 目录 摘要 一、硬件方案 二、设计功能 三、实物图 四、原理图 五、PCB图 六、程序源码 七、资料包括 随着汽车工业的迅猛发展,我国汽车拥有量急剧增加。停车场作为交通设施的组成部分,随着交通运输的繁忙和不断发展,

    2024年02月15日
    浏览(41)
  • 学习笔记:利用usb_cam进行单目标定与畸变矫正(笔记本摄像头 or usb相机)

    一个刚入门视觉的学习笔记,怕哪天系统崩了找不回笔记了,故上传到博客方便保留。 1、准备工作(安装usb_cam) 1)创建文件夹 2)下载编译安装usb_cam包(该包能将摄像头的图像通过sensor_msgs::Image消息发布)    2、可以通过ls/dev/video*来查看电脑的设备号来选择外接或笔记本

    2024年02月07日
    浏览(39)
  • 实时人脸检测:基于卷积神经网络CNN和OpenCV的摄像头应用

    人脸检测是计算机视觉中的重要任务之一,广泛应用于人脸识别、人脸表情分析、人脸跟踪等领域。在实时视频流中进行人脸检测可以帮助我们快速准确地识别和定位图像中的人脸。本文将介绍如何使用 OpenCV 库来实现通过本地摄像头获取实时视频流,并利用预训练的深度学

    2024年02月07日
    浏览(47)
  • ROS高效进阶第四章 -- 机器视觉处理之图像格式,usb_cam,摄像头标定,opencv和cv_bridge引入

    从本文开始,我们用四篇文章学习ROS机器视觉处理,本文先学习一些外围的知识,为后面的人脸识别,目标跟踪和yolov5目标检测做准备。 我的笔记本是Thinkpad T14 i7 + Nvidia MX450,系统是ubuntu20.04,ros是noetic。由于很多驱动与硬件强相关,请读者注意这点。 本文的参考资料有:

    2024年02月04日
    浏览(42)
  • 76、基于STM32单片机车牌识别摄像头图像处理扫描设计(程序+原理图+PCB源文件+相关资料+参考PPT+元器件清单等)

    单片机主芯片选择方案 方案一:AT89C51是美国ATMEL公司生产的低电压,高性能CMOS型8位单片机,器件采用ATMEL公司的高密度、非易失性存储技术生产,兼容标准MCS-51指令系统,片内置通用8位中央处理器(CPU)和Flash存储单元,功能强大。其片内的4K程序存储器是FLASH工艺的,这种单

    2024年02月12日
    浏览(52)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包