ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

IE浏览器下实现低延迟播放RTSP或RTMP流

2021-02-22 13:59:29  阅读:218  来源: 互联网

标签:SP obj ULONG IE RTSP RTMP var NT ID


首先,虽然本文是介绍IE浏览器下OCX控件播放RTSP或RTMP,但这种方式并不推荐,毕竟它只能用于IE浏览器环境下,局限太大,而且随着微软IE浏览器的更新,不确定后续支持情况。当然,话说回来,如果是在特定的使用场景下,只需要某些版本IE浏览器支持,但对延迟和稳定性要求非常高,OCX控件方式也不失为一个好的选择。

如果需要浏览器场景下有更好的兼容性,对于RTSP流来说,好多公司通常的做法是把RTSP转RTMP,然后分发到RTMP服务器,然后服务器转http-flv出来,浏览器直接播放http-flv流,或者直接播放hls流(如果可以忍受几秒甚至十几秒延迟的话)。

本文基于大牛直播SDK https://github.com/daniulive/SmarterStreaming 现有RTSP、RTMP播放接口的基础上,二次封装,扩展了ocx控件,用于IE浏览器下的低延迟RTMP或RTSP播放,支持RTMP/RTSP H.265(hevc)播放。

页面展示

图一:

图二:

设计注意事项:

1. 接口透传,不再赘述,注意数据类型即可;

2. Event回调传递,特别是多窗口多实例播放模式下,需要区分处理不同实例回调上来的event(如分辨率、实时码率、网络状态等);

3. OCX控件正常注册、反注册(运行网页播放端之前,请确保以管理员权限注册ocx控件:regplayerocx.bat右键-->“以管理员身份运行(A)”,同理,反注册也是需要管理员身份);

4. 浏览器模式下,如滚动条拖动,避免因此带来的闪烁;

5. 等比例绘制,这块最好做到底层SDK里面去,要么,比较笨的办法是,底层回调上来视频宽高信息,上层根据比例二次处理;

6. 窗口显示模式和全屏模式切换等。

对应封装接口

	ULONG NT_Open();
	ULONG NT_Close();
	ULONG NT_StartPlay();
	ULONG NT_StopPlay();
	ULONG NT_SetMute(LONG is_mute);
	ULONG NT_SetURL(LPCTSTR url);
	ULONG NT_SetBuffer(LONG buffer);
	ULONG NT_SetRTSPTcpMode(LONG isUsingTCP);
	ULONG NT_SetRtspTimeout(LONG timeout);
	ULONG NT_SetRtspAutoSwitchTcpUdp(LONG is_auto_switch_tcp_udp);
	ULONG NT_SetFastStartup(LONG isFastStartup);
	ULONG NT_SetVideoHardwareDecoder(LONG isVideoHardwareDecoder);
	ULONG NT_SetLowLatencyMode(LONG mode);
	ULONG NT_SetFlipVertical(LONG is_flip);
	ULONG NT_SetFlipHorizontal(LONG is_flip);
	ULONG NT_SetRotation(LONG degress);
	ULONG NT_SwitchURL(LPCTSTR url);
	ULONG NT_SetCaptureImagePath(LPCTSTR path);
	ULONG NT_CaptureImage();
	ULONG NT_SetRecorderDirectory(LPCTSTR dir);
	ULONG NT_SetRecorderFileMaxSize(ULONG size);
	ULONG NT_NT_SP_RecorderFileNameRuler(ULONG type, LPCTSTR file_name_prefix, LONG append_date, LONG append_time);
	ULONG NT_SetRecorderAudioTranscodeAAC(LONG is_transcode);
	ULONG NT_SetRecorderVideo(LONG is_record_video);
	ULONG NT_SetRecorderAudio(LONG is_record_audio);
	ULONG NT_StartRecorder();
	ULONG NT_StopRecorder();
	ULONG NT_FullScreen();
	void OnSDKEventReceived(BSTR object_id, ULONG event_id, ULONG param1);
	void OnVideoSizeReceived(ULONG width, ULONG height);
	ULONG NT_SetLogPath(LPCTSTR log_path);
	ULONG NT_SetObjectID(LPCTSTR obj_id_str);
	ULONG NT_SetSDKClientKey(LPCTSTR cid, LPCTSTR key);
	ULONG NT_SetAudioVolume(LONG audio_volume);
	ULONG NT_SetRenderScaleMode(LONG mode);

