Quicktime是一個跨瀏覽器的播放插件,能夠實現RTSP視頻直播,可用於電視直播或視頻監控平臺。本文主要講了關於播放器如何實現直播、事件響應、播放器全屏、動態修改播放路徑等問題。
須要準備的軟件:quicktime安裝文件、RTSP模擬器(或VLC播放器)。
如下是個人實現方式:javascript
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 直播路徑(便於動態切換播放路徑); html
4. kioskmode="true" 隱藏播放器右鍵菜單。java
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 |
}; |
代碼說明: ios
1. 上述代碼並不完整,須要根據實際狀況做相應調整;
2. 基本使用方式:Player.regQuickTimeEvents().setPlayerParameters(url);
3. Quicktime在播放RTSP時會有3-5秒延遲,這是緩存所至,但控件沒有提供相應清空緩存方法,只有經過SetRate()來設置播放速率來清除緩存。web
播放截圖:
瀏覽器
可能出現的問題:
1. 在顯示/隱藏播放控件、全屏/恢復時會致使從新加載視頻;緩存
1. JavaScript Scripting Guide for QuickTime
2. QuickTime: Embed Tag Attributes
3. QuickTime fullscreen ( 很帥的東西) app
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 |