Quicktime是一个跨浏览器的播放插件,可以实现RTSP视频直播,可用于电视直播或视频监控平台。本文主要讲了关于播放器如何实现直播、事件响应、播放器全屏、动态修改播放路径等问题。

需要准备的软件:quicktime安装文件、RTSP模拟器(或VLC播放器)。
   以下是我的实现方式:

1. 播放器HTML静态代码

01 <div id="player">
02   <!--[if IE]><object id="qt_event_source" classid="clsid:CB927D12-4FF7-4a9e-A169-56E4B8A75598" style="display:none;"></object><![endif]-->
03   <object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" width="640" height="480" codebase="http://www.apple.com/qtactivex/qtplugin.cab#version=7,6,9,0" standby="控件加载中..." name="QT_OBJ" id="QT_OBJ" style="behavior:url(#qt_event_source);overflow:hidden;">
04     <param name="src" value="ress/preview.mov"/>
05     <!-- <param name="qtsrc" value="rtsp://"/> -->
06     <param name="enablejavascript" value="true"/>
07     <param name="postdomevents" value="true"/>
08     <param name="controller" value="false"/>
09     <param name="scale" value="tofit"/>
10     <param name="kioskmode" value="true"/>
11     <param name="bgcolor" value="#000000"/>
12     <param name="qtsrcdontusebrowser" value="true"/>
13     <param name="cache" value="false"/>
14     <!-- qtsrc=""  -->
15     <embed src="ress/preview.mov" width="640" height="480" pluginspage="http://www.apple.com/quicktime/download/" name="QT_EMB" id="QT_EMB" enablejavascript="true" postdomevents="true" controller="false" scale="tofit" kioskmode="true" bgcolor="#000000" qtsrcdontusebrowser="true" cache="false" style="overflow:hidden;"></embed>
16   </object>
17 </div>

代码说明:
1. object 用于IE浏览器,而 embed 用于非IE浏览器;
2. qt_event_source 对象是为了给IE浏览器注册事件,通过style( style="behavior:url(#qt_event_source);overflow:hidden;")绑定行为;
3. src="ress/preview.mov" 用于在页面加载后初始化控件,因为在上述代码中没有初始化 qtsrc 直播路径(便于动态切换播放路径);

4. kioskmode="true" 隐藏播放器右键菜单。

2. Javascript代码实现(部分)

