当前位置: 首页 > news >正文

基于Air8101的RTMP推流方案(开源)及应用搭建说明

针对行业伙伴关注的“Air8101是否有RTMP推流方案”这一问题,本文先明确核心结论:相关方案已开源,可直接用于实际项目参考。为便于伙伴理解方案的可行性,先简要说明Air8101的核心能力——其为研发的工业级多媒体Wi-Fi_UI SoC引擎,支持1024*720分辨率10寸屏、DVP/USB摄像头即插即用、多路视频采集及RTMP推流等核心功能。

主要硬件准备

为确保方案顺利部署,请提前准备以下关键硬件:

  • Air8101核心板

  • USB摄像头配件板AirCAMERA_1030

  • TYPE-C数据线用于供电及固件烧录调试

  • Win10及其以上PC电脑

  • USB HUB(可选,接入多路摄像头时使用)

接线方式如下:

Air8101核心板通过Type-C USB口供电(核心板正面的拨码开发拨到5V一端,背面的功耗测试开关拨到OFF一端),AirCAMERA_1030直插在Air8101核心板上。

开源示例下载

RTMP核心价值在于低延时、高兼容性,广泛应用于直播、安防监控、远程视频巡检等需要实时观看画面的物联网场景。通过RTMP推流,设备端的画面可以被用户通过手机、电脑等终端实时观看,无需等待录制完成再上传。

本示例基于Air8101核心板与AirCAMERA_1030配件板,实现USB摄像头的RTMP实时推流。

2.1 最新源码下载:

https://gitee.com/openLuat/LuatOS/tree/master/module/Air8101/demo/accessory_board/AirCAMERA_1030

2.2 RTMP业务逻辑:

  • 订阅IP_READY信息:确认联网后执行RTMP推流任务;

  • 获取RTMP推流地址:通过http.request()请求从服务器获取推流地址;

  • 初始化摄像头:excamera.open()初始化USB摄像头;

  • RTMP推流:excamera.rtmp()确保摄像头状态正常,然后rtmpc:start()开始推流逻辑;

  • 监控推流状态:循环监控推流过程,每20秒打印一次内存信息。

  • 处理异常情况:推流异常时发送RECONNECT_RTMP信息,然后根据重连函数进行重连;

  • 释放资源:推流结束时excamera.close()关闭摄像头,释放资源。

核心代码如下,完整demo详见源码仓库文件。

