前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Windows平台RTMP推送|轻量级RTSP服务录像模块如何支持中文路径?

Windows平台RTMP推送|轻量级RTSP服务录像模块如何支持中文路径?

原创
作者头像
音视频牛哥
发布2024-01-14 10:40:39
1580
发布2024-01-14 10:40:39
举报

技术背景

我们在做Windows平台RTMP推送、轻量级RTSP服务录像模块的时候,部分开发者抱怨路径无法设置中文,只能设置为英文。

以C#的接口为例,早期的设计如下:

代码语言:csharp
复制
   /*
    * 设置本地录像目录, 必须是英文目录,否则会失败
    */
    [DllImport(@"SmartPublisherSDK.dll")]
    public static extern UInt32 NT_PB_SetRecorderDirectory(IntPtr handle, [MarshalAs(UnmanagedType.LPStr)] String dir, IntPtr pReserve);

考虑到一些场景的特殊性,可能需要中文路径,我们设计的接口如下:

代码语言:csharp
复制
        /*
         * 设置本地录像目录, 支持中文目录, 需要设置宽字符,比如L"D:\\xxx\\gg"
         */
        [DllImport(@"SmartPublisherSDK.dll")]
        public static extern UInt32 NT_PB_SetRecorderDirectoryW(IntPtr handle, [MarshalAs(UnmanagedType.LPWStr)]String dir, IntPtr pReserve);

调用如下,以调用开始录像、暂停录像、停止录像为例,调用逻辑如下,可以看到除了中文路径诉求,录像模块还可以添加前缀、添加文字、水印:

代码语言:csharp
复制
       public bool StartRecorder()
        {
            if (is_empty_handle() || is_recording())
                return false;

            //string edit_rec_dir = "D:\\dntest";
            string edit_rec_dir = "D:\\推送端录像";

            if (String.IsNullOrEmpty(edit_rec_dir))
            {
                Console.WriteLine("请设置录像目录");
                return false;
            }

            uint ret = NTSmartPublisherSDK.NT_PB_SetRecorderDirectoryW(handle_, edit_rec_dir, IntPtr.Zero);

            if (NTBaseCodeDefine.NT_ERC_OK != ret)
            {
                try_close_handle();
                return false;
            }

            uint rec_max_file_size = 512 * 1024;
            NTSmartPublisherSDK.NT_PB_SetRecorderFileMaxSize(handle_, rec_max_file_size);

            NT_PB_RecorderFileNameRuler rec_name_ruler = new NT_PB_RecorderFileNameRuler();

            String rec_file_name_prefix_ = "transcode-rec";
            rec_name_ruler.file_name_prefix_ = rec_file_name_prefix_.ToString();
            rec_name_ruler.append_date_ = 1;
            rec_name_ruler.append_time_ = 1;

            NTSmartPublisherSDK.NT_PB_SetRecorderFileNameRuler(handle_, ref rec_name_ruler);

            if (NTBaseCodeDefine.NT_ERC_OK != NTSmartPublisherSDK.NT_PB_StartRecorder(handle_, IntPtr.Zero))
            {
                try_close_handle();
                return false;
            }

            shared_lock_.EnterWriteLock();
            try
            {
                handle_reference_count_++;
                is_recording_ = true;
            }
            finally
            {
                shared_lock_.ExitWriteLock();
            }

            return true;
        }

        public UInt32 PauseRecorder(bool is_pause)
        {
            if (is_empty_handle() || !is_recording())
                return NTBaseCodeDefine.NT_ERC_FAILED;

            UInt32 ret = NTBaseCodeDefine.NT_ERC_OK;

            if (is_pause)
            {
                ret = NTSmartPublisherSDK.NT_PB_PauseRecorder(handle_, 1);
                if ((UInt32)NT.NTSmartPublisherDefine.NT_PB_E_ERROR_CODE.NT_ERC_PB_NEED_RETRY == ret)
                {
                    Console.WriteLine("暂停录像失败, 请重新尝试!");
                    return ret;
                }
                else if (NTBaseCodeDefine.NT_ERC_OK == ret)
                {
                    //btn_pause_rec.Text = "恢复录像";
                }
            }
            else
            {
                ret = NTSmartPublisherSDK.NT_PB_PauseRecorder(handle_, 0);
                if ((UInt32)NT.NTSmartPublisherDefine.NT_PB_E_ERROR_CODE.NT_ERC_PB_NEED_RETRY == ret)
                {
                    Console.WriteLine("恢复录像失败, 请重新尝试!");
                    return ret;
                }
                else if (NTBaseCodeDefine.NT_ERC_OK == ret)
                {
                    //btn_pause_rec.Text = "暂停录像";
                }
            }

            return ret;
        }

        public void StopRecorder()
        {
            if (is_empty_handle() || !is_recording())
                return;

            shared_lock_.EnterWriteLock();
            try
            {
                is_recording_ = false;
                handle_reference_count_--;
            }
            finally
            {
                shared_lock_.ExitWriteLock();
            }

            NTSmartPublisherSDK.NT_PB_StopRecorder(handle_);
            try_close_handle();
        }

开始录像和录像完成后,提示如下:

代码语言:csharp
复制
        private void PbEventCallBack(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_RECORDER_START_NEW_FILE:
                    event_log = " start new recorder file";

                    byte[] utf8_bytes = Encoding.Default.GetBytes(param5);
                    byte[] default_bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, utf8_bytes);
                    String file_name = Encoding.Default.GetString(default_bytes);

                    if (!String.IsNullOrEmpty(file_name))
                    {
                        event_log = event_log + " file name:" + file_name;
                    }
                    break;

                case (uint)NTSmartPublisherDefine.NT_PB_E_EVENT_ID.NT_PB_E_EVENT_ID_ONE_RECORDER_FILE_FINISHED:
                    event_log = " finish recorder file";
                    byte[] finished_utf8_bytes = Encoding.Default.GetBytes(param5);
                    byte[] finished_default_bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, finished_utf8_bytes);
                    String finished_file_name = Encoding.Default.GetString(finished_default_bytes);

                    if (!String.IsNullOrEmpty(finished_file_name))
                    {
                        event_log = event_log + " file name:" + finished_file_name;
                    }
                    break;

                .......

                default:
                    break;
            }

            EventGetPublisherEventMsg(event_log);
        }

总结

Windows平台RTMP推送、轻量级RTSP服务配套的录像模块,除了设置录像保存路径外、还可以设置录像文件前缀、是不是添加日期、时间等,还有就是单个录像文件大小,超过这个大小后,会自动切换到下个文件。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 总结
相关产品与服务
实时音视频
实时音视频(Tencent RTC)基于腾讯21年来在网络与音视频技术上的深度积累,以多人音视频通话和低延时互动直播两大场景化方案,通过腾讯云服务向开发者开放,致力于帮助开发者快速搭建低成本、低延时、高品质的音视频互动解决方案。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档