001 var Player = {
002     /**
003      * 播放器对象
004      */
005     object : null,
006     stream : {
007         /**
008          * 视频初始化原始宽度
009          */
010         width : 640,
011         /**
012          * 视频初始化原始高度
013          */
014         height : 480
015     },
016     /**
017      * 设置播放路径
018      
019      * @param url
020      */
021     setPlayerParameters : function(url) {
022         try {
023             if (Player.object) {
024                 var qt = Player.object;
025                 if (!$.browser.msie && !qt.SetURL) {
026                     return this;
027                 }
028                 qt.SetURL(url);
029                 qt.SetControllerVisible(false);
030                 qt.SetKioskMode(true);
031                 qt.SetVolume(100);
032                 qt.SetBgColor('#ffffff');
033             }
034         } catch (e) {
035             alert('resetPlayerParameters - ' + e.toString());
036         }
037         return this;
038     },
039     /**
040      * 设置播放速率
041   
042      * 实现实时播放
043      */
044     setRate : function() {
045         if (Player.object)
046             Player.object.SetRate(10);
047     },
048     /**
049      * 初始化播放路径,如:rtsp://192.168.0.100:554/3
050      
051      * @param stream
052      * @returns
053      */
054     initGUrl : function(stream) {
055         var host = location.hostname;
056         var port = '';// ':'+554;
057         var url = [ 'rtsp://', host, port, '/', stream ].join('');
058         return url;
059     },
060     /**
061      * 注册事件,为IE浏览器注册时要多加个'on'在事件前面
062      */
063     regQuickTimeEvents : function() {
064         var listerners = Player.listerners;
065         if (document.addEventListener) {
066             var obj = document.QT_EMB;
067             if (obj) {
068                 Player.object = obj;
069                 obj.addEventListener("qt_timechanged",
070                         listerners._qt_timechanged_listerner);
071                 obj.addEventListener("qt_stalled",
072                         listerners._qt_stalled_listerner);
073                 obj
074                         .addEventListener("qt_error",
075                                 listerners._qt_error_listerner);
076             }
077         } else {
078             var obj = document.QT_OBJ;
079             if (obj) {
080                 Player.object = obj;
081                 obj.attachEvent("onqt_timechanged",
082                         listerners._qt_timechanged_listerner);
083                 obj.attachEvent("onqt_stalled",
084                         listerners._qt_stalled_listerner);
085                 obj.attachEvent("onqt_error", listerners._qt_error_listerner);
086             }
087         }
088         return this;
089     },
090     listerners : {
091         _qt_timechanged_listerner : function() {
092             if (Player.object) {
093                 var qt = Player.object;
094                 if (!$.browser.msie && !qt.SetRate) {
095                     return false;
096                 }
097                 // 通过设置播放率快速播放来消耗缓存达到实时播放
098                 qt.SetRate(10);
099                 qt.SetBgColor('#000000');
100                 Player.getStreamWidthHeight(qt, true);
101                 Player.adaptation();
102             }
103         },
104         _qt_stalled_listerner : function() {
105             alert('连接已终断,正在尝试重新连接...');
106         },
107         _qt_error_listerner : function() {
108             alert('播放时发生错误,请刷新页面或重新登录来解决此问题!');
109         }
110     },
111     /**
112      * 将视频填充到当前播放器大小一致,并维持原始长宽比
113   
114      * SetRectangle参数中每个值都必须是整形,不能有小数 在计算时可能出现高度或宽度相差一个像素
115      */
116     adaptation : function() {
117         try {
118             if (!Player.object)
119                 return false;
120             var object = Player.object;
121             var qt = $(object);
122             var w_box = qt.width();
123             var h_box = qt.height();
124             var wh = Player.getStreamWidthHeight(object, false);
125             if (!wh)
126                 return false;
127             var w_per = wh.width || 640;
128             var h_per = wh.height || 480;
129             var rect = [ 0, 0, 640, 480 ];
130             var dw = w_per / w_box;
131             var dh = h_per / h_box;
132             if (dw == dh) {
133                 rect[2] = parseInt(w_box);
134                 rect[3] = parseInt(h_box);
135             } else if (dw > dh) {
136                 var h_per_new = h_per / dw;
137                 var offset = (h_box - h_per_new) / 2;
138                 rect[1] = parseInt(offset);
139                 rect[2] = parseInt(w_box);
140                 rect[3] = parseInt(h_per_new + offset);
141             } else {
142                 var w_per_new = w_per / dh;
143                 var offset = (w_box - w_per_new) / 2;
144                 rect[0] = parseInt(offset);
145                 rect[2] = parseInt(w_per_new + offset);
146                 rect[3] = parseInt(h_box);
147             }
148             if (!$.browser.msie && !object.SetRectangle) {
149                 return false;
150             }
151             object.SetRectangle(rect.join(','));
152         } catch (e) {
153             // TODO
154         }
155     },
156     /**
157      * 获取播放器对象的高度和宽度
158      
159      * @param playerObj
160      * @param isInit
161      *            是否将 Player.stream中的参数重写
162      * @returns
163      */
164     getStreamWidthHeight : function(playerObj, isFlash) {
165         try {
166             if (!playerObj)
167                 return false;
168             if (!$.browser.msie && !playerObj.GetRectangle) {
169                 return false;
170             }
171             var rect = playerObj.GetRectangle().split(',');
172             var width = parseInt(rect[2]) - parseInt(rect[0]);
173             var height = parseInt(rect[3]) - parseInt(rect[1]);
174             if (isFlash) {
175                 this.stream.width = width;
176                 this.stream.height = height;
177             }
178             return {
179                 width : width || this.stream.width,
180                 height : height || this.stream.height
181             };
182         } catch (e) {
183             // TODO
184         }
185     },
186     /**
187      * @param{Object} el 被放大对象
188      */
189     requestFullScreen : function(el) {
190         var agent = '';// TODO 获取浏览器名称
191         var obj = $(el);
192           
193         // 支持大多数浏览器全屏功能,除了FCK IE!
194         var requestMethod = el.requestFullScreen || el.webkitRequestFullScreen
195                 || el.mozRequestFullScreen || el.msRequestFullScreen;
196           
197         if (requestMethod) {
198             requestMethod.call(el);
199             var stream = Player.stream;
200             el.SetRectangle([ 0, 0, stream.width, stream.height ].join(','));
201             obj.width(window.screen.width);
202             obj.height(window.screen.height);
203   
204             // 根据不同浏览器作相应调整
205             if (agent.name == 'safari') {
206                 obj.offset({
207                     top : 0,
208                     left : 0
209                 });
210             }
211         } else {
212             // 如果浏览器没有全屏接口就放大显示区
213             // TODO
214         }
215     }
216 };

代码说明:

1. 上述代码并不完整,需要根据实际情况作相应调整;
2. 基本使用方式:Player.regQuickTimeEvents().setPlayerParameters(url);
3. Quicktime在播放RTSP时会有3-5秒延迟,这是缓存所至,但控件没有提供相应清空缓存方法,只有通过SetRate()来设置播放速率来清除缓存。

播放截图:

可能出现的问题:
1. 在显示/隐藏播放控件、全屏/恢复时会导致重新加载视频;

3. 相关资源

1.  JavaScript Scripting Guide for QuickTime
2.  QuickTime: Embed Tag Attributes
3. QuickTime fullscreen ( 很帅的东西)

4. Quicktime插件函数列表

AddCuePoint(time, fcnName, pause) void  
Clear() void  
GetAutoPlay() Number  
GetBgColor() String 获取播放器背景颜色
GetChapterCount() Number  
GetChapterName(chapterNum) String  
GetComponentVersion(type, subType, manufacturer) String  
GetControllerVisible() Number  
GetCurrentChapterIndex() Number  
GetDuration() Number  
GetEndTime() Number  
GetFieldOfView() Number  
GetHotspotTarget(hotspotID) String  
GetHotspotUrl(hotspotID) String  
GetHREF() Number  
GetIsLooping() Number  
GetIsQuickTimeRegistered() Number  
GetIsVRMovie() Number  
GetKioskMode() Number  
GetLanguage() String  
GetLoopIsPalindrome() Number  
GetMatrix() String  
GetMaxBytesLoaded() Number  
GetMaxTimeLoaded() Number  
GetMIMEType() String  
GetMovieID() Number  
GetMovieName() String  
GetMovieSize() Number  
GetMute() Number  
GetNodeCount() Number  
GetNodeID() Number  
GetPanAngle() Number  
GetPlayEveryFrame() Number  
GetPluginStatus() String  
GetPluginVersion() String  
GetQTNEXTUrl(index) String  
GetQuickTimeConnectionSpeed() Number  
GetQuickTimeLanguage() String  
GetQuickTimeVersion() String  
GetRate() Number  
GetRectangle() String  
GetResetPropertiesOnReload() Number  
GetSpriteTrackVariable(trackIndex, variableIndex) String  
GetStartTime() Number  
GetTarget() String  
GetTiltAngle() Number  
GetTime() Number  
GetTimeScale() Number  
GetTrackCount() Number  
GetTrackEnabled(index) Number  
GetTrackName(index) String  
GetTrackType(index) String  
GetURL() String  
GetUserData(type) String  
GetVolume() Number  
GoPreviousNode() void  
GoToChapter(chapterName) void  
Hide() void  
Play() void  
RemoveCuePoint(time, fcnName) void  
Rewind() void  
SendSpriteEvent(trackIndex, spriteID, messageID) void  
SetAutoPlay(autoPlay) void  
SetBgColor(color) void  
SetControllerVisible(visible) void  
SetCurrentChapterIndex(chapterIndex) void  
SetEndTime(time) void  
SetFieldOfView(fov) void  
SetHotspotTarget(hotspotID, target) void  
SetHotspotUrl(hotspotID, url) void  
SetHREF(url) void  
SetIsLooping(loop) void  
SetKioskMode(kioskMode) void  
SetLanguage(language) void  
SetLoopIsPalindrome(loop) void  
SetMatrix(matrix) void  
SetMovieID(movieID) void  
SetMovieName(movieName) void  
SetMute(mute) void  
SetNodeID(id) void  
SetPanAngle(angle) void  
SetPlayEveryFrame(playAll) void  
SetQTNEXTUrl(index, url) void  
SetRate(rate) void 设置播放速度。可设置较大速度以此作清除缓存的辅助工具。
SetRectangle(rect) void 设置显示画面大小和位置。
SetResetPropertiesOnReload(reset) void  
SetSpriteTrackVariable(trackIndex, variableIndex, value) void  
SetStartTime(time) void  
SetTarget(target) void  
SetTiltAngle(angle) void  
SetTime(time) void  
SetTrackEnabled(index, enabled) void  
SetURL(url) void  
SetVolume(volume) void  
Show() void  
ShowDefaultView() void  
Step(count) void  
Stop() void  

