Windows平台如何实现RTSP|RTMP流录像?

embedded/2024/10/9 14:19:37/

好多开发者使用场景,除了实现基础的低延迟RTSP、RTMP播放外,还需要实现RTSP、RTMP流数据的本地录像功能。本文以大牛直播SDK的Windows平台播放模块为例,介绍下如何实现RTSP、RTMP流录像

功能设计

  •  [拉流]支持拉取RTSP流录像
  •  [拉流]支持拉取RTMP流录像
  •  [逻辑分离]和播放、转发功能完全分离,支持随时录像;
  •  [参数设置]支持设置单个录像文件大小、录像路径等,并支持纯音频、纯视频、音视频录制模式;
  •  [音频转码]支持音频(PCMU/PCMA,Speex等)转AAC后再录像;
  •  [265支持]支持RTSP/RTMP H.265录制到MP4文件;
  •  [事件回调]从开始录像,到录像结束均有event callback上来。

引入相关头文件和库

C#头文件:

  • [base code定义]nt_base_code_define.cs
  • [player接口]smart_player_define.cs
  • [player参数定义]smart_player_sdk.cs

相关Lib:

  • SmartLog.dll
  • SmartLog.lib
  • SmartPlayerSDK.dll
  • SmartPlayerSDK.lib
  • avcodec-56.dll
  • avdevice-56.dll
  • avfilter-5.dll
  • avformat-56.dll
  • avutil-54.dll
  • postproc-53.dll
  • swresample-1.dll
  • swscale-3.dll

 设置日志存放路径

需要在player_api_.Init之前添加下面的代码:

// 设置日志路径(请确保目录存在)
String log_path = "D:\\playerlog";
NTSmartLog.NT_SL_SetPath(log_path);

如目录存在,并具备文件写入权限,关闭应用程序后,相关文件夹下会有smart_sdk.log生成。

初始化SDK

NT_SP_Init:SDK初始化,多实例播放,此接口仅需调用一次即可。

 创建播放实例

NT_SP_Open:每调用一次Open接口,对应一个播放实例,如需播放多实例,对应多个player handler。

if (player_handle_ == IntPtr.Zero)
{player_handle_ = new IntPtr();UInt32 ret_open = NTSmartPlayerSDK.NT_SP_Open(out player_handle_, IntPtr.Zero, 0, IntPtr.Zero);if (ret_open != 0){player_handle_ = IntPtr.Zero;MessageBox.Show("调用NT_SP_Open失败..");return;}
}

设置回调事件

NT_SP_SetEventCallBack:用于回调网络链接状态、buffer状态(开始、buffer比例、结束)、实时带宽等,对应EventID如下:

/*事件ID*/
public enum NT_SP_E_EVENT_ID : uint
{NT_SP_E_EVENT_ID_BASE = NTBaseCodeDefine.NT_EVENT_ID_SMART_PLAYER_SDK,NT_SP_E_EVENT_ID_CONNECTING          = NT_SP_E_EVENT_ID_BASE | 0x2, /*连接中*/NT_SP_E_EVENT_ID_CONNECTION_FAILED = NT_SP_E_EVENT_ID_BASE | 0x3, /*连接失败*/NT_SP_E_EVENT_ID_CONNECTED       = NT_SP_E_EVENT_ID_BASE | 0x4, /*已连接*/NT_SP_E_EVENT_ID_DISCONNECTED     = NT_SP_E_EVENT_ID_BASE | 0x5, /*断开连接*/NT_SP_E_EVENT_ID_NO_MEDIADATA_RECEIVED = NT_SP_E_EVENT_ID_BASE | 0x8,  /*收不到RTMP数据*/NT_SP_E_EVENT_ID_RTSP_STATUS_CODE   = NT_SP_E_EVENT_ID_BASE | 0xB,  /*rtsp status code上报, 目前只上报401, param1表示status code*//* 接下来请从0x81开始*/NT_SP_E_EVENT_ID_START_BUFFERING = NT_SP_E_EVENT_ID_BASE | 0x81, /*开始缓冲*/NT_SP_E_EVENT_ID_BUFFERING     = NT_SP_E_EVENT_ID_BASE | 0x82, /*缓冲中, param1 表示百分比进度*/NT_SP_E_EVENT_ID_STOP_BUFFERING  = NT_SP_E_EVENT_ID_BASE | 0x83, /*停止缓冲*/NT_SP_E_EVENT_ID_DOWNLOAD_SPEED  = NT_SP_E_EVENT_ID_BASE | 0x91, /*下载速度, param1表示下载速度,单位是(Byte/s)*/NT_SP_E_EVENT_ID_PLAYBACK_REACH_EOS = NT_SP_E_EVENT_ID_BASE | 0xa1,     /*播放结束, 直播流没有这个事件,点播流才有*/NT_SP_E_EVENT_ID_RECORDER_REACH_EOS = NT_SP_E_EVENT_ID_BASE | 0xa2,     /*录像结束, 直播流没有这个事件, 点播流才有*/NT_SP_E_EVENT_ID_PULLSTREAM_REACH_EOS = NT_SP_E_EVENT_ID_BASE | 0xa3,   /*拉流结束, 直播流没有这个事件,点播流才有*/NT_SP_E_EVENT_ID_DURATION = NT_SP_E_EVENT_ID_BASE | 0xa8, /*视频时长,如果是直播,则不上报,如果是点播的话, 若能从视频源获取视频时长的话,则上报, param1表示视频时长,单位是毫秒(ms)*/
}

