如何在Unity3d下实现RTMP推送摄像头/屏幕数据到RTMP服务器

简介:

一直以来,好多开发者苦于很难在unity3d下实现RTMP直播推送,本次以大牛直播SDK(Github)的Windows平台RTMP推送模块(以推摄像头为例,如需推屏幕数据,设置相关参数即可)为例,介绍下unity3d的RTMP推送集成。

简单来说,Unity3D环境下,可以直接调用C#的接口封装,针对此,我们先做了一层封装 (nt_publisher_wrapper.cs),核心代码如下:

初始化和基础参数设置:

   private bool InitSDK()
    {
        if (!is_pusher_sdk_init_)
        {
            // 设置日志路径(请确保目录存在)
            String log_path = "D:\\pulisherlog";
            NTSmartLog.NT_SL_SetPath(log_path);

            UInt32 isInited = NTSmartPublisherSDK.NT_PB_Init(0, IntPtr.Zero);

            if (isInited != 0)
            {
                Debug.Log("调用NT_PB_Init失败..");
                return false;
            }

            is_pusher_sdk_init_ = true;
        }

        return true;
    }

    public bool OpenPublisherHandle(uint video_option, uint audio_option)
    {
        if (publisher_handle_ != IntPtr.Zero)
        {
            return true;
        }

        publisher_handle_count_ = 0;

        if (NTBaseCodeDefine.NT_ERC_OK != NTSmartPublisherSDK.NT_PB_Open(out publisher_handle_,
            video_option, audio_option, 0, IntPtr.Zero))
        {
            return false;
        }

        if (publisher_handle_ != IntPtr.Zero)
        {
            pb_event_call_back_ = new NT_PB_SDKEventCallBack(PbEventCallBack);

            NTSmartPublisherSDK.NT_PB_SetEventCallBack(publisher_handle_, IntPtr.Zero, pb_event_call_back_);

            return true;
        }
        else
        {
            return false;
        }
    }
    private void SetCommonOptionToPublisherSDK()
    {
        if (!IsPublisherHandleAvailable())
        {
            Debug.Log("SetCommonOptionToPublisherSDK, publisher handle with null..");
            return;
        }

        CameraInfo camera = cameras_[cur_sel_camera_index_];
        NT_PB_VideoCaptureCapability cap = camera.capabilities_[cur_sel_camera_resolutions_index_];

        SetVideoCaptureDeviceBaseParameter(camera.id_.ToString(), (UInt32)cap.width_, (UInt32)cap.height_);

        SetFrameRate((UInt32)CalBitRate(edit_key_frame_, cap.width_, cap.height_));

        SetVideoEncoderType(is_h264_encoder ? 1 : 2);

        SetVideoQualityV2(CalVideoQuality(cap.width_, cap.height_, is_h264_encoder));

        SetVideoMaxBitRate((CalMaxKBitRate(edit_key_frame_, cap.width_, cap.height_, false)));

        SetVideoKeyFrameInterval((edit_key_frame_));

        if (is_h264_encoder)
        {
            SetVideoEncoderProfile(1);

        }

        SetVideoEncoderSpeed(CalVideoEncoderSpeed(cap.width_, cap.height_, is_h264_encoder));

        // 音频相关设置

        SetAuidoInputDeviceId(0);

        SetPublisherAudioCodecType(1);

        SetPublisherMute(is_mute);

        SetInputAudioVolume(Convert.ToSingle(edit_audio_input_volume_));
    }
AI 代码解读

预览、停止预览:

   public bool StartPreview()
    {
        if(CheckPublisherHandleAvailable() == false)
            return false;

        video_preview_image_callback_ = new NT_PB_SDKVideoPreviewImageCallBack(SDKVideoPreviewImageCallBack);

        NTSmartPublisherSDK.NT_PB_SetVideoPreviewImageCallBack(publisher_handle_, (int)NTSmartPublisherDefine.NT_PB_E_IMAGE_FORMAT.NT_PB_E_IMAGE_FORMAT_RGB32, IntPtr.Zero, video_preview_image_callback_);

        if (NTBaseCodeDefine.NT_ERC_OK != NTSmartPublisherSDK.NT_PB_StartPreview(publisher_handle_, 0, IntPtr.Zero))
        {
            if (0 == publisher_handle_count_)
            {
                NTSmartPublisherSDK.NT_PB_Close(publisher_handle_);
                publisher_handle_ = IntPtr.Zero;
            }

            return false;
        }

        publisher_handle_count_++;

        is_previewing_ = true;

        return true;
    }

    public void StopPreview()
    {
        if (is_previewing_ == false) return;

        is_previewing_ = false;

        publisher_handle_count_--;
        NTSmartPublisherSDK.NT_PB_StopPreview(publisher_handle_);

        if (0 == publisher_handle_count_)
        {
            NTSmartPublisherSDK.NT_PB_Close(publisher_handle_);
            publisher_handle_ = IntPtr.Zero;
        }
    }
