如何在IE瀏覽器播放RTSP或RTMP流

  • 2019 年 10 月 5 日
  • 筆記

好多開發者一直苦惱於如何在IE瀏覽器環境下,構建低延遲的RTSP或RTMP播放,對於RTSP流來說,好多公司通常的做法是把RTSP轉RTMP,然後分發到RTMP伺服器,然後伺服器轉http-flv出來,瀏覽器直接播放http-flv流,亦或通過flash控制項直接播放RTMP流,還有就是,轉hls流出來,缺點是hls流延遲更大。

以上方案未嘗不可,如果對播放體驗和延遲要求更高,最簡單的做法是直接在IE瀏覽器下載入activex控制項。

大牛直播SDK(Github)在現有SDK的基礎上,擴展了ocx控制項,用於IE瀏覽器下的低延遲RTMP或RTSP播放,不謙虛的說,也可能是行業內功能支援和延遲最好的RTMP和RTSP播放器(支援RTMP/RTSP H.265(hevc)播放)。

頁面展示

1. 功能齊全的單畫面RTMP流或RTSP流播放:

2. 同時播放4路RTMP流或RTSP流畫面:

本地播放

DEMO說明

  1. 1_player_ocx.html:單個窗口功能展示。
  2. 4_player_ocx.html:4窗口功能展示。
  3. SmartPlayer.exe:cs架構播放器。

運行網頁播放端之前,請確保以管理員許可權註冊ocx控制項:regplayerocx.bat右鍵–>「以管理員身份運行(A)」,同理,反註冊也是需要管理員身份。

注意:RTSP/RTMP播放OCX控制項只適用於微軟IE瀏覽器。

對應封裝介面

	ULONG NT_SetLogPath();  	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_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(ULONG event_id, ULONG param1);  	void OnVideoSizeReceived(ULONG width, ULONG height);

設置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();

全螢幕顯示窗口。

事件Event:

1. void OnSDKEventReceived(ULONG event_id, ULONG param1);

回調網路狀態、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(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介面調用實例:

播放和錄像調用示例:

var is_player_opened = false;  var is_playing = false;  var is_recording = false;    function OpenPlayer()  {  	if(is_player_opened)  	{  		return;  	}    	var obj = document.getElementById("SmartPlayerActiveX");    	//如需記錄log文件,請確保log路徑存在, 如多級目錄, 可按照"D:\Daniulive\log"類似格式設定, 記錄文件名: smart_sdk.log  	obj.NT_SetLogPath("D:\");    	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);    		//設置需要播放或錄像的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);    	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();  }