好多开发者一直苦恼于如何在IE浏览器环境下,构建低延迟的RTSP或RTMP播放,对于RTSP流来说,好多公司通常的做法是把RTSP转RTMP,然后分发到RTMP服务器,然后服务器转http-flv出来,浏览器直接播放http-flv流,亦或通过flash控件直接播放RTMP流,还有就是,转hls流出来,缺点是hls流延迟更大。
以上方案未尝不可,如果对播放体验和延迟要求更高,最简单的做法是直接在IE浏览器下加载activex控件。
大牛直播SDK(Github: https://github.com/daniulive/SmarterStreaming)在现有SDK的基础上,扩展了ocx控件,用于IE浏览器下的低延迟RTMP或RTSP播放,不谦虚的说,也可能是行业内功能支持和延迟最好的RTMP和RTSP播放器(支持RTMP/RTSP H.265(hevc)播放)。
页面展示
1. 功能齐全的单画面RTMP流或RTSP流播放:
2. 同时播放4路RTMP流或RTSP流画面:
本地播放和集成说明:
点我下载DEMO
本地播放
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.logobj.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 IE11var 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 IE11var 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.logobj.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 urlvar 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();
}