如何在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_player_ocx.html:單個窗口功能展示。
- 4_player_ocx.html:4窗口功能展示。
- 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(); }