设置拉流的URL

NT_SP_SetURL:支持rtsp/rtmp/本地FLV文件(全路径)。

设置录像规则

  1. NT_SP_SetRecorderDirectory:设置录像目录
  2. NT_SP_SetRecorderFileMaxSize:设置单个文件最大大小
  3. NT_SP_SetRecorderFileNameRuler:设置录像文件名生成规则
  4. NT_SP_SetRecorderCallBack:设置录像回调接口
  5. NT_SP_SetRecorderAudioTranscodeAAC:设置录像时音频转AAC编码的开关, aac比较通用,sdk增加其他音频编码(比如speex, pcmu, pcma等)转aac的功能
  6. NT_SP_SetRecorderVideo:设置是否录视频,默认的话,如果视频源有视频就录,没有就没得录, 但有些场景下可能不想录制视频,只想录音频,所以增加个开关
  7. NT_SP_SetRecorderAudio:设置是否录音频,默认的话,如果视频源有音频就录,没有就没得录, 但有些场景下可能不想录制音频,只想录视频,所以增加个开关

实现录像逻辑

  1. NT_SP_StartRecorder:启动录像
  2. NT_SP_StopRecorder:停止录像

代码调用示例:

/** SmartPlayerForm.cs* Author: daniusdk.com* WeChat: xinsheng120*/
private void btn_record_Click(object sender, EventArgs e)
{if (player_handle_ == IntPtr.Zero)return;if (btn_record.Text == "录像"){if (!is_rec_video_ && !is_rec_audio_){MessageBox.Show("音频录制选项和视频录制选项至少需要选择一个!");return;}if (!is_playing_){if (!InitCommonSDKParam()){MessageBox.Show("设置参数错误!");return;}}NTSmartPlayerSDK.NT_SP_SetRecorderVideo(player_handle_, is_rec_video_ ? 1 : 0);NTSmartPlayerSDK.NT_SP_SetRecorderAudio(player_handle_, is_rec_audio_ ? 1 : 0);UInt32 ret = NTSmartPlayerSDK.NT_SP_SetRecorderDirectoryW(player_handle_, rec_dir_);if (NT.NTBaseCodeDefine.NT_ERC_OK != ret){MessageBox.Show("设置录像目录失败");return;}NTSmartPlayerSDK.NT_SP_SetRecorderFileMaxSize(player_handle_, max_file_size_);NT_SP_RecorderFileNameRuler rec_name_ruler = new NT_SP_RecorderFileNameRuler();rec_name_ruler.type_ = 0;rec_name_ruler.file_name_prefix_ = rec_name_file_prefix_;rec_name_ruler.append_date_ = is_append_date_ ? 1 : 0;rec_name_ruler.append_time_ = is_append_time_ ? 1 : 0;NTSmartPlayerSDK.NT_SP_SetRecorderFileNameRuler(player_handle_, ref rec_name_ruler);record_call_back_ = new SP_SDKRecorderCallBack(SDKRecorderCallBack);NTSmartPlayerSDK.NT_SP_SetRecorderCallBack(player_handle_, IntPtr.Zero, record_call_back_);NTSmartPlayerSDK.NT_SP_SetRecorderAudioTranscodeAAC(player_handle_, is_audio_transcode_aac_ ? 1 : 0);if (NT.NTBaseCodeDefine.NT_ERC_OK != NTSmartPlayerSDK.NT_SP_StartRecorder(player_handle_)){MessageBox.Show("录像失败!");return;}btn_record.Text = "停止录像";is_recording_ = true;}else{StopRecorder();}
}

