Unity实现Camera和Audio数据的低延迟RTMP推送技术探讨

2023-11-15

关于Unity实现RTMP直播推送技术方案,之前零散的写过几篇介绍,得到了好多开发者的关注。以Android平台为例,目前视频这块,我们demo实现的是Camera数据的采集,然后编码投递到底层,如果设备没有性能瓶颈,可达到高帧率(60帧)均匀的RTMP推送效果。

视频采集这块,不再是难题,用ReadPixels从当前Render Target读取到图像数据即可,视频编码的话,我们分软编码、硬编码两块,硬编码,我们又实现了native层的硬编(5.0+以上版本),效率更高,native层我们做的可圈可点的一个地方是,armv7a也可以支持。

视频采集这块,需要考虑的是,如果场景分辨率发送变化,需要自动适配,帧与帧之间的连贯问题。

数据的采集,也可以参考官方给出来的示例:

using System.IO;
using UnityEngine;
using UnityEngine.Networking;
using System.Collections;
 
public class ExampleClass : MonoBehaviour
{
    // Take a shot immediately
    IEnumerator Start()
    {
        UploadPNG();
        yield return null;
    }
 
    IEnumerator UploadPNG()
    {
        // We should only read the screen buffer after rendering is complete
        yield return new WaitForEndOfFrame();
 
        // Create a texture the size of the screen, RGB24 format
        int width = Screen.width;
        int height = Screen.height;
        Texture2D tex = new Texture2D(width, height, TextureFormat.RGB24, false);
 
        // Read screen contents into the texture
        tex.ReadPixels(new Rect(0, 0, width, height), 0, 0);
        tex.Apply();
 
        // Encode texture into PNG
        byte[] bytes = tex.EncodeToPNG();
        Destroy(tex);
 
        // For testing purposes, also write to a file in the project folder
        // File.WriteAllBytes(Application.dataPath + "/../SavedScreen.png", bytes);
 
 
        // Create a Web Form
        WWWForm form = new WWWForm();
        form.AddField("frameCount", Time.frameCount.ToString());
        form.AddBinaryData("fileUpload", bytes);
 
        // Upload to a cgi script
        var w = UnityWebRequest.Post("http://localhost/cgi-bin/env.cgi?post", form);
        yield return w.SendWebRequest();
        if (w.result != UnityWebRequest.Result.Success)
            print(w.error);
        else
            print("Finished Uploading Screenshot");
        yield return null;
    }
}

有人说官方示例太简单,实际上官方示例,拿到数据,直接投递到底层即可,底层接口设计如下:


/*
 * Github: https://github.com/daniulive/SmarterStreaming
 */

private const String OnPostLayerImageRGBA8888Native_MethodName = "OnPostLayerImageRGBA8888Native";
        
        private int postLayerImageRGBA8888Native(long handle, int index, int left, int top,
                                            long rgba_plane, int offset, int row_stride, int width, int height,
                                            int is_vertical_flip, int is_horizontal_flip,
                                            int scale_width, int scale_height, int scale_filter_mode,
                                            int rotation_degree){

            return obj_.Call<int>(OnPostLayerImageRGBA8888Native_MethodName, handle, index, left, top,
                rgba_plane, offset, row_stride, width, height,
                is_vertical_flip, is_horizontal_flip,
                scale_width, scale_height, scale_filter_mode, rotation_degree);
        }

音频的话,我们支持了几种模式:

    /*定义Audio源选项*/
    public enum PB_AUDIO_OPTION : uint
    {
        AUDIO_OPTION_CAPTURE_MIC = 0x0,             /*采集麦克风音频*/
        AUDIO_OPTION_EXTERNAL_PCM_DATA = 0x1,       /*外部PCM数据*/
        AUDIO_OPTION_MIC_EXTERNAL_PCM_MIXER = 0x2,  /*麦克风+外部PCM数据混音*/
        AUDIO_OPTION_TWO_EXTERNAL_PCM_MIXER = 0x3,  /* 两路外部PCM数据混音*/
    }

分别是采集麦克风、外部PCM、麦克风和外部PCM混音、两路外部PCM的混音,几种模式。