AI 代码解读

开始推送、停止推送:

    public bool StartPublisher(String url)
    {
        if (CheckPublisherHandleAvailable() == false) return false;

        if (publisher_handle_ == IntPtr.Zero)
        {
            return false;
        }
        if (!String.IsNullOrEmpty(url))
        {
            NTSmartPublisherSDK.NT_PB_SetURL(publisher_handle_, url, IntPtr.Zero);
        }

        if (NTBaseCodeDefine.NT_ERC_OK != NTSmartPublisherSDK.NT_PB_StartPublisher(publisher_handle_, IntPtr.Zero))
        {
            if (0 == publisher_handle_count_)
            {
                NTSmartPublisherSDK.NT_PB_Close(publisher_handle_);
                publisher_handle_ = IntPtr.Zero;
            }

            is_publishing_ = false;

            return false;
        }

        publisher_handle_count_++;

        is_publishing_ = true;

        return true;
    }

    public void StopPublisher()
    {
        if (is_publishing_ == false) return;

        publisher_handle_count_--;
        NTSmartPublisherSDK.NT_PB_StopPublisher(publisher_handle_);

        if (0 == publisher_handle_count_)
        {
            NTSmartPublisherSDK.NT_PB_Close(publisher_handle_);
            publisher_handle_ = IntPtr.Zero;
        }

        is_publishing_ = false;
    }
AI 代码解读

相关event事件回调:

    private void PbEventCallBack(IntPtr handle, IntPtr user_data, 
        UInt32 event_id,
        Int64 param1,
        Int64 param2,
        UInt64 param3,
        UInt64 param4,
        [MarshalAs(UnmanagedType.LPStr)] String param5,
        [MarshalAs(UnmanagedType.LPStr)] String param6,
        IntPtr param7)
    {
        String event_log = "";

        switch (event_id)
        {
            case (uint)NTSmartPublisherDefine.NT_PB_E_EVENT_ID.NT_PB_E_EVENT_ID_CONNECTING:
                event_log = "连接中";
                if (!String.IsNullOrEmpty(param5))
                {
                    event_log = event_log + " url:" + param5;
                }
                break;

            case (uint)NTSmartPublisherDefine.NT_PB_E_EVENT_ID.NT_PB_E_EVENT_ID_CONNECTION_FAILED:
                event_log = "连接失败";
                if (!String.IsNullOrEmpty(param5))
                {
                    event_log = event_log + " url:" + param5;
                }
                break;

            case (uint)NTSmartPublisherDefine.NT_PB_E_EVENT_ID.NT_PB_E_EVENT_ID_CONNECTED:
                event_log = "已连接";
                if (!String.IsNullOrEmpty(param5))
                {
                    event_log = event_log + " url:" + param5;
                }
                break;

            case (uint)NTSmartPublisherDefine.NT_PB_E_EVENT_ID.NT_PB_E_EVENT_ID_DISCONNECTED:
                event_log = "断开连接";
                if (!String.IsNullOrEmpty(param5))
                {
                    event_log = event_log + " url:" + param5;
                }
                break;

            default:
                break;
        }

        if(OnLogEventMsg != null) OnLogEventMsg.Invoke(event_id, event_log);
    }
AI 代码解读

SmartPublishWinMono.cs 调用上述封装的代码即可,本地预览的话,拿到回调的RGB数据,在unity3d上层刷下即可,如下图:

win_unity_publisher

经测试,unity3d下,RTMP推送,配合RTMP播放端,依然可以实现毫秒级延迟的推拉流体验。

