技术背景

上篇文章,我们介绍了Unity平台RTMP、RTSP播放器录像功能,这里,我们详细的介绍下,做个RTSP或RTMP拉流端录像模块有哪些需要考虑的技术点?

在我们常规的考量,RTMP或RTSP流录制,无非就是拉取数据写文件而已,接口设计StartRecorder()/StopRecorder()足矣。

是的,一般场景下,两个接口足够了,但如果是做个更加通用的模块,以下几点是可以酌情考虑的:

  • 支持设置单个录像文件大小,比如单个录像文件最大设置到200M,到了200M,可自动切分到下个录像文件;
  • 支持设置录像路径;
  • 支持设置录像文件前缀:录像文件前缀,是为了更友好的做特定文件的分类;
  • 支持文件名增加日期;
  • 支持文件名增加时间;
  • 支持设置纯音频、纯视频、音视频录制模式;
  • 支持音频(PCMU/PCMA,Speex等)转AAC后再录像;
  • 支持录像事件回调,从开始录像,到录像结束均有event callback上来。

除了上述的设计,还需要确保和RTSP、RTMP播放在一个实例下,确保播放的过程中可以随时录像,录像的过程中,可以随时播放。

录像模块设计

无图无真相,先看录像设置:

开始录像、停止录像:

Windows平台,我们提供了C++和C#的接口,本文以C++接口设计为例:

先说录像设置:

设置录制纯音频或纯视频:

       /** 设置是否录视频,默认的话,如果视频源有视频就录,没有就没得录, 但有些场景下可能不想录制视频,只想录音频,所以增加个开关* is_record_video: 1 表示录制视频, 0 表示不录制视频, 默认是1*/NT_UINT32(NT_API *SetRecorderVideo)(NT_HANDLE handle, NT_INT32 is_record_video);/** 设置是否录音频,默认的话,如果视频源有音频就录,没有就没得录, 但有些场景下可能不想录制音频,只想录视频,所以增加个开关* is_record_audio: 1 表示录制音频, 0 表示不录制音频, 默认是1*/NT_UINT32(NT_API *SetRecorderAudio)(NT_HANDLE handle, NT_INT32 is_record_audio);

设置录像目录:

     /*设置本地录像目录, 必须是英文目录,否则会失败*/NT_UINT32(NT_API *SetRecorderDirectory)(NT_HANDLE handle, NT_PCSTR dir);

设置单个录像文件最大大小:

     /*设置单个录像文件最大大小, 当超过这个值的时候,将切割成第二个文件size: 单位是KB(1024Byte), 当前范围是 [5MB-800MB], 超出将被设置到范围内*/NT_UINT32(NT_API *SetRecorderFileMaxSize)(NT_HANDLE handle, NT_UINT32 size);

设置录像文件名生成规则:

     /*设置录像文件名生成规则*/NT_UINT32(NT_API *SetRecorderFileNameRuler)(NT_HANDLE handle, NT_SP_RecorderFileNameRuler* ruler);

对应的NT_SP_RecorderFileNameRuler设计:

// 如果三项都是0的话,将不能启动录像
typedef struct _NT_SP_RecorderFileNameRuler
{NT_UINT32  type_; // 这个值目前默认是0,将来扩展用NT_PCSTR    file_name_prefix_; // 设置一个录像文件名前缀, 例如:daniuliveNT_INT32 append_date_; // 如果是1的话,将在文件名上加日期, 例如:daniulive-2017-01-17NT_INT32   append_time_; //  如果是1的话,将增加时间,例如:daniulive-2017-01-17-17-10-36
} NT_SP_RecorderFileNameRuler;

设置录像回调接口:

     /*设置录像回调接口*/NT_UINT32(NT_API *SetRecorderCallBack)(NT_HANDLE handle,NT_PVOID call_back_data, SP_SDKRecorderCallBack call_back);

对应录像回调:

/*
录像回调
status: 1:表示开始写一个新录像文件. 2:表示已经写好一个录像文件
file_name: 实际录像文件名
*/
typedef NT_VOID(NT_CALLBACK* SP_SDKRecorderCallBack)(NT_HANDLE handle, NT_PVOID user_data, NT_UINT32 status,NT_PCSTR file_name);