设置LOG存放路径:

ULONG CSmartPlayerActiveXCtrl::NT_SetLogPath(LPCTSTR log_path)

请于NT_Open() 之前调用,代码示例:

var obj = document.getElementById("SmartPlayerActiveX");
				
//如需记录log文件,请确保log路径存在, 如多级目录, 可按照"D:\\Daniulive\\log"类似格式设定, 记录文件名: smart_sdk.log

obj.NT_SetLogPath("D:\\");

接口说明:

   1.  ULONG NT_Open();

打开player实例;
    2. ULONG NT_Close();

关闭player实例;
    3. ULONG NT_StartPlay();

开始播放;
    4. ULONG NT_StopPlay();

停止播放;
    5. ULONG NT_SetMute(LONG is_mute);

设置实时静音;
    6. ULONG NT_SetURL(LPCTSTR url);

设置播放的RTMP或RTSP url;
    7. ULONG NT_SetBuffer(LONG buffer);

设置buffer time,缓冲时间,单位:毫秒;
    8. ULONG NT_SetRTSPTcpMode(LONG isUsingTCP);

设置RTSP TCP/UDP播放模式;
    9. ULONG NT_SetRtspTimeout(LONG timeout);

设置RTSP超时时间;
    10. ULONG NT_SetRtspAutoSwitchTcpUdp(LONG is_auto_switch_tcp_udp);

设置是否自动切换TCP/UDP模式;
    11. ULONG NT_SetFastStartup(LONG isFastStartup);

设置是否快速启动;
    12. ULONG NT_SetLowLatencyMode(LONG mode);

设置是否低延迟模式播放;
    13. ULONG NT_SetFlipVertical(LONG is_flip);

设置垂直反转模式图像;
    14. ULONG NT_SetFlipHorizontal(LONG is_flip);

设置水平反转图像;
    15. ULONG NT_SetRotation(LONG degress);

设置旋转图像,可设定角度:0度 90度 180度 270度;
    16. ULONG NT_SwitchURL(LPCTSTR url);

设置快速切换RTSP/RTMP url;
    17. ULONG NT_SetCaptureImagePath(LPCTSTR path);

设置快照保存位置;
    18. ULONG NT_CaptureImage();

设置实时快照功能;
    19. ULONG NT_SetRecorderDirectory(LPCTSTR dir);

设置录像保存位置;
    20. ULONG NT_SetRecorderFileMaxSize(ULONG size);

设置单个录像文件最大size,单位:兆;
    21. ULONG NT_NT_SP_RecorderFileNameRuler(ULONG type, LPCTSTR file_name_prefix, LONG append_date, LONG append_time);

设置录像文件命名规则:是否需要前缀、是否添加日期、是否添加时间;
    22. ULONG NT_SetRecorderAudioTranscodeAAC(LONG is_transcode);

设置录像音频文件是否转AAC后录制,支持PCMA/PCMU/SPEEX转AAC后录制文件;
    23. ULONG NT_SetRecorderVideo(LONG is_record_video);

设置是否录制视频;
    24. ULONG NT_SetRecorderAudio(LONG is_record_audio);

设置是否录制音频;
    25. ULONG NT_StartRecorder();

开始录像;
    26. ULONG NT_StopRecorder();

停止录像;
    27. ULONG NT_FullScreen();

全屏显示窗口。

    28. ULONG NT_SetObjectID();

设置Object ID,用于区分不同实例。

    29. ULONG NT_SetSDKClientKey();

设置license key,用于授权。

    30. ULONG NT_SetAudioVolume();

 播放端实时音量调节。

    31. ULONG NT_SetRenderScaleMode();

 设置是否等比例显示窗体。

事件Event:    

1. void OnSDKEventReceived;

回调网络状态、buffering状态、下载速度等;

