Windows平台下如何实现Unity3D下的RTMP推送

简介: 好多开发者苦于很难在unity3d下实现RTMP直播推送,本次以大牛直播SDK(Github)的Windows平台RTMP推送模块(以推摄像头为例,如需推屏幕数据,设置相关参数即可)为例,介绍下unity3d的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_));
        }

预览、停止预览:

       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;
            }
        }

开始推送、停止推送:

        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;
        }

相关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);
        }

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

20200610162635520.png

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

相关文章
|
9天前
|
监控 Windows
Windows平台RTSP|RTMP播放器如何实时调节音量
我们在做Windows平台RTSP、RTMP播放器的时候,有这样的技术需求,特别是多路监控的时候,并不是每一路audio都需要播放出来的,所以,这时候,需要有针对音量调节的设计
|
9天前
|
监控 C# 块存储
Windows平台RTSP|RTMP播放器如何叠加OSD文字
做Windows平台RTSP|RTMP播放器的时候,特别是多路播放场景下,开发者希望可以给每一路RTSP或RTMP流添加个额外的OSD台标,以区分不同的设备信息(比如添加摄像头所在位置),本文主要探讨,如何动态添加OSD台标。
Windows平台RTSP|RTMP播放器如何叠加OSD文字
|
9天前
|
Linux Android开发 iOS开发
Windows平台RTSP|RTMP播放器如何实现实时录像功能
Windows平台RTSP、RTMP播放器实时录像接口设计,实际上,除了Windows平台,我们Linux、Android、iOS平台也是一样的设计,单纯的录像模块,如果做的全面,也不是一两个接口可以搞定的
|
1月前
|
图形学 iOS开发 Android开发
从Unity开发到移动平台制胜攻略:全面解析iOS与Android应用发布流程,助你轻松掌握跨平台发布技巧,打造爆款手游不是梦——性能优化、广告集成与内购设置全包含
【8月更文挑战第31天】本书详细介绍了如何在Unity中设置项目以适应移动设备,涵盖性能优化、集成广告及内购功能等关键步骤。通过具体示例和代码片段,指导读者完成iOS和Android应用的打包与发布,确保应用顺利上线并获得成功。无论是性能调整还是平台特定的操作,本书均提供了全面的解决方案。
109 0
|
2月前
|
开发者 图形学 iOS开发
掌握Unity的跨平台部署与发布秘籍,让你的游戏作品在多个平台上大放异彩——从基础设置到高级优化,深入解析一站式游戏开发解决方案的每一个细节,带你领略高效发布流程的魅力所在
【8月更文挑战第31天】跨平台游戏开发是当今游戏产业的热点,尤其在移动设备普及的背景下更为重要。作为领先的游戏开发引擎,Unity以其卓越的跨平台支持能力脱颖而出,能够将游戏轻松部署至iOS、Android、PC、Mac、Web及游戏主机等多个平台。本文通过杂文形式探讨Unity在各平台的部署与发布策略,并提供具体实例,涵盖项目设置、性能优化、打包流程及发布前准备等关键环节,助力开发者充分利用Unity的强大功能,实现多平台游戏开发。
53 0
|
2月前
|
编解码 开发工具 数据安全/隐私保护
如何快速实现Windows平台屏幕摄像头采集并推送RTMP|轻量级RTSP服务能力?
一个好的推送模块,除了实现高效率的编码传输外,还要有好的音视频采集机制和灵活的架构支持,便于后期功能扩展,比如实时快照、预览、实时录像等。除此之外,还要有好的交互机制(比如envent callback)、低延迟和长期运行稳定的性能。
|
1月前
|
网络安全 虚拟化 Windows
windows 11安装openSSH server 遇到的"kex_exchange_identification: read: Connection reset"问题
windows 11安装openSSH server 遇到的"kex_exchange_identification: read: Connection reset"问题
|
2月前
|
PHP Windows
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
【Azure App Service for Windows】 PHP应用出现500 : The page cannot be displayed because an internal server error has occurred. 错误
|
2月前
|
开发框架 .NET API
Windows Server 2022 安装IIS 报错 访问临时文件夹 C:\WINDOWS\TEMP\3C 读取/写入权限 错误: 0x80070005
Windows Server 2022 安装IIS 报错 访问临时文件夹 C:\WINDOWS\TEMP\3C 读取/写入权限 错误: 0x80070005
86 0