麦克风的数据采集,我们是直接基于原生的Android,通过Unity调用Android实现数据采集推送,外部PCM数据,我们以AudioClip为例,读取到数据,每隔10ms传下去,两路外部PCM也就是两路AudioClip数据投递,JNI层做混音。麦克风和外部PCM数据混音,实际上是为了达到类似授课或者讲解过程中,自带背景音的效果,需要注意的是,AudioClip读到的是float类型的数据,有些音频编码器需要sint16格式,也可以在上层或者底层做下转换。

音频这块,如果是读取文件,还需要考虑的是,如果audio source读过之后,是从头读,还是后面静音?当然不管哪种实现都不难。

数据有了,实现RTMP推送这块,小菜一碟了,由于我们有多年的RTMP推送方面的技术积累,对我们来说,无非就是多一种类型的数据源而已。

经过实际测试,配合我们自研的RTMP播放器,轻松实现超过50帧的RTMP毫秒级延迟的体验,足够应对大多数行业场景了。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Unity实现Camera和Audio数据的低延迟RTMP推送技术探讨 的相关文章

  • Unity中级客户端开发工程师的进阶之路

    上期UWA技能成长系统之 Unity高级客户端开发工程师的进阶之路 得到了很多Unity开发者的肯定 通过系统的学习 可以掌握游戏性能瓶颈定位的方法和常见的CPU GPU 内存相关的性能优化方法 UWA技能成长系统是UWA根据学员的职业发展
  • Unity中按钮检测鼠标状态

    改方法主要是用于按钮检测鼠标的进入 滑出 点击 抬起 长按 长按停止 1 先将下面这个脚本挂载到需要检测鼠标状态的按钮上 using System Collections using System Collections Generic u
  • Unity动画系统详解

    目录 动画编辑器 编辑器面板 动画复用 前言 人形重定向动画 Humanoid 通用动画 Generic 旧版本动画 Legacy 动画控制器 系统状态 切换条件 状态机脚本 IK动画 反向动力学 BlendTree 混合树 Animato
  • UnityVR--组件3--Line Renderer--线性渲染

    目录 线性渲染组件简介 绘制线条Line Renderer组件介绍 绘制拖尾Trail Renderer组件介绍 应用1 使用Line Renderer绘制线段 应用1实现 使用系统工具或自定义工具绘制线段 应用2 Trail Render
  • Unity中实现倒计时的几种方式

    1 Time time using UnityEngine public class TimeTest MonoBehaviour public float secound 10 void Update Timing private flo
  • GooglePlay提审警告(com.google.android.gms:play-services-safetynet:17.0.0)

    1 Goole在今年6月份出的新政策 不在使用safetynet 而使用Play Integrity API 2 项目本身没有使用过safetynet 3 使用了firebase 查阅资料 解决方案如下 implementation pla
  • Unity学习笔记(一)—— 基础知识

    一 基础知识 1 开发团队组成 2 unity特点 图形界面 所见即所得 入门简单 支持C 比OC C 更友好 js 国内外资源丰富 因为使用的人多 跨平台性好 PC端 移动端等 对VR AR的支持最完善 3 成功案例 游戏 炉石传说 神庙
  • unity工程崩溃资源找回

    1 Unity死机未保存场景 当你在Unity中编辑场景 突然死机时 可以在项目文件目录中找到Temp文件夹 双击文件夹 找到 Backupscenes文件夹 把后缀为 backup的文件后缀改为 unity 然后拖进Unity的Proje
  • Unity 键盘控制人物移动——之输入方式代码的编写

    键盘输入 控制人物移动 在我们制作游戏中最常见的需求之一就是使用键盘移动游戏角色 那么我们首先需要获取键盘输入 以下提供两种方法获取键盘 这里尽量通过截图解释让大家理解代码的含义 GetInput void FixedUpdate Move
  • Unity打开工程时卡住的问题

    自从Unity升级了一个版本后 Unity打开工程卡住的问题越来越严重了 具体表现为 选择工程后 Unity窗口消失 但进程还在 有时候等个几分钟能出来 有时候等10分钟都不见得能出来 直观感受上看 似乎是Unity加载工程的时候某一步卡了
  • unity: C#的Action Event Delegate的异同

    目录 一 Action 二 Event 三 Action和Event区别 四 Delegate 总结 Action Event Delegate的异同 前言 Action Event和Delegate都是C 语言中的重要概念 分别用于管理函
  • unity 性能查看工具Profiler

    文章目录 前言 profiler工具介绍 菜单栏 帧视图 模块视图 模块详细信息 通过profiler分析优化游戏性能 最后 前言 每次进行游戏优化的时候都用这个工具查看内存泄漏啊 代码优化啊之类的东西 真的好用 但是之前也就是自己摸索一下
  • Unity打包WebGL的优化常用操作?

    1 贴图部分优化 如果贴图格式时2048 在不影响画面效果的情况下 改成1024或者5 12 还可以缩小包体 2 压缩和解压缩问题 WebGL打包的时候分三种压缩情况 gzip 比Brotli文件打 但打包快 http和https都支持 B
  • unity3d image组件不显示

    需要将UI组件放到画布下面
  • 【Unity】运行时创建曲线(贝塞尔的运用)

    Unity 运行时创建线 贝塞尔的运用 1 实现的目标 在运行状态下创建一条可以使用贝塞尔方法实时编辑的网格曲线 2 原理介绍 2 1 曲线的创建 unity建立网格曲线可以参考 Unity程序化网格体 的实现方法 主要分为顶点 三角面 U
  • VS2022 | 显示Unreal Engine日志

    VS2022 显示Unreal Engine日志 视图 gt 其他窗口 gt Unreal Engine日志 视图 gt 其他窗口 gt Unreal Engine日志
  • 游戏开发常见操作梳理之NPC任务系统

    多数游戏存在任务系统 接下来介绍通过NPC触发任务的游戏制作代码 using System Collections using System Collections Generic using UnityEngine
  • 游戏开发之常见操作梳理——武器装备商店系统(NGUI版)

    游戏开发中经常出现武器商店 接下来为你们带来武器装备商店系统的具体解决办法 后续出UGUI Json版本 敬请期待 武器道具的具体逻辑 using System Collections using System Collections Ge
  • 游戏开发常用实践操作之按动任意键触发

    接下来一些笔记会对于一些大大小小的实践操作进行记录 希望对你有所帮助 在游戏中 我们经常会遇到一些按动任意键触发的操作 接下来展示核心代码 以下是对于Unity中的操作 使用的UI是NGUI 对于核心操作没有影响 你可以自己置换 void
  • 游戏开发中常见系统梳理之背包系统的实现一

    游戏中几乎都存在大大小小的背包系统 接下来我将讲述背包系统具体是如何实现的 完整源码 以下是使用unity NGUI实现 使用txt配置的方法 后续更新UGUI Json实现的背包系统敬请期待 背包中的物品我们常常将其制作成预设体 通过改变