事件类型:

		<script>
			var NT_EVENT_ID_SMART_PLAYER_SDK = 0x01000000;
			var NT_SP_E_EVENT_ID_BASE = NT_EVENT_ID_SMART_PLAYER_SDK;
			var NT_SP_E_EVENT_ID_CONNECTING				= NT_SP_E_EVENT_ID_BASE | 0x2;	/*连接中*/
			var NT_SP_E_EVENT_ID_CONNECTION_FAILED		= NT_SP_E_EVENT_ID_BASE | 0x3;	/*连接失败*/
			var NT_SP_E_EVENT_ID_CONNECTED				= NT_SP_E_EVENT_ID_BASE | 0x4;	/*已连接*/
			var NT_SP_E_EVENT_ID_DISCONNECTED			= NT_SP_E_EVENT_ID_BASE | 0x5;	/*断开连接*/
			var NT_SP_E_EVENT_ID_NO_MEDIADATA_RECEIVED	= NT_SP_E_EVENT_ID_BASE | 0x8;	/*收不到RTMP数据*/
			var NT_SP_E_EVENT_ID_RTSP_STATUS_CODE       = NT_SP_E_EVENT_ID_BASE | 0xB;  /*rtsp status code上报, 目前只上报401, param1表示status code*/

			/* 接下来请从0x81开始*/
			var NT_SP_E_EVENT_ID_START_BUFFERING = NT_SP_E_EVENT_ID_BASE | 0x81; /*开始缓冲*/
			var NT_SP_E_EVENT_ID_BUFFERING		 = NT_SP_E_EVENT_ID_BASE | 0x82; /*缓冲中, param1 表示百分比进度*/
			var NT_SP_E_EVENT_ID_STOP_BUFFERING  = NT_SP_E_EVENT_ID_BASE | 0x83; /*停止缓冲*/

			var NT_SP_E_EVENT_ID_DOWNLOAD_SPEED  = NT_SP_E_EVENT_ID_BASE | 0x91; /*下载速度, param1表示下载速度,单位是(Byte/s)*/

			var NT_SP_E_EVENT_ID_PLAYBACK_REACH_EOS		= NT_SP_E_EVENT_ID_BASE | 0xa1; /*播放结束, 直播流没有这个事件,点播流才有*/
			var NT_SP_E_EVENT_ID_RECORDER_REACH_EOS		= NT_SP_E_EVENT_ID_BASE | 0xa2; /*录像结束, 直播流没有这个事件, 点播流才有*/
			var NT_SP_E_EVENT_ID_PULLSTREAM_REACH_EOS   = NT_SP_E_EVENT_ID_BASE | 0xa3; /*拉流结束, 直播流没有这个事件,点播流才有*/
			var NT_SP_E_EVENT_ID_DURATION = NT_SP_E_EVENT_ID_BASE | 0xa8; /*视频时长,如果是直播,则不上报,如果是点播的话, 若能从视频源获取视频时长的话,则上报, param1表示视频时长,单位是毫秒(ms)*/
		</script>

