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. .NET Framework中Object基类有哪些方法?

    ToString(),虚方法,任何子类可重写自定义 GetType(),非虚,返回类型名 Equals(),虚方法,默认情况下判定两个引用是否指向同一实例.(ReferenceEquals()功能相同 ...

  2. innerHTML 与 innerText 的区别

    innerHTML指的是从对象的起始位置到终止位置的全部内容,包括Html标签.innerText 指的是从起始位置到终止位置的内容,但它去除Html标签.同时,innerHTML 是所有浏览器都支持 ...

  3. 转: BAT等研发团队的技术博客

    BAT 技术团队博客   1. 美团技术团队博客:  地址: http://tech.meituan.com/ 2. 腾讯社交用户体验设计(ISUX) 地址:http://isux.tencent.c ...

  4. JDBC、JTA、Spring的事务管理

    Java事务的类型有三种:JDBC事务.JTA(Java Transaction API)事务.容器事务. 事务就是对一系列的数据库操作(比如插入多条数据)进行统一的提交或回滚操作,如果插入成功,那么 ...

  5. Unity: Passing Constructor Parameters to Resolve

    In this tutorial we will go through of couple different ways of using custom constructor parameters ...

  6. JDBC编程

    简单地说,JDBC 可做三件事:与数据库建立连接.发送 SQL 语句并处理结果.下列代码段给出了以上三步的基本示例: Connection con = DriverManager.getConnect ...

  7. PAT (Basic Level) Practise 1040 有几个PAT(DP)

    1040. 有几个PAT(25) 时间限制 120 ms 内存限制 65536 kB 代码长度限制 8000 B 判题程序 Standard 作者 CAO, Peng 字符串APPAPT中包含了两个单 ...

  8. Java将文件转为字节数组

    Java将文件转为字节数组 关键字:文件,文件流,字节流,字节数组,二进制 摘要:最近工作中碰到的需求是,利用http传输二进制数据到服务器对应接口,需要传输userId, file(加密后)等一系列 ...

  9. 经典的javascript函数实例,css的. #区别

    先贴javascript经典例子代码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" &quo ...

  10. 网页语言有html,php.jsp,无论什么语言浏览器总是能正常显示,这个解析工作是浏览器完成的吗?

    不是,浏览器最基本的语言是html也就是说浏览器只看得懂html.css.js等其他的服务器端动态脚本,比如你说的php.jsp等,解析工作是在服务器完成的!打个比方,你在电脑显示屏上看到的一切东西, ...