随机推荐

  • Container With Most Water

    Given n non negative integers a1 a2 an where each represents a point at coordinate i ai n vertical lines are drawn such
  • 似然场模型初识

    slam 激光雷达的数学模型之似然场模型 光束模型的缺点 计算量大 每一个位姿需要进行N次raytracing N为每一帧激光的激光束数量 在非结构化环境中 比较杂乱的环境中 使用光束模型会导致当位姿发生微小变化时 得分从非常高一下改变为趋
  • 五人合伙最佳股份分配_有限责任公司与合伙企业傻傻分不清,纳税又有什么不同?...

    我们经常见到许多的公司类型 xx公司xx合伙等等 每种不同的形式纳税是不是有所不同 合伙企业分为 普通合伙企业和有限合伙企业 其中 普通合伙企业又包含特殊的普通合伙企业 1 普通合伙企业由2人以上的普通合伙人 没有上限规定 组成 普通合伙企
  • STL源代码剖析笔记----第一章STL概论与版本简介

    在现在这家公司半年了 虽说也学了不少东西 但是总觉得自己的技术还不够成熟 不过好处就是 有大把的时间可以自己支配 闲来无事便把侯捷先生的STL源代码剖析拿出来看了一下 在工作中用的最多的还是STL 自己也曾尝试些属于自己的一些算法 但是 结
  • easy mock本地部署和nuxt项目初始化

    easy mock本地部署和nuxt项目初始化 一 说明 easy mock和nuxt项目创建初始化用到的nodejs版本有差异 前者需要低版本 后者初始化需要高版本 所以需要nvm管理nodejs版本 安装nvm 下载地址https gi
  • nodejs17/18版本报错:digital envelope routines::unsupported

    一 临时方案 cmd或终端执行 export NODE OPTIONS openssl legacy provider 二 修改系统环境变量 新建一个系统环境变量配置 配置信息如下 NODE OPTIONS openssl legacy p
  • 系统U盘制作工具WinToUSB,也可以将系统安装到U盘

    WinToUSB 轻松将Windows WinPE安装到USB移动硬盘或者U盘 Hasleo WinToUSB是个免费的U盘安装系统工具 可以将操作系统ISO WIM ESD SWM文件或CD DVD光驱安装到U盘或者移动硬盘 Window
  • Hbase学习2:部署

    http dblab xmu edu cn blog install hbase HBASE 官网 https hbase apache org book html preface Use the following legend to i
  • 程序员分类

    程序员 前端 html css javascript bootstrap jQuery Node js Augular TypeScript ReactJS vue js 后端 Java Python Go C C Ruby Node js
  • LeetCode-1615. 最大网络秩【图】

    LeetCode 1615 最大网络秩 图 题目描述 解题思路一 简单暴力 用一个矩阵g记录每对点之间是否连通 如果连通g a b g b a 1 然后用一个一位数组cnt记录每一个点的度 最终答案是每对城市之间的最大网络秩即max cnt
  • 机器学习、深度学习常用专业术语

    主要记录一些深度学习中可能用到的专业术语 一般是碰到了不懂的才记录 所有没有按一定的规律记录 持续更新 1 梯度下降 gradient descent 2 学习速率 learning rate 学习率指每次迭代中 对成本函数的 最小化次数
  • 用 Python 快速追踪基金的收益情况(2022年4月更新)

    来源 Python数据之道 ID PyDataLab 作者 阳哥 大家好 我是阳哥 大家知道 近几年 不少同学都是经由基金进入到股市中的 至于股票和基金到底谁更好 这个仁者见仁智者见智 恐怕一时半会儿也说不清楚 2021年 阳哥曾经分享过
  • 机器学习课后题——贝叶斯

    第四章 贝叶斯分类器 1 简述朴素贝叶斯的优缺点 答 朴素贝叶斯的主要优点有 算法比较简单 易于实现 快速 易于训练 朴素贝叶斯模型有稳定的分类效率 对小规模的数据表现很好 能处理多分类任务 适合增量式训练 尤其是数据量超出内存时 可以一批
  • 今天是我的生日,也是我的离职日!

    前言 时间就是这么巧妙 今天是我的生日 也是我的离职日 职场中有人来 就有人走 本是件很平常的事 在这里祝自己生日快乐 江湖路远 后会有期 今天是我的生日 也是我的离职日 一 往昔 二 ZQ的人事物 三 离职建议 四 后会有期 一 往昔 记
  • 【JavaScript面向对象详解】

    ES6之前的JavaScript面向对象比较不好理解 涉及到很多知识和思想 ES6增加了class和extends来实现类的封装和继承 但是通过babel转换成ES5之后还是之前的一套逻辑 这里 我打算用四篇文章 来讲解一下关于ES5中面向
  • k8s ingress配置wss编排模板

    前段时间遇到了一个k8s配置websocket的问题 需要配置一下 由于wss比较安全 结合tls证书才能配置成功 如果是ws则无法在https的网站上面直接使用 wss才行 下面给出配置文件 希望帮助到需要的伙伴 配置一个新的单独为所有w
  • 【学习笔记】——appium移动端自动化测试实战

    最近学习了appium移动端自动化测试 以qq登录模块的功能进行实战学习 主要涉及到的技术有 python appium unittest 数据驱动 weditor查看元素定位 断言 测试报告 最后以pom模式呈现效果 在学习过程中 除了元
  • java类的静态变量调用_Java学习笔记八---类的静态变量与静态方法的访问与调用方式...

    静态变量又称类变量 静态方法又称类方法 它们统称为静态成员或类成员 静态成员由static修饰 是属于整个类的 所有的对象共享这些静态成员 不需要创建任何对象 静态成员在类装载时就已初始化了 整个运行期间其内存位置不变 直到类卸载 鉴于静态
  • apache 插件开发之过滤器 (filter)

    过滤器 filter A filter is a process that is applied to data that is sent or received by the server Data sent by clients to
  • Unity实现Camera和Audio数据的低延迟RTMP推送技术探讨

    关于Unity实现RTMP直播推送技术方案 之前零散的写过几篇介绍 得到了好多开发者的关注 以Android平台为例 目前视频这块 我们demo实现的是Camera数据的采集 然后编码投递到底层 如果设备没有性能瓶颈 可达到高帧率 60帧