调用展示:

		<script language='javascript' for="SmartPlayerActiveX"  event="OnSDKEventReceived(object_id, event_id, param1)">
			// Test 1 - statically load the script (This is the basis for the hack)
			// Works on IE8, IE9, IE10 and IE11
			
			var show_str = "";

			var connection_status = event_id;

			if (connection_status != 0)
			{
				show_str += "链接状态: ";

				if (NT_SP_E_EVENT_ID_CONNECTING == connection_status)
				{
					show_str += "链接中";
				}
				else if (NT_SP_E_EVENT_ID_CONNECTION_FAILED == connection_status)
				{
					show_str += "链接失败";
				}
				else if (NT_SP_E_EVENT_ID_CONNECTED == connection_status)
				{
					show_str += "链接成功";
				}
				else if (NT_SP_E_EVENT_ID_DISCONNECTED == connection_status)
				{
					show_str += "链接断开";
				}
				else if (NT_SP_E_EVENT_ID_NO_MEDIADATA_RECEIVED == connection_status)
				{
					show_str += "收不到数据";
				}
			}

			var download_speed = -1;
			
			if (NT_SP_E_EVENT_ID_DOWNLOAD_SPEED == event_id)
			{
				download_speed = param1;
			}
			
			if (download_speed != -1)
			{
				show_str += "下载速度:" + (download_speed * 8 / 1000).toFixed(0) + "kbps " + (download_speed / 1024).toFixed(0) + "KB/s";
			}
			
			var buffer_status = 0;
			
			if (NT_SP_E_EVENT_ID_START_BUFFERING == event_id
			|| NT_SP_E_EVENT_ID_BUFFERING == event_id
			|| NT_SP_E_EVENT_ID_STOP_BUFFERING == event_id)
			{
				buffer_status = event_id;
			}

			if (buffer_status != 0)
			{
				show_str += "缓冲状态: ";

				if (NT_SP_E_EVENT_ID_START_BUFFERING == buffer_status)
				{
					show_str += "开始缓冲";
				}
				else if (NT_SP_E_EVENT_ID_BUFFERING == buffer_status)
				{
					show_str += "缓冲中" + param1 + "%";
				}
				else if (NT_SP_E_EVENT_ID_STOP_BUFFERING == buffer_status)
				{
					show_str += "结束缓冲";
				}
			}
			
			var EventMsgText = document.getElementById("EventMsg");
						
			EventMsgText.innerHTML = show_str;
		</script>


2. void OnVideoSizeReceived(ULONG width, ULONG height);

回调视频宽高信息。

调用展示:

<script language='javascript' for="SmartPlayerActiveX"  event="OnVideoSizeReceived(width, height)">
	// Test 1 - statically load the script (This is the basis for the hack)
	// Works on IE8, IE9, IE10 and IE11
	
	var VideoResolutionText = document.getElementById("VideoResolution");
				
	VideoResolutionText.innerHTML = width + "*" + height;
</script>

SDK接口调用实例:

