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. ZooKeeper学习总结 第二篇:ZooKeeper深入探讨(转载)

    其实zookeeper系列的学习总结很早就写完了,这段时间在准备找工作的事情,就一直没有更新了.下边给大家送上,文中如有不恰当的地方,欢迎给予指证,不胜感谢!. 1. 数据模型 1.1. 只适合存储小 ...

  2. NOI 题库 2727

    2727   仙岛求药 描述 少年李逍遥的婶婶病了,王小虎介绍他去一趟仙灵岛,向仙女姐姐要仙丹救婶婶.叛逆但孝顺的李逍遥闯进了仙灵岛,克服了千险万难来到岛的中心,发现仙药摆在了迷阵的深处.迷阵由M×N ...

  3. YACC和BISON学习心得

    最近学习了YACC和BISON两个工具,参考书籍<YACC和BISON>,通过里面的例子,明白了如何编写自己的解释性语言.

  4. C语言_第一章

    1. 计算机能直接识别和接受的二进制代码称为     机器指令——>(集合) 机器语言. 2. 输出C #include<stdio.h> int main(){ printf(&q ...

  5. Unity3d与Android交互

    先看下效果 你一定会说,然并卵! 没错,这里只是一个最简单的例子,unity与android activity 互相传参数. 玩过手游的都知道,在你要为你心爱的游戏角色准备花钱买钻石,点击购买的时候, ...

  6. centos使用yum安装软件的时候出现了undefined symbol: CRYPTO_set_locking_callback

    1.问题 在CentOS下使用yum安装软件,结果出现了下面的错误提示: # yum installThere was a problem importing one of the Python mo ...

  7. Velocity 语法(转)

    一.基本语法 1."#"用来标识Velocity的脚本语句,包括#set.#if .#else.#end.#foreach.#end.#iinclude.#parse.#macro ...

  8. 【KMP算法】字符串匹配

    一.问题 给定两个字符串S(原串)和(模式串)T,找出T在S中出现的位置. 二.朴素算法 当S[i] != T[j]时,把T往后移一位,回溯S的位置并重新开始比较.    (1) 成功匹配的部分(AB ...

  9. Python实战:下载鬼灵报告有声小说

    在家无聊,想看看小说,不过看的眼睛痛,就想着下个有声小说来听听.但风上找到的都是要一集一集下,还得重命名,122集啊,点到什么时候. 写个批处理下载的脚本.记录下过程. 一.老套路了,找到下载URL. ...

  10. HTML 5 画布(canvas)

    canvas 元素使用 JavaScript 在网页上绘制图像,本身是没有绘图能力. canvas 是一个矩形区域,可以控制其每一像素. canvas 拥有多种绘制路径.矩形.圆形.字符以及添加图像的 ...