设置音频转AAC开关:

     /*设置录像时音频转AAC编码的开关, aac比较通用,sdk增加其他音频编码(比如speex, pcmu, pcma等)转aac的功能.is_transcode: 设置为1的话,如果音频编码不是aac,则转成aac, 如果是aac,则不做转换. 设置为0的话,则不做任何转换. 默认是0.注意: 转码会增加性能消耗*/NT_UINT32(NT_API *SetRecorderAudioTranscodeAAC)(NT_HANDLE handle, NT_INT32 is_transcode);

启动录像、停止录像:

     /*启动录像*/NT_UINT32(NT_API *StartRecorder)(NT_HANDLE handle);/*停止录像*/NT_UINT32(NT_API *StopRecorder)(NT_HANDLE handle);

接口调用实例

/** Author: https://daniusdk.com*/
void CSmartPlayerDlg::OnBnClickedButtonRecord()
{if ( player_handle_ == NULL )return;CString btn_record_str;btn_record_.GetWindowTextW(btn_record_str);if ( btn_record_str == _T("录像") ){if ( !rec_conf_info_.is_record_video_ && !rec_conf_info_.is_record_audio_ ){AfxMessageBox(_T("音频录制选项和视频录制选项至少需要选择一个!"));return;}if ( !is_playing_ ){if ( !InitCommonSDKParam() ){AfxMessageBox(_T("设置参数错误!"));return;}}player_api_.SetRecorderVideo(player_handle_, rec_conf_info_.is_record_video_ ? 1 : 0);player_api_.SetRecorderAudio(player_handle_, rec_conf_info_.is_record_audio_ ? 1 : 0);auto ret = player_api_.SetRecorderDirectory(player_handle_, rec_conf_info_.dir_.c_str());if ( NT_ERC_OK != ret ){AfxMessageBox(_T("设置录像目录失败,请确保目录存在且是英文目录"));return;}player_api_.SetRecorderFileMaxSize(player_handle_, rec_conf_info_.file_max_size_);NT_SP_RecorderFileNameRuler rec_name_ruler = { 0 };rec_name_ruler.type_ = 0;rec_name_ruler.file_name_prefix_ = rec_conf_info_.file_name_prefix_.c_str();rec_name_ruler.append_date_       = rec_conf_info_.is_append_date_ ? 1 : 0;rec_name_ruler.append_time_       = rec_conf_info_.is_append_time_ ? 1 : 0;player_api_.SetRecorderFileNameRuler(player_handle_, &rec_name_ruler);player_api_.SetRecorderCallBack(player_handle_, GetSafeHwnd(), &SP_SDKRecorderHandle);player_api_.SetRecorderAudioTranscodeAAC(player_handle_, rec_conf_info_.is_audio_transcode_aac_ ? 1 : 0);if ( NT_ERC_OK != player_api_.StartRecorder(player_handle_) ){AfxMessageBox(_T("录像失败!"));return;}btn_record_.SetWindowTextW(_T("停止录像"));is_recording_ = true;}else{StopRecorder();}
}

停止录像:

void CSmartPlayerDlg::StopRecorder()
{if (player_handle_ == NULL)return;player_api_.StopRecorder(player_handle_);btn_record_.SetWindowTextW(_T("录像"));is_recording_ = false;if (!is_playing_){SetWindowText(base_title_);edit_duration_.SetWindowText(_T(""));btn_pause_.SetWindowText(_T("暂停"));}RefreshLogo(true);
}

总结

一个小小的录像功能,如果做的更加通用兼容性好的话,需要注意的点还很多,本文抛砖引玉,感兴趣的开发者可酌情参考。