使用Quicktime 实现视频直播(Live video using Quicktime) (转)的更多相关文章

  1. 前端视频直播技术总结及video.js在h5页面中的应用

    全手打原创,转载请标明出处:https://www.cnblogs.com/dreamsqin/p/12557070.html,多谢,=.=~ (如果对你有帮助的话请帮我点个赞啦) 目前有一个需求是在 ...

  2. 【腾讯bugly干货分享】HTML 5 视频直播一站式扫盲

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://bugly.qq.com/bbs/forum.php?mod=viewthread&tid=1277 视频直 ...

  3. 【腾讯Bugly干货分享】H5 视频直播那些事

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57a42ee6503dfcb22007ede8 Dev Club 是一个交流移动 ...

  4. iOS中 视频直播功能-流媒体的使用(详解)韩俊强的CSDN博客

    上一篇博客:(流媒体实现视频播放和下载功能):http://blog.csdn.net/qq_31810357/article/details/50574914 最近视频直播功能比较火,处于需求,研究 ...

  5. HLS视频直播

    HTTP Live Streaming (HLS) 苹果官方对于视频直播服务提出了 HLS 解决方案,该方案主要适用范围在于: 使用 iPhone .iPod touch. iPad 以及 Apple ...

  6. Android&iOS视频直播之旅

    现在的移动互联网时代,大家的网速真是越来越快,高带宽的WIFI和覆盖率极大的4G,4G+把手机观看视频直播推上了风口浪尖,越来越多的应用在玩手机视频直播,我们做的应用里也要嵌入视频直播. 这篇文章里我 ...

  7. 使用ckplayer搭建rtmp视频直播应用

    视频直播才有的是RTMP协议进行视频实时流传输,在这里我们用到的软件都是 adobe 公司的一个是:Flash Media Server4 另一个是flash media live encoder 这 ...

  8. 基于live555的视频直播 DM368IPNC RTSP分析

    因需要,从个人的理解顺序和需求角度对live555的分析与开发整理,包含RTSP Server与RTSP Client.如何直播H.264流与JPEG流等,均进行了探讨,对live555的初学者有一定 ...

  9. H5 视频直播相关技术

    一.移动视频直播发展 大家首先来看下面这张图: 可以看到,直播从 PC 到一直发展到移动端,越来越多的直播类 App 上线,同时移动直播进入了前所未有的爆发阶段,但是对于大多数移动直播来说,还是要以 ...

随机推荐

  1. Django分析之Middleware中间件

    写了几周的脚本,今天终于开始接触web框架了~学习Python的web框架,那么Django就几乎是必修课了,这次的工作是先打打下手,主要的任务是在setting中添加版本号,在渲染静态css,js的 ...

  2. aps.net cored 新概念

    Tag Helpers The EnvironmentTagHelper can be used to include different scripts in your views (for exa ...

  3. C#中xml操作

    序列化成一个字符串: public static string XMLSerialize<T>(T entity) { StringBuilder buffer = new StringB ...

  4. 李洪强iOS经典面试题143-绘图与动画

    李洪强iOS经典面试题143-绘图与动画   绘图与动画 CAAnimation的层级结构 CAPropertyAnimation是CAAnimation的子类,也是个抽象类,要想创建动画对象,应该使 ...

  5. CentOS7 编译安装 Mariadb (实测 笔记 Centos 7.0 + Mariadb 10.0.15)

    环境: 系统硬件:vmware vsphere (CPU:2*4核,内存2G,双网卡) 系统版本:CentOS-7.0-1406-x86_64-DVD.iso 安装步骤: 1.准备 1.1 显示系统版 ...

  6. *HDU1829 并查集

    A Bug's Life Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Tot ...

  7. Spring MVC:在jsp中引入css

    为了将css引入jsp中,今天可真是踩了好多坑,最后在stackoverflow上找到了解决方法,不多说贴出代码. 在web.xml中添加以下代码: <servlet-mapping> & ...

  8. NOIP2014初赛分数线及金华上线名单

    NOIP2014初赛分数线及金华上线名单 分数线:提高组81.5,普及组93 这分数线还能再高些吗?悲催的浙江. 金华上线普及组名单: 地市 姓名 学校 年级 参赛语种 成绩 金华 成浩鹏 稠州丹溪校 ...

  9. struts基于ognl的自动类型转换需要注意的地方

    好吧,坎坷的过程我就不说了,直接上结论: 在struts2中使用基于ognl的自动类型转换时,Action中的对象属性必须同时添加get/set方法. 例如: 客户端表单: <s:form ac ...

  10. 【PC网站前端架构探讨系列】关于中小型PC网站前端架构方案的讨论与实践

    目   录 1.遇到的问题 2.目标 3.探讨 4.架构设想 5.流程 6.初步实现 7.存在问题 8.最后 遇到的问题 我在这个系列上篇文章 已经讲解并开始逐步应用模块化思想,不知大家还记不记得,题 ...