--[[@module rtmp_app @summary USB摄像头RTMP推流功能模块 @version1.0@usage 本文件为USB摄像头RTMP推流功能模块,核心业务逻辑为:1. USB 摄像头初始化、帧率配置与H264视频编码2. 通过HTTP请求获取RTMP推流地址3. 连接RTMP服务器并进行视频推流]]-- 引入excamera扩展库localexcamera=require("excamera")localRTMP_TASK_NAME="rtmp_app_task"-- RTMP任务名称 -- HTTP请求获取RTMP服务器地址函数localfunctionrtmp_http_request()localget_device_id=netdrv.mac(socket.LWIP_STA)-- Air8101用STA MAC作为设备ID log.info("打印设备的ID号", get_device_id)localurl="http://video.luatos.com:10030/api-system/deviceVideo/get".."/"..get_device_id log.info("打印的URL", url)localcamera_header={["Accept-Encoding"]="identity",["Host"]="video.luatos.com:10030",["Content-Type"]="application/json"}localpost_body={deviceAccess="8", --8代表接入方式为RTMP deviceUser="admin", -- 平台录像机设置的设备用户(不是登录用的用户名) devicePsd="Air123456"-- 平台录像机设置的设备密码(不是登录用的密码)}-- 发送POST请求并等待响应localcode, headers, body=http.request("POST", url, camera_header, json.encode(post_body)).wait()log.info("打印的请求code", code)ifcode ~=200thenlog.error("HTTP请求失败")returnfalse, nil end log.info("打印的请求body", body)localjson_body=json.decode(body)ifnot json_body or json_body.code ~=200thenlog.error("请求视频URL失败", json_body and json_body.msg or"未知错误")returnfalse, nil endlocalrtmp_url=json_body.data.urlList[1]log.info("请求得到的RTMP地址", rtmp_url)ifnot rtmp_urlthenlog.error("未获取到RTMP地址")returnfalse, nil endreturntrue, rtmp_url endlocalg_s_rtmp_state -- RTMP状态回调函数 -- 连接过程中,如果连接失败,state状态依次为STATE_IDLE->STATE_DISCONNECTING->STATE_IDLE->STATE_ERROR -- 已经建立了连接,推流过程中,如果本地调用disconnect接口,state状态依次为STATE_IDLE->STATE_DISCONNECTING->STATE_IDLE -- 已经建立了连接,推流过程中,如果网络或者服务器出现了异常,或者本地发送数据出现了异常,state状态依次为STATE_IDLE->STATE_DISCONNECTING->STATE_IDLE->STATE_ERRORlocalfunctionrtmp_state_callback(state)-- 打印RTMP状态变化基础日志 log.info("rtmp_state_callback state", state)-- 根据不同状态执行对应逻辑ifstate==rtmp.STATE_IDLEthenlog.info("空闲状态,可能和推流时效有关,需要等待一段时间,再尝试重连")ifg_s_rtmp_state==rtmp.STATE_DISCONNECTINGthensys.sendMsg(RTMP_TASK_NAME,"RTMP_EVENT","DISCONNECTED")end elseif state==rtmp.STATE_CONNECTINGthenlog.info("正在连接")elseif state==rtmp.STATE_HANDSHAKINGthenlog.info("握手中")elseif state==rtmp.STATE_CONNECTEDthenlog.info("已连接")sys.sendMsg(RTMP_TASK_NAME,"RTMP_EVENT","CONNECTED")elseif state==rtmp.STATE_PUBLISHINGthenlog.info("推流中")elseif state==rtmp.STATE_DISCONNECTINGthenlog.info("正在断开")elseif state==rtmp.STATE_ERRORthenlog.info("错误")end g_s_rtmp_state=state end -- RTMP main task 的任务处理函数localfunctionrtmp_task()localcamera_opened, msg, rtmpc, success, rtmp_urlwhiletruedo--1. 如果当前时间点设置的默认网卡还没有连接成功,一直在这里循环等待whilenot socket.adapter(socket.dft())dolog.warn("rtmp_task","wait IP_READY", socket.dft())-- 在此处阻塞等待默认网卡连接成功的消息"IP_READY"-- 或者等待1秒超时退出阻塞等待状态;-- 注意:此处的1000毫秒超时不要修改的更长; -- 因为当使用exnetif.set_priority_order配置多个网卡连接外网的优先级时,会隐式的修改默认使用的网卡 -- 当exnetif.set_priority_order的调用时序和此处的socket.adapter(socket.dft())判断时序有可能不匹配 -- 此处的1秒,能够保证,即使时序不匹配,也能1秒钟退出阻塞状态,再去判断socket.adapter(socket.dft())sys.waitUntil("IP_READY",1000)end -- 检测到了IP_READY消息 log.info("rtmp_task","recv IP_READY", socket.dft())-- 清空此task绑定的消息队列中的未处理的消息 sys.cleanMsg(RTMP_TASK_NAME)--2. HTTP请求获取RTMP服务器地址 success, rtmp_url=rtmp_http_request()ifnot successthenlog.error("获取RTMP地址失败")goto EXCEPTION_PROC end --3. 配置摄像头 camera_opened=excamera.open({id=camera.USB, sensor_width=1280, sensor_height=720, usb_port=1})ifnot camera_openedthenlog.error("摄像头初始化失败")goto EXCEPTION_PROC end -- 启动摄像头 log.info("启动摄像头...")ifnot excamera.rtmp()thenlog.error("无法启动摄像头")goto EXCEPTION_PROC end -- 创建RTMP客户端 rtmpc=rtmp.create(rtmp_url)ifnot rtmpcthenlog.error("rtmp.create","创建RTMP客户端失败")goto EXCEPTION_PROC end log.info("rtmp.create","RTMP客户端创建成功")-- 设置RTMP状态回调 rtmpc:setCallback(rtmp_state_callback)-- 连接RTMP服务器 log.info("开始连接RTMP服务器...")success=rtmpc:connect()ifnot successthenlog.error("连接RTMP服务器失败")goto EXCEPTION_PROC end -- 推流状态的处理调度逻辑whiletruedo-- 等待消息 msg=sys.waitMsg(RTMP_TASK_NAME,"RTMP_EVENT")ifmsgthenlog.info("rtmp_task waitMsg", msg[2], msg[3], msg[4])-- 连接成功ifmsg[2]=="CONNECTED"then-- 直接启动推流,不检查返回值 log.info("准备开始推流")rtmpc:start()log.info("推流已启动")-- 连接失败/连接断开 elseif msg[2]=="DISCONNECTED"thenbreak-- 需要主动关闭连接 -- 用户需要主动关闭rtmp连接时,可以调用sys.sendMsg(RTMP_TASK_NAME,"RTMP_EVENT","CLOSE")elseif msg[2]=="CLOSE"then-- 主动断开rtmp client连接 rtmpc:disconnect()end end end -- 出现异常 ::EXCEPTION_PROC:: -- 清空此task绑定的消息队列中的未处理的消息 sys.cleanMsg(RTMP_TASK_NAME)--5. 关闭推流 log.info("推流结束,开始释放资源")-- 关闭摄像头ifcamera_openedthenexcamera.close()log.info("excamera已关闭")end -- 关闭RTMP客户端ifrtmpcthenrtmpc:stop()log.info("RTMP推流已停止")rtmpc:disconnect()log.info("RTMP连接已断开")rtmpc:destroy()log.info("RTMP客户端已销毁")end -- 确保所有状态重置 log.info("所有资源已释放,5秒后重连")--5秒后跳转到循环体开始位置,自动发起重连 sys.wait(5000)end endlocalfunctionwifi_sta_func(evt, data)-- evt 可能的值有:"CONNECTED","DISCONNECTED"-- 当evt=CONNECTED, data是连接的AP的ssid, 字符串类型 -- 当evt=DISCONNECTED, data断开的原因, 整数类型 log.info("收到STA事件", evt, data)ifevt=="DISCONNECTED"thensys.sendMsg(RTMP_TASK_NAME,"RTMP_EVENT","DISCONNECTED")end end -- 内存检查函数localfunctionmemory_check()whiletruedo-- 等待20秒 sys.wait(20000)-- 打印系统内存使用信息 log.info("系统内存使用情况", rtos.meminfo("sys"))-- 打印Lua虚拟机内存使用信息 log.info("Lua虚拟机内存使用情况", rtos.meminfo("lua"))end end -- wifi的STA相关事件 sys.subscribe("WLAN_STA_INC", wifi_sta_func)-- 运行这个task的处理函数rtmp_task sys.taskInitEx(rtmp_task, RTMP_TASK_NAME)-- 启动内存检查任务 sys.taskInit(memory_check)
2.3 RTMP推流功能核心步骤:
  • 搭建好硬件环境;

  • 修改rtmp_app.lua中的deviceUser、devicePsd参数;

  • 修改netdrv_wifi.lua 中的Wi-Fi账号密码;

  • 打开main.lua文件中require “rtmp_app”,同时注释掉:

    require “take_photo_http_post”;

  • 烧录内核固件和相关demo成功后,自动开机运行;

  • 可以看到代码运行结果如下,日志中如果出现以下类似打印则说明RTMP推流成功。