录像事件回调

/** 录像回调* status: 1:表示开始写一个新录像文件. 2:表示已经写好一个录像文件* file_name: 实际录像文件名*/
[UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]public delegate void SP_SDKRecorderCallBack(IntPtr handle, IntPtr user_data, UInt32 status, [MarshalAs(UnmanagedType.LPStr)] String file_name);

调用示例:

private void RecordCallBack(UInt32 status, [MarshalAs(UnmanagedType.LPStr)] String file_name)
{byte[] utf8_bytes = Encoding.Default.GetBytes(file_name);byte[] default_bytes = Encoding.Convert(Encoding.UTF8, Encoding.Default, utf8_bytes);String recorder_file_name = Encoding.Default.GetString(default_bytes);StringBuilder sb = new StringBuilder();sb.Append("录像状态:");if (status == 1){sb.Append("new file: ");}else if(status == 2){sb.Append("finished file: ");}sb.Append(recorder_file_name);MessageBox.Show(sb.ToString());
}

销毁播放实例

NT_SP_Close

调用Close接口后,player handler置空。

if ( player_handle_ != IntPtr.Zero)
{NTSmartPlayerSDK.NT_SP_Close(player_handle_);player_handle_ = IntPtr.Zero;
}

释放资源

NT_SP_UnInit

UnInit() 是SDK最后一个调用的接口,多实例环境下,只需要调用一次即可。


http://www.ppmy.cn/embedded/120616.html

相关文章

(最新已验证)stm32 + 新版 onenet +dht11+esp8266/01s + mqtt物联网(含微信小程序)上报温湿度和控制单片机(保姆级教程)

物联网实践教程:微信小程序结合OneNET平台MQTT实现STM32单片机远程智能控制 远程上报和接收数据——汇总 前言 之前在学校获得了一个新玩意:ESP-01sWIFI模块,去搜了一下这个小东西很有玩点,远程控制LED啥的,然后我就想…

Django 解决跨域

一、配置 安装依赖 pip3 install django-cors-headers 修改配置 ALLOW_HOSTS [*] INSTALLD_APPS [ corsheaders ] MIDDLEWARE [ django.middleware.security.SecurityMiddleware, django.contrib.sessions.middleware.SessionMiddleware, corsheaders.middleware.CorsMiddl…

基于 STM32F407 的串口 IAP

目录 一、概述二、IAP 实现三、IAP 程序1、串口部分2、iap 程序3、内部 flash 读写4、main 程序 IAP(In Application Programming,在应用编程)是用户自己的程序在运行过程中对 User Flash 的部分区域进行烧写。简单来说,就是开发者…

华为NAT ALG技术的实现

双向NAT技术:经过防火墙的2报文源IP地址和目的IP地址都同时被转换,外网发送报文给内网服务器,先转换目的IP地址,然后符合安全策略后,在替换源IP地址,然后将记录写入防火墙会话表,并发送出报文&a…

计算机网络——TCP/IP网络模型

1. TCP/IP网络模型有哪几层 对于同一台设备上的进程间通信,有很多种方式,比如管道、消息队列、共享内存、信号等。而对于不同设备上的进程间通信,就需要网络通信,而设备是多样性的,所以要兼容多种多样的设备&#xff…

【Redis】如何在 Ubuntu 上安装 Redis 5

🥰🥰🥰来都来了,不妨点个关注叭! 👉博客主页:欢迎各位大佬!👈 本期内容主要介绍如何在 Ubuntu 上安装 Redis5 一些碎碎念: 本来这期内容介绍如何在 Centos 安装 Redis …

【人人保-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击,存在如下安全问题: 1. 暴力破解密码,造成用户信息泄露 2. 短信盗刷的安全问题,影响业务及导致用户投诉 3. 带来经济损失,尤其是后付费客户,风险巨大,造…