目录
打赏
0
0
0
0
5
分享
相关文章
释放数据潜力:利用 MCP 资源让大模型读懂你的服务器
MCP(Model Control Protocol)资源系统是将服务器数据暴露给客户端的核心机制,支持文本和二进制两种类型资源。资源通过唯一URI标识,客户端可通过资源列表或模板发现资源,并使用`resources/read`接口读取内容。MCP还支持资源实时更新通知及订阅机制,确保动态数据的及时性。实现时需遵循最佳实践,如清晰命名、设置MIME类型和缓存策略,同时注重安全性,包括访问控制、路径清理和速率限制等。提供的示例代码展示了如何用JavaScript和Python实现资源支持。
184 80
在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾
以上就是在Linux环境下备份Docker中的MySQL数据并传输到其他服务器以实现数据级别的容灾的步骤。这个过程就像是一场接力赛,数据从MySQL数据库中接力棒一样传递到备份文件,再从备份文件传递到其他服务器,最后再传递回MySQL数据库。这样,即使在灾难发生时,我们也可以快速恢复数据,保证业务的正常运行。
95 28
网络通讯技术:HTTP POST协议用于发送本地压缩数据到服务器的方案。
总的来说,无论你是一名网络开发者,还是普通的IT工作人员,理解并掌握POST方法的运用是非常有价值的。它就像一艘快速,稳定,安全的大船,始终为我们在网络海洋中的冒险提供了可靠的支持。
69 22
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
博客不应该只有代码和解决方案,重点应该在于给出解决方案的同时分享思维模式,只有思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
Java||Springboot读取本地目录的文件和文件结构,读取服务器文档目录数据供前端渲染的API实现
|
1月前
服务器数据恢复—NTFS分区误格式化数据怎样挽回?
NTFS文件系统下格式化在理论上不会对数据造成太大影响,但有可能造成部分文件目录结构丢失的情况。下面介绍一个人为误操作导致服务器磁盘阵列中的NTFS文件系统分区被格式化后的服务器数据恢复案例。
Unity下如何实现低延迟的全景RTMP|RTSP流渲染
随着虚拟现实技术的发展,全景视频成为新的媒体形式。本文详细介绍了如何在Unity中实现低延迟的全景RTMP或RTSP流渲染,包括环境准备、引入依赖、初始化客户端、解码与渲染、优化低延迟等步骤,并提供了具体的代码示例。适用于远程教育、虚拟旅游等实时交互场景。
174 5
Unity保存数据
在Unity中保存场景数据涉及数据收集、序列化和存储。数据收集包括游戏对象的基本信息(如位置、旋转、缩放、名称和标签)及组件数据(如渲染、物理和自定义脚本组件)。接着,通过序列化将数据转换为可存储格式。示例代码展示了如何使用XML保存场景中的游戏对象及其属性。
服务器感染了.baxia勒索病毒,如何确保数据文件完整恢复?
近年来,勒索病毒如.baxia不断演变,利用漏洞、社交工程等手段加密文件,威胁范围扩大。加密货币的兴起使其支付方式更匿名,追踪困难。技术支持尤为重要,添加技术服务号(shuju315),专业团队提供数据恢复方案。面对复杂解密要求,包括赎金支付、个人信息提供和执行特定操作,需保持冷静并寻求帮助。防御措施包括加强安全意识、定期备份数据、安装杀毒软件、避免未知文件、更新系统及制定应急响应计划。
146 11
PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑
本文深入探讨了PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑;Ajax则通过异步请求实现页面无刷新更新。文中详细介绍了两者的工作原理、数据传输格式选择、具体实现方法及实际应用案例,如实时数据更新、表单验证与提交、动态加载内容等。同时,针对跨域问题、数据安全与性能优化提出了建议。总结指出,PHP与Ajax的结合能显著提升Web应用的效率和用户体验。
125 3
Unity下如何实现低延迟的全景RTMP|RTSP流渲染
随着虚拟现实技术的发展,全景视频逐渐成为新的媒体形式。本文详细介绍了如何在Unity中实现低延迟的全景RTMP或RTSP流渲染,包括环境准备、引入依赖、初始化客户端、解码与渲染、优化低延迟等步骤,并提供了具体的代码示例。适用于远程教育、虚拟旅游等实时交互场景。
148 2

热门文章

最新文章