播放和录像调用示例:

			function OpenPlayer()
			{			   
				if(is_player_opened)
				{
					return;
				}
				
				var obj = document.getElementById("SmartPlayerActiveX");
				
				//如需记录log文件,请确保log路径存在, 如多级目录, 可按照"D:\\Daniulive\\log"类似格式设定, 记录文件名: smart_sdk.log
				obj.NT_SetLogPath("D:\\");
				
				obj.NT_SetObjectID("SmartPlayerActiveX");
				
				var ret = obj.NT_Open();
				
				if(ret == 0)
				{   
				    //设置TCP/UDP模式
					var rtsp_tcp_mode = document.getElementById("rtspTcpMode").checked ? 1 : 0;
					obj.NT_SetRTSPTcpMode(rtsp_tcp_mode);
					
					//设置RTSP超时时间
					var rtsp_timeout = document.getElementById("rtspTimeout").value;
					obj.NT_SetRtspTimeout(rtsp_timeout);
					
					//设置是否自动切换TCP-UDP模式
					var rtsp_auto_switch_tcp_udp = document.getElementById("rtspAutoSwitchTcpUdp").checked ? 1 : 0;
					obj.NT_SetRtspAutoSwitchTcpUdp(rtsp_auto_switch_tcp_udp);
					
					//设置是否快速启动
					var fast_startup_mode = document.getElementById("fastStartupMode").checked ? 1 : 0;
					obj.NT_SetFastStartup(fast_startup_mode);

					//设置是否硬解码
					var is_video_hardware_decoder = document.getElementById("videoHardwareDecoder").checked ? 1 : 0;
					obj.NT_SetVideoHardwareDecoder(is_video_hardware_decoder);
					
					
					//设置需要播放或录像的RTSP/RTMP url
					var url = document.getElementById("playorReocordUrl").value;
					obj.NT_SetURL(url);
					
					//设置实时截图路径(可自行设置或选取系统存在的文件夹), 如多级目录可按照"D:\\Daniulive\\image"类似格式设定
					var image_path = "D:\\";
					obj.NT_SetCaptureImagePath(image_path);
				
					is_player_opened = true;
				}
			}
			
			function ClosePlayer()
			{
				if(is_player_opened)
				{
					var obj = document.getElementById("SmartPlayerActiveX");
					obj.NT_Close();
					
					var EventMsgText = document.getElementById("EventMsg");	
					EventMsgText.innerHTML = "";
					
					is_player_opened = false;
				}
			}
			
			function OnBnClickedPlay()
			{
				if(!isIE())
				{
					alert("非IE浏览器,请用IE打开播放控件..");
					return;
				}
				
				if(!isActiveXInstalled())
				{
					alert("控件未加载,请先加载控件..");
					return;
				}
				
				if(is_playing)
				{
					StopPlayback();
				}
				else
				{
					StartPlayback();
				}
			}
			
			//开始播放
			function StartPlayback() {
				
				if(!is_playing && !is_recording)
				{
					OpenPlayer();
				}
				
				var obj = document.getElementById("SmartPlayerActiveX");
	
				//设置是否启用低延迟模式
				var low_latency_mode = document.getElementById("lowlatencyMode").checked ? 1 : 0;
				obj.NT_SetLowLatencyMode(low_latency_mode);
								
				//设置缓冲时间
				var buffer_time = document.getElementById("bufferTime").value;
				obj.NT_SetBuffer(buffer_time);
							
				//设置播放音量, 范围是[0, 100], 0是静音,100是最大音量, 默认是100
				//var audio_volume = 0;
				//obj.NT_SetAudioVolume(audio_volume);
				
				//设置视频画面的填充模式,如填充整个绘制窗口、等比例填充绘制窗口,如不设置,默认填充整个绘制窗口
				//mode: 0: 填充整个绘制窗口; 1: 等比例填充绘制窗口, 默认值是0
				var render_scale_mode = 1;
				obj.NT_SetRenderScaleMode(render_scale_mode);
								
				var ret = obj.NT_StartPlay();
				
				if(ret == 0)
				{
					is_playing = true;	
					
					var playBtnText = document.getElementById("playBtn");
				
					playBtnText.innerHTML = "停止播放";
				}		
			}
			
			//停止播放
			function StopPlayback() {
			
				if(!is_playing)
				{
					return;
				}
				
				var obj = document.getElementById("SmartPlayerActiveX");
	
				obj.NT_StopPlay();
				 
				is_playing = false;
				
				var playBtnText = document.getElementById("playBtn");
				
				playBtnText.innerHTML = "开始播放";
				
				if(!is_recording)
				{
					ClosePlayer();
				}
				
				var VideoResolutionText = document.getElementById("VideoResolution");
						
				VideoResolutionText.innerHTML = "";
			}
						
			function OnBnClickedRecord()
			{
				if(!isIE())
				{
					alert("非IE浏览器,请用IE打开播放控件..");
					return;
				}
				
				if(!isActiveXInstalled())
				{
					alert("控件未加载,请先加载控件..");
					return;
				}

				if(is_recording)
				{
					StopRecorder();
				}
				else
				{
					StartRecorder();
				}
			}
			
			//开始录像
			function StartRecorder() {
				
				if(!is_playing && !is_recording)
				{
					OpenPlayer();
				}
				
				var obj = document.getElementById("SmartPlayerActiveX");
	
				//设置实时录像存放路径(可自行设置或选取系统存在的文件夹), 如多级目录可按照"D:\\Daniulive\\rec"类似格式设定
				var rec_dir = "D:\\";
				obj.NT_SetRecorderDirectory(rec_dir);
				
				var rec_max_size = 200;
				obj.NT_SetRecorderFileMaxSize(rec_max_size);
				
				var type = 0;
				var file_name_prefix = "daniulive";
				var append_date = 1;
				var append_time = 1;
				obj.NT_NT_SP_RecorderFileNameRuler(type, file_name_prefix, append_date, append_time);
				
				var is_transcode = 1;
				obj.NT_SetRecorderAudioTranscodeAAC(is_transcode);
				
				var is_record_video = 1;
				obj.NT_SetRecorderVideo(is_record_video);
				
				var is_record_audio = 1;
				obj.NT_SetRecorderAudio(is_record_audio);
				
				var ret = obj.NT_StartRecorder();
				
				if(ret == 0)
				{
					is_recording = true;
					
					var recordBtnText = document.getElementById("recordBtn");
				
					recordBtnText.innerHTML = "停止录像";
				}
			}
			
			//停止录像
			function StopRecorder() {
			
				if(!is_recording)
				{
					return;
				}
				
				var obj = document.getElementById("SmartPlayerActiveX");
	
				obj.NT_StopRecorder();
				
				is_recording = false;
				
				var recordBtnText = document.getElementById("recordBtn");
				
				recordBtnText.innerHTML = "开始录像";
				
				if(!is_playing)
				{
					ClosePlayer();
				}
			}
			