音视频平台查看

目前,音视频测试平台已开放安卓系统移动端APP下载和PC端浏览器操作。

本文以PC端为例,支持使用共享账号(账号:AirVideo,密码:123456)在线查看挂测设备,也支持用户使用IoT账号自主添加配置在线设备。

自主配置设备操作要点如下:

3.1 平台网址

在浏览器打开音视频平台:https://video.luatos.com:8083/login?redirect=/real-time

3.2 账号密码

账号密码与您的IoT平台账号可通用。

3.3 新增设备

参照下图按步点击,注意设备账户密码需与代码中日配置一致。

3.4 查看推流视频

点击实时视频,查看自己设备的推流情况。

基于上述Air8101的核心能力及开源方案的基础信息,后续将通过具体硬件组合(Air8101核心板+AirCAMERA_1030摄像头配件板),详细讲解如何借助LuatOS与音视频平台搭建USB摄像头实时推流应用,助力行业客户高效完成视频上云部署。

http://www.jsqmd.com/news/690247/

相关文章:

  • C++ MCP网关接入提速5.8倍的关键路径:从协议解析到内存池优化的7层穿透式调优指南
  • 3个月速成模型大师!2026年大模型进阶秘籍,薪资直接翻倍!
  • ColumnTransformer:高效处理混合特征的数据预处理利器
  • 2026年Q2新余全屋整装技术要点与理性选择参考 - 优质品牌商家
  • 漫画版图文解说带你了解:黑客为什么不攻击微信和支付宝钱包?真正的原因竟然是这样?!
  • Transformer注意力掩码:原理、实现与优化实践
  • GroupKFold实战:从原理到代码,解决数据泄露的交叉验证方案
  • 量化交易提速,从行情接口开始
  • 缅甸花梨木沙发核心技术鉴别与场景适配指南:花梨木家具,刺猬紫檀沙发,大果紫檀红木茶台,大果紫檀餐桌,实力盘点! - 优质品牌商家
  • 算法训练营第十天 |80. 删除有序数组中的重复项 II
  • GCC 14 + Clang 18双编译器适配方案,从零部署C内存安全规范:5类高危函数替换清单全公开
  • 长芯微LMD9633完全P2P替代AD9633,四通道12位采样80/105/125MSPS 模数转换器ADC
  • 频率学派与贝叶斯统计:核心差异与应用场景解析
  • 快捷支付频繁风控?银联通道轻松解决
  • 目前正规的隔墙板公司价格
  • VibeVoice-Realtime-0.5B部署教程:server.log日志排查常见问题
  • VSCode 2026农业插件开发避坑清单:92%开发者踩中的MQTT QoS2离线重传陷阱,含可运行的田间断网模拟测试套件
  • 中兴光猫隐藏功能解锁指南:zteOnu工具3步获取超级权限
  • 别再乱接线了!STM32F407ZGT6连接ST-LINK与USB转TTL的保姆级图文指南(附舵机驱动)
  • 神泣纷争手游:官网下载评测 - 正版玩法深度解析
  • 半失能卧床老人护理实操分享|68岁老人日常照料全流程(附注意事项)
  • 从停机到秒级自愈:Docker 27健康探测+设备数字孪生联动实践——某汽车焊装线72小时零非计划停机实录
  • C#处理时间戳别再踩坑了!秒与毫秒转换的3个常见错误与最佳实践
  • Docker 27容器逃逸漏洞CVE-2024-3094已触发3起金融数据侧漏——紧急升级清单与热补丁验证指南(附渗透测试POC)
  • 从BJT到IGBT:一张图看懂五大功率器件怎么选(附应用场景对比)
  • DDrawCompat终极指南:让经典DirectX游戏在现代Windows系统上流畅运行的完整解决方案
  • Weka机器学习14天速成:零代码实战指南
  • 终极B站视频下载神器:5分钟搞定离线观看与批量收藏
  • 告别屏幕撕裂和亮度不均:手把手教你用ILI9341的B组命令优化显示效果
  • OpenGL/ES开发避坑指南:用glGetError函数给你的代码做个‘体检’(附完整C++示例)