Unity3D下如何采集camera场景数据并推送RTMP服务?
Unity3D使用场景
Unity3D是非常流行的游戏开发引擎,可以创建各种类型的3D和2D游戏或其他互动应用程序。常见使用场景如下:
- 游戏开发:Unity3D是一个广泛用于游戏开发的环境,适用于创建各种类型的游戏,包括动作游戏、角色扮演游戏、策略游戏、冒险游戏等。
- 虚拟现实:Unity3D也常用于虚拟现实(VR)开发,它提供了对VR设备的支持,如Oculus Rift和HTC Vive。
- 交互式演示:Unity3D可以用于创建各种类型的交互式演示,如产品原型、建筑和设计模拟器、教育应用程序等。
- 实时渲染:Unity3D的实时渲染功能可以用于创建电影级的特效和动画,以及用于视觉预览和产品渲染。
- 跨平台开发:Unity3D支持多个平台,包括PC、Mac、Linux、Android、iOS、Windows等,这使得开发者可以更容易地将他们的应用程序和游戏移植到不同的平台。
无论你是在哪个领域使用Unity3D,都需要了解其基本的工具和功能,包括场景编辑器、游戏对象、组件、脚本等。同时,还需要掌握一些基本的编程语言,如C#,以编写游戏逻辑和控制流程。
如何获取Camera场景数据
Unity3D获取摄像机数据通常用RenderTexture和RenderTexture.GetPixel方法来获取数据,把捕获屏幕的图像,存储在一个Texture2D实例中,用这个实例获取RGB数据。需要注意的是,需要为输出纹理创建一个新的纹理对象,否则可能会在屏幕上看到一片空白。示例代码如下:
using UnityEngine; public class GetCameraData : MonoBehaviour
{ public Texture2D outputTexture; // 输出纹理,用于存储RGB数据 public RenderTexture renderTexture; // RenderTexture实例,用于捕获屏幕图像 void Start() { // 创建一个RenderTexture实例 renderTexture = new RenderTexture(Screen.width, Screen.height, 24); // 获取当前摄像机 Camera camera = GetComponent<Camera>(); // 将当前摄像机的屏幕输出设置为刚刚创建的RenderTexture实例 camera.targetTexture = renderTexture; // 创建一个空的Texture2D实例,用于存储从RenderTexture读取的RGB数据 outputTexture = new Texture2D(Screen.width, Screen.height); } void Update() { // 从RenderTexture中读取RGB数据,并存储到outputTexture中 RenderTexture.active = renderTexture; outputTexture.ReadPixels(new Rect(0, 0, Screen.width, Screen.height), 0, 0); outputTexture.Apply(); }
}
如何实现RTMP推送服务
本文以大牛直播SDK开发的Unity3D下Android平台的RTMP推送camera场景的demo为例,结合Unity和原生模块交互,大概介绍下核心实现逻辑。
开始推送RTMP服务:
public bool StartRtmpPusher(){if (is_pushing_rtmp_){Debug.Log("已推送.."); return false;}if(!is_rtsp_publisher_running_){InitAndSetConfig();}if (pusher_handle_ == 0) {Debug.LogError("StartRtmpPusher, publisherHandle is null..");return false;}NT_PB_U3D_SetPushUrl(pusher_handle_, rtmp_push_url_);int is_suc = NT_PB_U3D_StartPublisher(pusher_handle_);if (is_suc == DANIULIVE_RETURN_OK){Debug.Log("StartPublisher success.."); is_pushing_rtmp_ = true;}else{Debug.LogError("StartPublisher failed..");return false;}return true;}
InitAndSetConfig()完成常规参数设置,比如软硬编码、帧率、码率等参数设置,如果需要采集audio,还可以把麦克风采集到的audio和audioclip获取到的audio数据mix后输出:
private void InitAndSetConfig(){if ( java_obj_cur_activity_ == null ){Debug.LogError("getApplicationContext is null");return;}int audio_opt = 1;int video_opt = 3;video_width_ = camera_.pixelWidth;video_height_ = camera_.pixelHeight;pusher_handle_ = NT_PB_U3D_Open(audio_opt, video_opt, video_width_, video_height_);if (pusher_handle_ != 0){Debug.Log("NT_PB_U3D_Open success");NT_PB_U3D_Set_Game_Object(pusher_handle_, game_object_);}else{Debug.LogError("NT_PB_U3D_Open failed!");return;}int fps = 30;int gop = fps * 2;if(video_encoder_type_ == (int)PB_VIDEO_ENCODER_TYPE.VIDEO_ENCODER_HARDWARE_AVC){int h264HWKbps = setHardwareEncoderKbps(true, video_width_, video_height_);h264HWKbps = h264HWKbps * fps / 25;Debug.Log("h264HWKbps: " + h264HWKbps);int isSupportH264HWEncoder = NT_PB_U3D_SetVideoHWEncoder(pusher_handle_, h264HWKbps);if (isSupportH264HWEncoder == 0) {NT_PB_U3D_SetNativeMediaNDK(pusher_handle_, 0);NT_PB_U3D_SetVideoHWEncoderBitrateMode(pusher_handle_, 1); // 0:CQ, 1:VBR, 2:CBRNT_PB_U3D_SetVideoHWEncoderQuality(pusher_handle_, 39);NT_PB_U3D_SetAVCHWEncoderProfile(pusher_handle_, 0x08); // 0x01: Baseline, 0x02: Main, 0x08: High// NT_PB_U3D_SetAVCHWEncoderLevel(pusher_handle_, 0x200); // Level 3.1// NT_PB_U3D_SetAVCHWEncoderLevel(pusher_handle_, 0x400); // Level 3.2// NT_PB_U3D_SetAVCHWEncoderLevel(pusher_handle_, 0x800); // Level 4NT_PB_U3D_SetAVCHWEncoderLevel(pusher_handle_, 0x1000); // Level 4.1 多数情况下,这个够用了//NT_PB_U3D_SetAVCHWEncoderLevel(pusher_handle_, 0x2000); // Level 4.2// NT_PB_U3D_SetVideoHWEncoderMaxBitrate(pusher_handle_, ((long)h264HWKbps)*1300);Debug.Log("Great, it supports h.264 hardware encoder!");}}else if(video_encoder_type_ == (int)PB_VIDEO_ENCODER_TYPE.VIDEO_ENCODER_HARDWARE_HEVC){int hevcHWKbps = setHardwareEncoderKbps(false, video_width_, video_height_);hevcHWKbps = hevcHWKbps*fps/25;Debug.Log("hevcHWKbps: " + hevcHWKbps);int isSupportHevcHWEncoder = NT_PB_U3D_SetVideoHevcHWEncoder(pusher_handle_, hevcHWKbps);if (isSupportHevcHWEncoder == 0) {NT_PB_U3D_SetNativeMediaNDK(pusher_handle_, 0);NT_PB_U3D_SetVideoHWEncoderBitrateMode(pusher_handle_, 0); // 0:CQ, 1:VBR, 2:CBRNT_PB_U3D_SetVideoHWEncoderQuality(pusher_handle_, 39);// NT_PB_U3D_SetVideoHWEncoderMaxBitrate(pusher_handle_, ((long)hevcHWKbps)*1200);Debug.Log("Great, it supports hevc hardware encoder!");}}else {if (is_sw_vbr_mode_) //H.264 software encoder{int is_enable_vbr = 1;int video_quality = CalVideoQuality(video_width_, video_height_, true);int vbr_max_bitrate = CalVbrMaxKBitRate(video_width_, video_height_);vbr_max_bitrate = vbr_max_bitrate * fps / 25;NT_PB_U3D_SetSwVBRMode(pusher_handle_, is_enable_vbr, video_quality, vbr_max_bitrate);//NT_PB_U3D_SetSWVideoEncoderSpeed(pusher_handle_, 2);}}NT_PB_U3D_SetAudioCodecType(pusher_handle_, 1);NT_PB_U3D_SetFPS(pusher_handle_, fps);NT_PB_U3D_SetGopInterval(pusher_handle_, gop);if (audio_push_type_ == (int)PB_AUDIO_OPTION.AUDIO_OPTION_MIC_EXTERNAL_PCM_MIXER|| audio_push_type_ == (int)PB_AUDIO_OPTION.AUDIO_OPTION_TWO_EXTERNAL_PCM_MIXER){NT_PB_U3D_SetAudioMix(pusher_handle_, 1);}else{NT_PB_U3D_SetAudioMix(pusher_handle_, 0);}}
投递video数据的逻辑实现如下:
void PostVideoData() {if(pusher_handle_ == 0)return;if(!is_pushing_rtmp_ && !is_rtsp_publisher_running_)return;if (textures_poll_ == null)return;int w = camera_.pixelWidth;int h = camera_.pixelHeight;if (w != video_width_ || h != video_height_) {Debug.Log("PostVideoData resolution changed++ width: " + w + " height: " + h);if(render_texture_ != null) {render_texture_.Release();render_texture_ = null;}video_width_ = w;video_height_ = h;}if (null == render_texture_ ) {render_texture_ = new RenderTexture(video_width_, video_height_, 16);render_texture_.Create();}Texture2D image_texture = textures_poll_.get(video_width_, video_height_);if (null == image_texture)return;...image_texture.ReadPixels(new Rect(0, 0, video_width_, video_height_), 0, 0, false);...post_image_worker_.post(image_texture, is_vertical_flip_, is_horizontal_flip_, scale_width_, scale_height_);}
如果需要停止RTMP推送:
private void StopRtmpPusher(){if(!is_pushing_rtmp_)return;NT_PB_U3D_StopPublisher(pusher_handle_);if(!is_rtsp_publisher_running_){NT_PB_U3D_Close(pusher_handle_);pusher_handle_ = 0;NT_PB_U3D_UnInit();}is_pushing_rtmp_ = false;}
技术总结
Unity3D下采集camera场景并推送RTMP具有重要的意义,可以为实时监控、在线直播、视频教程制作、增强现实和虚拟现实应用以及数据记录和分析等领域提供有力的支持。比如,采集camera场景可以用于增强现实和虚拟现实应用。在AR中,可以通过采集实际场景的画面,将虚拟元素与现实场景进行融合,增强沉浸感和互动性。
相关文章:

Unity3D下如何采集camera场景数据并推送RTMP服务?
Unity3D使用场景 Unity3D是非常流行的游戏开发引擎,可以创建各种类型的3D和2D游戏或其他互动应用程序。常见使用场景如下: 游戏开发:Unity3D是一个广泛用于游戏开发的环境,适用于创建各种类型的游戏,包括动作游戏、角…...

黑客可利用 Windows 容器隔离框架绕过端点安全系统
新的研究结果表明,攻击者可以利用一种隐匿的恶意软件检测规避技术,并通过操纵 Windows 容器隔离框架来绕过端点安全的解决方案。 Deep Instinct安全研究员丹尼尔-阿维诺姆(Daniel Avinoam)在本月初举行的DEF CON安全大会上公布了…...
STM32注入通道
什么是注入通道? 注入通道是ADC的一种采样方式,主要用于在规则通道转换期间并行处理快速变化信号的采样。注入通道的转换可以在规则通道转换时强行插入,相当于一个“中断通道”。当有注入通道需要转换时,规则通道的转换会停止,优先执行注入通道的转换,当注入通道的转换执…...

WebVR — 网络虚拟现实
推荐:使用 NSDT编辑器 快速搭建3D应用场景 虚拟现实设备 随着Oculus Rift和许多其他生产设备即将上市,未来看起来很光明——我们已经有足够的技术来使VR体验“足够好”,可以玩游戏。有许多设备可供选择:像Oculus Rift或HTC Vive这…...
ASP.NET Core 的 Routing
ASP.NET Core 的 Routing ASP.NET Core 的 controllers 使用Routing 中间件匹配客户端的 url 请求,然后映射到对应的 controller 的处理方法(Action)上。 Actions 可以是 常规路由 或 属性路由 的映射。 MVC App一般使用常规路由。 REST API…...

IBM Spectrum LSF Explorer 为要求苛刻的分布式和任务关键型高性能技术计算环境提供强大的工作负载管理
IBM Spectrum LSF Explorer 适用于 IBM Spectrum LSF 集群的强大、轻量级报告解决方案 亮点 ● 允许不同的业务和技术用户使用单一解决方案快速创建和查看报表和仪表板 ● 利用可扩展的库提供预构建的报告 ● 自定义并生成性能、工作负载和资源使用情况的报…...

RHCE——十一、NFS服务器
NFS服务器 一、简介1、NFS背景介绍2、生产应用场景 二、NFS工作原理1、示例图2、流程 三、NFS的使用1、安装2、配置文件3、主配置文件分析3.1 实验1 4、NFS账户映射4.1 实验24.2 实验3 四、autofs自动挂载服务1、产生原因2、安装3、配置文件分析4、实验45、实验5 一、简介 1、…...
Python编程练习与解答 练习100:随机密码
编写一个生成最忌密码的函数,密码的长度应该在7-10个字符之间。每个字符应该从ASCII表的第33位到126位中随机选择。函数不接受任何参数,返回随机生成的密码作为位移结果。在文件的main程序中显示随机生成的密码。main程序只在解答没有被导入另一个文件时…...

华为云云服务器评测 | 从零开始:云耀云服务器L实例的全面使用解析指南
文章目录 一、前言二、云耀云服务器L实例要点介绍2.1 什么是云耀云服务器L实例2.1.1 浅析云耀云服务器L实例 2.2 云耀云服务器L实例的产品定位2.3 云耀云服务器L实例优势2.4 云耀云服务器L实例支持的镜像与应用场景2.5 云耀云服务器L实例与弹性云服务器(ECS…...

欧科云链研究院探析Facebook稳定币发行经历会不会在PayPal重演
引言 作者最近的报告-探析PayPal发行稳定币是否会重蹈Facebook覆辙-近期被英国的金融时报(中文版)刊登。由于该报告在欧科云链研究院内部反响较好,下面就带大家简单的剖析这篇报告的主要内容。 *这篇文章主要由对比分析(已删减&a…...
docker 容器pip、git安装异常;容器内web对外端口ping不通
1、docker 容器pip、git安装异常 错误信息: git clone https://github.com/vllm-project/vllm.git Cloning into ‘vllm’… fatal: unable to access ‘https://github.com/vllm-project/vllm.git/’: Failed to connect to 127.0.0.1 port 10808: Connection ref…...

SpringBoot Mybatis 多数据源 MySQL+Oracle+Redis
一、背景 在SpringBoot Mybatis 项目中,需要连接 多个数据源,连接多个数据库,需要连接一个MySQL数据库和一个Oracle数据库和一个Redis 二、依赖 pom.xml <dependencies><dependency><groupId>org.springframework.boot&l…...
【JavaScript 16】对象继承 原型对象属性 原型链 构造函数属性 instanceof运算符 继承 多重继承 模块
对象继承 原型对象概述instanceof运算符构造函数的继承多重继承模块 A 对象通过继承 B 对象,就能 直接拥有 B 对象的所有属性和方法(利于代码复用) 大部分面向对象的编程语言都是通过类(class)实现对象的继承 但 传统…...

地下管线三维自动建模软件MagicPipe3D V3.0发布
2023年9月1日经纬管网建模系统MagicPipe3D V3.0正式发布,该版本经过众多用户应用和反馈,在三维地下管线建模效果、效率、适配性等方面均有显著提升!MagicPipe3D本地离线参数化构建地下管网模型(包括管道、接头、附属设施等&#x…...

百度等8家企业首批上线大模型服务;大语言模型微调之道
🦉 AI新闻 🚀 百度等8家企业首批上线大模型服务 摘要:百度、字节、中科院旗下8家企业/机构的大模型通过备案,正式面向公众提供服务。百度旗下AI大模型产品文心一言率先开放,用户可下载App或登录官网体验。百川智能也…...

二、Mycat2 相关概念及读写分离
第三章 Mycat2 相关概念 3.1 概念描述 1、分库分表 按照一定规则把数据库中的表拆分为多个带有数据库实例,物理库,物理表访问路 径的分表。 解读:分库:一个电商项目,分为用户库、订单库等等。 分表:一张订单表数据数百万ÿ…...

react利用wangEditor写评论和@功能
先引入wangeditor写评论功能 import React, { useEffect, useState, useRef, forwardRef, useImperativeHandle } from react; import wangeditor/editor/dist/css/style.css; import { Editor, Toolbar } from wangeditor/editor-for-react; import { Button, Card, Col, For…...

Android之布局转圆角
Android之布局转圆角 文章目录 Android之布局转圆角说明一、效果图二、实现步骤1.自定义RoundRelativeLayout2.使用 总结 说明 很多需求比较无语,需要某个布局转圆角,像个显眼包一样,所以为了满足显眼包,必须整呐提示:…...

Linux的目录结构特点
Linux的目录结构特点 1、使用树形目录结构来组织和管理文件。 2、整个系统只有一个根目录(树根),Linux的根目录用“/”表示。 3、其他所有分区以及外部设备(如硬盘,光驱等)都是以根目录为起点࿰…...

【算法与数据结构】654、LeetCode最大二叉树
文章目录 一、题目二、解法三、完整代码 所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。 一、题目 二、解法 思路分析:【算法与数据结构】106、LeetCode从中序与后序遍历序列构造二叉树这两道题有些类似,相关代…...

Docker 离线安装指南
参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性,不同版本的Docker对内核版本有不同要求。例如,Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本,Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...

Cloudflare 从 Nginx 到 Pingora:性能、效率与安全的全面升级
在互联网的快速发展中,高性能、高效率和高安全性的网络服务成为了各大互联网基础设施提供商的核心追求。Cloudflare 作为全球领先的互联网安全和基础设施公司,近期做出了一个重大技术决策:弃用长期使用的 Nginx,转而采用其内部开发…...
【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论
路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中(图1): mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

【Linux】Linux 系统默认的目录及作用说明
博主介绍:✌全网粉丝23W,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物…...
C#学习第29天:表达式树(Expression Trees)
目录 什么是表达式树? 核心概念 1.表达式树的构建 2. 表达式树与Lambda表达式 3.解析和访问表达式树 4.动态条件查询 表达式树的优势 1.动态构建查询 2.LINQ 提供程序支持: 3.性能优化 4.元数据处理 5.代码转换和重写 适用场景 代码复杂性…...

Vue3 PC端 UI组件库我更推荐Naive UI
一、Vue3生态现状与UI库选择的重要性 随着Vue3的稳定发布和Composition API的广泛采用,前端开发者面临着UI组件库的重新选择。一个好的UI库不仅能提升开发效率,还能确保项目的长期可维护性。本文将对比三大主流Vue3 UI库(Naive UI、Element …...
flow_controllers
关键点: 流控制器类型: 同步(Sync):发布操作会阻塞,直到数据被确认发送。异步(Async):发布操作非阻塞,数据发送由后台线程处理。纯同步(PureSync…...
webpack面试题
面试题:webpack介绍和简单使用 一、webpack(模块化打包工具)1. webpack是把项目当作一个整体,通过给定的一个主文件,webpack将从这个主文件开始找到你项目当中的所有依赖文件,使用loaders来处理它们&#x…...