快速切换URL调用示例:

//快速切换播放URL
function SwitchUrl() {

	if(!is_playing)
	{
		return;
	}

	var obj = document.getElementById("SmartPlayerActiveX");

	var switch_url = document.getElementById("playorReocordUrl").value;
	obj.NT_SwitchURL(switch_url);
}

实时静音调用示例:

//实时静音
var is_mute = 1;	
function SetMute() {
	
	var obj = document.getElementById("SmartPlayerActiveX");
	
	obj.NT_SetMute(is_mute);
	
	var muteText = document.getElementById("MuteBtn");
	
	if(is_mute == 1 )
	{
		is_mute = 0;
		muteText.innerHTML = "取消静音";
	}
	else
	{
		is_mute = 1;
		muteText.innerHTML  = "实时静音";
	}
}

视频view垂直反转、水平反转、旋转调用示例:

//垂直反转
var is_flip_vertical = 1;
function SetFlipVertical() {
	
	var obj = document.getElementById("SmartPlayerActiveX");
	
	obj.NT_SetFlipVertical(is_flip_vertical);
	
	var flipVerticalText = document.getElementById("FlipVerticalBtn");
	
	if(is_flip_vertical == 1 )
	{
		is_flip_vertical = 0;
		flipVerticalText.innerHTML = "取消反转";
	}
	else
	{
		is_flip_vertical = 1;
		flipVerticalText.innerHTML  = "垂直反转";
	}
}

//水平反转
var is_flip_horizontal = 1;
function SetFlipHorizontal() {
	
	var obj = document.getElementById("SmartPlayerActiveX");
	
	obj.NT_SetFlipHorizontal(is_flip_horizontal);
	
	var flipHorizontalText = document.getElementById("FlipHorizontalBtn");
	
	if(is_flip_horizontal == 1 )
	{
		is_flip_horizontal = 0;
		flipHorizontalText.innerHTML = "取消反转";
	}
	else
	{
		is_flip_horizontal = 1;
		flipHorizontalText.innerHTML  = "水平反转";
	}
}

//视频view旋转
var rotate_degrees_ = 0;
function SetRotation() {
	
	rotate_degrees_ += 90;
	rotate_degrees_ = rotate_degrees_ % 360;
	
	var obj = document.getElementById("SmartPlayerActiveX");
	
	obj.NT_SetRotation(rotate_degrees_);
	
	var rotateText = document.getElementById("RotateBtn");
					
	if (0 == rotate_degrees_)
	{
		rotateText.innerHTML = "旋转90度";
	}
	else if (90 == rotate_degrees_)
	{
		rotateText.innerHTML = "旋转180度";
	}
	else if (180 == rotate_degrees_)
	{
		rotateText.innerHTML = "旋转270度";
	}
	else if (270 == rotate_degrees_)
	{
		rotateText.innerHTML = "不旋转";
	}
}

实时截图调用示例:

function CaptureImage() {
	var obj = document.getElementById("SmartPlayerActiveX");

	obj.NT_CaptureImage();
}

全屏显示窗口调用示例:

//全屏显示窗口
function FullScreen() {
	var obj = document.getElementById("SmartPlayerActiveX");

	obj.NT_FullScreen();
}

标签:SP,obj,ULONG,IE,RTSP,RTMP,var,NT,ID
来源: https://blog.csdn.net/daniulivesdk/article/details/113935298

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有