Windows平台RTMP、RTSP播放器录像模块精细化控制相关推荐

  1. Windows平台RTMP|RTSP播放器实现画面全屏功能

    我们在Windows平台实现RTSP或者RTMP播放的时候,有个功能是绕不开的,那就是播放窗口全屏.本文就以大牛直播SDK(官方)的Windows播放器为例,大概讲下大概实现: 全屏播放需要考虑的点不 ...

  2. Windows平台RTMP|RTSP播放器为什么要兼容GDI绘制

    为什么要支持GDI 先说结论,Windows平台播放渲染这块,一般来说99%以上的机器都是支持D3D的,实现GDI模式绘制,除了为了好的兼容性外,在远程连接的场景下,D3D创建不成功,需要使用GDI模 ...

  3. Windows平台RTMP/RTSP播放器如何实现实时音量调节

    为什么要做实时音量调节 RTMP或RTSP直播播放音量调节,主要用于多实例(多窗口)播放场景下,比如同时播放4路RTMP或RTSP流,如果音频全部打开,几路audio同时打开,可能会影响用户体验,我们 ...

  4. Windows平台RTMP/RTSP直播推送模块设计和使用说明

    开发背景 好多开发者一直反馈,Windows平台,做个推屏或者推摄像头,推RTMP或者RTSP出去,不知道哪些功能是必须的,哪些设计是可有可无的,还有就是,不知道如何选技术方案,以下是基于我们设计的W ...

  5. Android平台RTMP/RTSP播放器开发系列之解码和绘制

    本文主要抛砖引玉,粗略介绍下Android平台RTMP/RTSP播放器中解码和绘制相关的部分(Github). 解码 提到解码,大家都知道软硬解,甚至一些公司觉得硬解码已经足够通用,慢慢抛弃软解了,如 ...

  6. Android、iOS平台RTMP/RTSP播放器实现实时音量调节

    介绍移动端RTMP.RTSP播放器实时音量调节之前,我们之前也写过,为什么windows播放端加这样的接口,windows端播放器在多窗口大屏显示的场景下尤其需要,尽管我们老早就有了实时静音接口,相对 ...

  7. android 直播流服务器,视频-Android上的实时流RTMP / RTSP播放器,无需使用webview(WOWZA服务器)...

    视频-Android上的实时流RTMP / RTSP播放器,无需使用webview(WOWZA服务器) 我正在开发一个Android应用程序,我想在其中发布和播放视频... 我想要的是: 我的应用记录 ...

  8. RTMP/RTSP推送端和RTMP/RTSP播放端录像设计探讨

    好多开发者认为,无论是RTSP/RTMP推送端还是RTSP/RTMP播放端,涉及到录像,只要2个接口足矣:开始录像.停止录像. 实际场景下,一个好的录像模块,2个接口远远不够, 本文以大牛直播SDK( ...

  9. windows平台VR全景播放器,支持图片视频,rtsp,rtmp,http,udp,hls等网络格式

    QQ: 515311445 先上下载链接:点击下载VR全景播放器 本工具使用开源的vlc做为核心播放器,添加全景代码而成,编译vlc时建议使用linux电脑编译,目前vlc已经支持全景图片和视频了,但 ...

最新文章

  1. 杀死多余的ghost 的Android emulator-5554 offline 的方法总结
  2. python中if错误-python中的异常处理
  3. GDI+ 学习记录(10): 线性渐变画刷 - LinearGradientBrush
  4. 在MOSS2007中使用网页获取部件
  5. 【操作系统/OS笔记15】死锁的系统模型,死锁的处理办法,银行家算法与死锁检验算法
  6. EMNLPICLR 多模态学习前沿分享
  7. 程序阅读:简单C++学生信息管理系统
  8. QDir类及其用法总结
  9. HTTP 417 错误 – 预期结果失败 (Expectation failed)
  10. 3D游戏编程与设计作业五
  11. QR码生成原理(一)
  12. spring cloud 总结(摘抄版)
  13. 软件加入使用时间_【安卓】换了这么多影视软件,还是这个老牌站点最靠谱
  14. 2022新版PMP考试有哪些变化?
  15. YOLOE,2022年新版YOLO解读
  16. 如何选择CDN?你需要关注这三个方面
  17. 吉首大学2019年程序设计竞赛(重现赛) B 干物妹小埋
  18. [work] pytorch切片
  19. 生命诚可贵,独立价最高——Let's follow our heart!
  20. 视频教程-C#Winform控件应用-C#

热门文章

  1. “战术竞技类”外挂打击已开始!揭秘腾讯We Test游戏安全服务新动作!
  2. (休息几天)读曼昆之微观经济学——外部性
  3. C程序查找段错误的方法
  4. linux dig命令的安装和使用详解
  5. 文本文件和二进制文件详解(转)
  6. 转 Oracle监听器启动出错:本地计算机上的OracleOraDb11g_home1TNSListener服务启动后又停止了解决方案
  7. 10项IT技能保证你年薪轻松10万美元以上
  8. 2.4、PHP数组与数组结构
  9. 基础编程题目集 函数题部分
  10. 有没有人可以帮我解析一下下面的json