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从中序与后序遍历序列构造二叉树这两道题有些类似,相关代…...

您必须尝试的 4 种经典特征提取技术!
一、说明 特征提取如何实现?其手段并不是很多,有四个基本方法,作为AI工程师不能不知。因此,本篇将对四种特征提取给出系统的方法。 二、概述 图像分类长期以来一直是计算机视觉领域的热门话题,并希望能够保持这种状态。…...

Unity中Shader的遮罩的实现
文章目录 前言一、遮罩效果的实现主要是使用对应的纹理实现的,在属性中暴露对应的遮罩纹理,对其进行采样后,最后相乘输出即可二、如果需要像和主要纹理一样流动,则需要使用和_Time篇一样的方法实现流动即可 前言 Unity中Shader的…...

架构师成长之路|Redis key过期清除策略
Eviction policies maxmemory 100mb 当我们设置的内存达到指定的内存量时,清除策略的配置方式决定了默认行为。Redis可以为可能导致使用更多内存的命令返回错误,也可以在每次添加新数据时清除一些旧数据以返回到指定的限制。 当达到最大内存限制时,Redis所遵循的确切行为是…...

ubuntu20.04使用privoxy进行http代理转http代理,并定制http代理头(hide-user-agent的使用方法)
#sudo apt-get update;sudo apt install -y privoxy #sudo apt remove privoxyprivoxy --version; rootfv-az1239-825:/tmp# privoxy --version Privoxy version 3.0.28 (https://www.privoxy.org/) rootfv-az1239-825:/tmp# 安装完毕后,先停止服务,修改配置文件,再启动服…...

任意文件读取
文章目录 渗透测试漏洞原理任意文件读取1. 任意文件读取概述1.1 漏洞成因1.2 漏洞危害1.3 漏洞分类1.4 任意文件读取1.4.1 文件读取1.4.2 任意文件读取1.4.3 权限问题 1.5 任意文件下载1.5.1 一般情况1.5.2 PHP实现1.5.3 任意文件下载 2. 任意文件读取攻防2.1 路径过滤2.1.1 过…...

微信小程序餐饮外卖系统设计与实现
摘 要 随着现在的“互联网”的不断发展。现在传统的餐饮业也朝着网络化的方向不断的发展。现在线上线下的方式来实现餐饮的获客渠道增加,可以更好地帮助餐饮企业实现更多、更广的获客需求,实现更好的餐饮销售。截止到2021年末,我国的外卖市场…...

一文速览嵌入式六大出口
嵌入式行业的前景确实十分广阔,并且在许多领域都发挥着重要作用。以下是一些关键点,说明嵌入式系统的发展潜力和前途: 1. 物联网(IoT):嵌入式系统是实现智能家居、智能城市、智能工厂等物联网设备的核心。物…...

华为云云服务器评测 | 宝塔8.0镜像应用
目录 🍒写在前面 🍒产品优势 🍒购买服务器 🍒服务器配置 🍒登录宝塔页面 🦐博客主页:大虾好吃吗的博客 🦐专栏地址:闲谈专栏地址 写在前面 云耀云服务器L实例是新一代开箱…...

构建简单的Node.js HTTP服务器,发布公网远程访问的快速方法
文章目录 前言1.安装Node.js环境2.创建node.js服务3. 访问node.js 服务4.内网穿透4.1 安装配置cpolar内网穿透4.2 创建隧道映射本地端口 5.固定公网地址 前言 Node.js 是能够在服务器端运行 JavaScript 的开放源代码、跨平台运行环境。Node.js 由 OpenJS Foundation࿰…...

ModaHub魔搭社区:向量数据库产业的现状与技术挑战
I. 向量数据库的崛起 什么是向量数据库 在过去的一段时间里,向量数据库逐渐在数据库领域崭露头角。那么,什么是向量数据库呢?简单来说,向量数据库是一种专门设计用来处理向量数据的数据库。这些向量数据可以是物理测量、机器学习模型输出、地理空间数据等。向量数据库使用…...