2
0

srs_gb28181.html 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <title>SRS</title>
  5. <meta charset="utf-8">
  6. <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"/>
  7. <style>
  8. body{
  9. padding-top: 55px;
  10. }
  11. #my_modal_footer {
  12. margin-top: -20px;
  13. padding-top: 3px;
  14. }
  15. #main_modal {
  16. margin-top: -60px;
  17. }
  18. #rtc_player_modal {
  19. margin-top: -60px;
  20. }
  21. .div_play_time {
  22. margin-top: 10px;
  23. }
  24. #pb_buffer_bg {
  25. margin-top: -4px;
  26. margin-bottom: 10px;
  27. }
  28. </style>
  29. </head>
  30. <body>
  31. <img src='https://ossrs.net/gif/v1/sls.gif?site=ossrs.net&path=/player/srsplayer'/>
  32. <div class="navbar navbar-fixed-top">
  33. <div class="navbar-inner">
  34. <div class="container">
  35. <a id="srs_index" class="brand" href="#">SRS</a>
  36. <div class="nav-collapse collapse">
  37. <ul class="nav">
  38. <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
  39. <li><a id="nav_rtc_player" href="rtc_player.html">RTC播放器</a></li>
  40. <li><a id="nav_rtc_publisher" href="rtc_publisher.html">RTC推流</a></li>
  41. <li><a href="http://ossrs.net/srs.release/releases/app.html">iOS/Andriod</a></li>
  42. <!--<li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>-->
  43. <!--<li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>-->
  44. <!--<li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>-->
  45. <!--<li><a id="nav_vlc" href="vlc.html">VLC播放器</a></li>-->
  46. <li class="active" ><a id="nav_gb28181" href="srs_gb28181.html">GB28181</a></li>
  47. <li>
  48. <a href="https://github.com/ossrs/srs">
  49. <img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/ossrs/srs?style=social">
  50. </a>
  51. </li>
  52. </ul>
  53. </div>
  54. </div>
  55. </div>
  56. </div>
  57. <div class="container">
  58. <div name="detect_flash">
  59. <div id="main_flash_alert" class="alert alert-danger fade in hide">
  60. <button type="button" class="close" data-dismiss="alert">×</button>
  61. <strong><p>Usage:</p></strong>
  62. <p>
  63. 请点击下面的图标,启用Flash
  64. </p>
  65. <p>
  66. 若没有见到这个图标,Chrome浏览器请打开
  67. <span class="text-info">chrome://settings/content/flash</span> 并修改为"Ask first"。
  68. </p>
  69. </div>
  70. <div id="main_flash_hdr" class="hide">
  71. </div>
  72. </div>
  73. <div class="form-inline">
  74. API地址与端口
  75. <input type="text" id="txt_api_url" class="input-xxlarge">
  76. <p></p>
  77. </div>
  78. <div>
  79. <div class="row">
  80. <div class="span4" id="divSipSessionList">
  81. <span>sip会话(需内部启用sip)</span><label id="lab_sip_session"></label>
  82. <div style="overflow:scroll; height:330px; width:310px">
  83. <ul id="sipSessionList"></ul>
  84. </div>
  85. </div>
  86. <div class="span8">
  87. <button class="btn btn-primary" id="btn_sip_query_session">查询所有会话</button>
  88. <button class="btn btn-primary" id="btn_sip_unregister">unregister</button>
  89. <button class="btn btn-primary" id="btn_sip_invite">invite</button>
  90. <button class="btn btn-primary" id="btn_sip_bye">bye</button>
  91. <button class="btn btn-primary" id="btn_sip_querycatalog">querycatalog</button>
  92. <div id="context2">
  93. 当前会话:<a id="sipSessionId"></a>
  94. <div>
  95. <pre id="sipSessionMessage" style="overflow:scroll; height:280px"></pre>
  96. </div>
  97. </div>
  98. </div>
  99. </div>
  100. </div>
  101. <p></p>
  102. <div>
  103. <div class="row">
  104. <div class="span4" id="divMediaChannelList">
  105. <span>GB28181媒体通道</span><label id="lab_gb28181_ch"></label>
  106. <div style="overflow:scroll; height:400px; width:310px">
  107. <ul id="gb28181ChList"></ul>
  108. </div>
  109. </div>
  110. <div class="span8">
  111. <button class="btn btn-primary" id="btn_query_channel">查询所有通道</button>
  112. <button class="btn btn-primary" id="btn_create_channel">创建通道</button>
  113. <button class="btn btn-primary" id="btn_delete_channel">删除通道</button>
  114. <div id="context2">
  115. 当前通道:<a id="gb28181ChannelId"></a>
  116. <div>
  117. <textarea class="span6" id="txt_rtmp_url" rows="2"></textarea>
  118. <button class="btn btn-primary" id="btn_play">FLV播放</button>
  119. </div>
  120. <div>
  121. <textarea class="span6" id="txt_rtc_url" rows="2"></textarea>
  122. <button class="btn btn-primary" id="btn_rtc_play">RTC播放</button>
  123. <div>RTC播放,需要后台启用RTC功能才能正常播放,
  124. <a href='https://github.com/ossrs/srs/wiki/v4_CN_RTCWiki'>RTC配置参考</a>
  125. </div>
  126. </div>
  127. <div>
  128. <pre id="gb28181ChannelMessage" style="overflow:scroll; height:210px"></pre>
  129. </div>
  130. </div>
  131. </div>
  132. </div>
  133. </div>
  134. <div id="main_content" class="hide">
  135. <div id="main_modal" class="modal hide fade">
  136. <div class="modal-header">
  137. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  138. <h3><a href="https://github.com/ossrs/srs">SrsFlvPlayer</a></h3>
  139. </div>
  140. <div class="modal-body">
  141. <div>
  142. <video id="video_player" width="98%" autoplay controls></video>
  143. </div>
  144. </div>
  145. <div class="modal-footer" id="my_modal_footer">
  146. <div>
  147. <div class="btn-group dropup">
  148. <button class="btn btn-primary" id="btn_ptz_up"> 上↑ </button>
  149. <button class="btn btn-primary" id="btn_ptz_down"> 下↓ </button>
  150. <button class="btn btn-primary" id="btn_ptz_left"> ←左 </button>
  151. <button class="btn btn-primary" id="btn_ptz_right"> 右→ </button>
  152. <button class="btn btn-primary" id="btn_ptz_zoomin"> 放大+ </button>
  153. <button class="btn btn-primary" id="btn_ptz_zoomout"> 缩小- </button>
  154. </div>
  155. [注意] !!! 云台控制需要启用内部sip功能
  156. </div>
  157. </div>
  158. </div>
  159. <div id="rtc_player_modal" class="modal hide fade">
  160. <div class="modal-header">
  161. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  162. <h3><a href="https://github.com/ossrs/srs">RtcPlayer</a></h3>
  163. </div>
  164. <div class="modal-body">
  165. <video id="rtc_media_player" width="100%" controls autoplay ></video>
  166. </div>
  167. <div class="modal-footer" id="my_modal_footer">
  168. <div>
  169. <div class="btn-group dropup">
  170. <button class="btn btn-primary" id="btn_ptz_up_rtc"> 上↑ </button>
  171. <button class="btn btn-primary" id="btn_ptz_down_rtc"> 下↓ </button>
  172. <button class="btn btn-primary" id="btn_ptz_left_rtc"> ←左 </button>
  173. <button class="btn btn-primary" id="btn_ptz_right_rtc"> 右→ </button>
  174. <button class="btn btn-primary" id="btn_ptz_zoomin_rtc"> 放大+ </button>
  175. <button class="btn btn-primary" id="btn_ptz_zoomout_rtc"> 缩小- </button>
  176. </div>
  177. [注意] !!! 云台控制需要启用内部sip功能
  178. </div>
  179. </div>
  180. </div>
  181. <div id="create_channel_modal" class="modal hide fade">
  182. <div class="modal-header">
  183. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  184. <h3>创建通道</h3>
  185. </div>
  186. <div class="modal-body">
  187. <div>
  188. <span class="add-on">通道ID</span>
  189. <input class="span1" style="width:200px" id="txt_channel_id" type="text" >
  190. </div>
  191. <div>
  192. <span class="add-on">app</span>
  193. <input class="span1" style="width:200px" id="txt_app" type="text" value="live">
  194. </div>
  195. <div>
  196. <div>可以参数化: [stream]--通道ID; [ssrc]--rtp中ssrc; [timestamp]--当前时间戳</div>
  197. <span class="add-on">stream</span>
  198. <input class="span1" style="width:200px" id="txt_stream" type="text" value="[stream]">
  199. </div>
  200. <div>
  201. <span>端口模式</span>
  202. <select id="sel_ch_mode_type" onclick="selectChannelModeType(this)">
  203. <option value="fixed">固定</option>
  204. <option value="random">随机</option>
  205. </select>
  206. </div>
  207. </div>
  208. <div class="modal-footer" id="my_modal_footer">
  209. <div class="btn-group dropup">
  210. <button id="btn_channel_cancel" class="btn btn-primary">取消</button>
  211. </div>
  212. <div class="btn-group dropup">
  213. <button id="btn_channel_submit" class="btn btn-primary">提交</button>
  214. </div>
  215. </div>
  216. </div>
  217. </div>
  218. <footer>
  219. <p></p>
  220. <p><a href="https://github.com/ossrs/srs">SRS Team &copy; 2013</a></p>
  221. </footer>
  222. </div>
  223. </body>
  224. <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
  225. <script type="text/javascript" src="js/bootstrap.min.js"></script>
  226. <script type="text/javascript" src="js/json2.js"></script>
  227. <script type="text/javascript" src="js/srs.page.js"></script>
  228. <script type="text/javascript" src="js/srs.log.js"></script>
  229. <script type="text/javascript" src="js/srs.utility.js"></script>
  230. <script type="text/javascript" src="js/winlin.utility.js"></script>
  231. <script type="text/javascript" src="js/flv-1.5.0.min.js"></script>
  232. <script type="text/javascript" src="js/hls-0.14.17.min.js"></script>
  233. <script type="text/javascript">
  234. $(function(){
  235. $('#main_content').show();
  236. autoLoadPage();
  237. });
  238. </script>
  239. <script type="text/javascript">
  240. var srs_player = null;
  241. var url = null;
  242. var query = parse_query_string();
  243. var query_host = query.host.split(':');
  244. if (query_host && query_host.length == 2) {
  245. $("#txt_api_url").val("http://" + query_host[0] + ":1985");
  246. } else {
  247. $("#txt_api_url").val("http://" + query.host + ":1985");
  248. }
  249. var __active_dar = null;
  250. function select_dar(dar_id, num, den) {
  251. srs_player.set_dar(num, den);
  252. if (__active_dar) {
  253. __active_dar.removeClass("active");
  254. }
  255. __active_dar = $(dar_id).parent();
  256. __active_dar.addClass("active");
  257. }
  258. var __active_size = null;
  259. function select_fs_size(size_id, refer, percent) {
  260. srs_player.set_fs(refer, percent);
  261. if (__active_size) {
  262. __active_size.removeClass("active");
  263. }
  264. __active_size = $(size_id).parent();
  265. __active_size.addClass("active");
  266. }
  267. function select_buffer(buffer_time) {
  268. var bt = buffer_time;
  269. var bt_id = "#btn_bt_" + bt.toFixed(1).replace(".", "_");
  270. select_buffer_time(bt_id, bt);
  271. }
  272. function select_max_buffer(max_buffer_time) {
  273. var mbt = max_buffer_time;
  274. var mbt_id = "#btn_mbt_" + mbt.toFixed(1).replace(".", "_");
  275. select_max_buffer_time(mbt_id, mbt);
  276. }
  277. var __active_bt = null;
  278. function select_buffer_time(bt_id, buffer_time) {
  279. srs_player.set_bt(buffer_time);
  280. if (__active_bt) {
  281. __active_bt.removeClass("active");
  282. }
  283. __active_bt = $(bt_id).parent();
  284. __active_bt.addClass("active");
  285. select_max_buffer(srs_player.max_buffer_time);
  286. }
  287. var __active_mbt = null;
  288. function select_max_buffer_time(mbt_id, max_buffer_time) {
  289. srs_player.set_mbt(max_buffer_time);
  290. if (__active_mbt) {
  291. __active_mbt.removeClass("active");
  292. }
  293. __active_mbt = $(mbt_id).parent();
  294. __active_mbt.addClass("active");
  295. }
  296. //格式化json显示
  297. function syntaxHighlight(json) {
  298. if (typeof json != 'string') {
  299. json = JSON.stringify(json, undefined, 2);
  300. }
  301. json = json.replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>');
  302. return json.replace(/("(\\u[a-zA-Z0-9]{4}|\\[^u]|[^\\"])*"(\s*:)?|\b(true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?)/g, function(match) {
  303. var cls = 'number';
  304. if (/^"/.test(match)) {
  305. if (/:$/.test(match)) {
  306. cls = 'key';
  307. } else {
  308. cls = 'string';
  309. }
  310. } else if (/true|false/.test(match)) {
  311. cls = 'boolean';
  312. } else if (/null/.test(match)) {
  313. cls = 'null';
  314. }
  315. return '<span class="' + cls + '">' + match + '</span>';
  316. });
  317. }
  318. function http_get(url){
  319. var retdata = null;
  320. console.log("GET", url);
  321. $.ajax({
  322. type : "GET",
  323. async : false,
  324. url : url,
  325. contentType: "text/html",
  326. data : "",
  327. complete : function() {
  328. },
  329. error : function(ret) {
  330. alert("GET 请求失败:" + url);
  331. },
  332. success : function(ret) {
  333. console.log(ret);
  334. //var jdata = JSON.parse(ret);
  335. retdata = ret;//.data;
  336. }
  337. });
  338. return retdata;
  339. }
  340. function refreshSipSessionList(sessionList){
  341. $("#sipSessionList").empty();
  342. for (idx in sessionList.sessions)
  343. {
  344. //href="javascript:void(0)" onclick="fn(this)">
  345. var session = sessionList.sessions[idx];
  346. var id = "id:" +session.id;
  347. var li = "<li><a id='linkChannelId1' href='javascript:void(0)' onclick='sipSessionOnClick(this)'>" +id + "</a></li>";
  348. $("#sipSessionList").append(li);
  349. var devices = session.devices;
  350. for (idx2 in devices)
  351. {
  352. //href="javascript:void(0)" onclick="fn(this)">
  353. var id = "-->" + devices[idx2].device_name + ":" + devices[idx2].device_id + ":" + devices[idx2].device_status + ":" + devices[idx2].invite_status;
  354. var li = "<li><a id='linkChannelId1' href='javascript:void(0)' onclick='sipSessionOnClick(this)' rel='"+ session.id + "'>" +id + "</a></li>";
  355. $("#sipSessionList").append(li);
  356. }
  357. }
  358. //if (sessionList == undefined)
  359. // $("#lab_chlist").text("(0)");
  360. //else
  361. // $("#lab_chlist").text("("+sessionList.length+")");
  362. }
  363. function sipSessionOnClick(chidObj){
  364. id = chidObj.rel + chidObj.text;
  365. if (id.indexOf("id:") != -1) {
  366. var aa = id.split(":")
  367. sessionid = aa[1];
  368. url = $("#txt_api_url").val();
  369. var apiurl = url + "/api/v1/gb28181?action=sip_query_session&id=" + sessionid
  370. var ret = http_get(apiurl);
  371. $('#sipSessionMessage').html(syntaxHighlight(ret));
  372. if (ret.code == 0 && ret.data != undefined ) {
  373. };
  374. }
  375. $("#sipSessionId").text(id);
  376. }
  377. function channelOnClick(chidObj){
  378. id = chidObj.text;
  379. $("#gb28181ChannelId").text(id);
  380. url = $("#txt_api_url").val();
  381. var apiurl = url + "/api/v1/gb28181?action=query_channel&id=" + id
  382. var ret = http_get(apiurl);
  383. $('#gb28181ChannelMessage').html(syntaxHighlight(ret));
  384. if (ret.code == 0 && ret.data != undefined ) {
  385. $("#txt_rtmp_url").val(ret.data.channels[0].flv_url);
  386. ret.data.channels[0].flv_url.split("//")
  387. //var urlObject = parse_rtmp_url(ret.data.channels[0].rtmp_url);
  388. //var werbrtc_url = "webrtc://"+ urlObject.server + "/" + urlObject.app + "/" + urlObject.stream;
  389. $("#txt_rtc_url").val(ret.data.channels[0].webrtc_url);
  390. }
  391. }
  392. function refreshGb28181ChList(gb28181ChList){
  393. $("#gb28181ChList").empty();
  394. for (idx in gb28181ChList.channels)
  395. {
  396. //href="javascript:void(0)" onclick="fn(this)">
  397. var channel = gb28181ChList.channels[idx];
  398. var id = channel.id;
  399. var li = "<li><a id='linkChannelId' href='javascript:void(0)' onclick='channelOnClick(this)'>" +id + "</a></li>";
  400. $("#gb28181ChList").append(li);
  401. }
  402. //if (sessionList == undefined)
  403. // $("#lab_chlist").text("(0)");
  404. //else
  405. // $("#lab_chlist").text("("+sessionList.length+")");
  406. }
  407. // Async-await-promise based SRS RTC Player.
  408. function SrsRtcPlayerAsync() {
  409. var self = {};
  410. // @see https://github.com/rtcdn/rtcdn-draft
  411. // @url The WebRTC url to play with, for example:
  412. // webrtc://r.ossrs.net/live/livestream
  413. // or specifies the API port:
  414. // webrtc://r.ossrs.net:11985/live/livestream
  415. // or autostart the play:
  416. // webrtc://r.ossrs.net/live/livestream?autostart=true
  417. // or change the app from live to myapp:
  418. // webrtc://r.ossrs.net:11985/myapp/livestream
  419. // or change the stream from livestream to mystream:
  420. // webrtc://r.ossrs.net:11985/live/mystream
  421. // or set the api server to myapi.domain.com:
  422. // webrtc://myapi.domain.com/live/livestream
  423. // or set the candidate(ip) of answer:
  424. // webrtc://r.ossrs.net/live/livestream?eip=39.107.238.185
  425. // or force to access https API:
  426. // webrtc://r.ossrs.net/live/livestream?schema=https
  427. // or use plaintext, without SRTP:
  428. // webrtc://r.ossrs.net/live/livestream?encrypt=false
  429. // or any other information, will pass-by in the query:
  430. // webrtc://r.ossrs.net/live/livestream?vhost=xxx
  431. // webrtc://r.ossrs.net/live/livestream?token=xxx
  432. self.play = async function(url) {
  433. var conf = self.__internal.prepareUrl(url);
  434. self.pc.addTransceiver("audio", {direction: "recvonly"});
  435. self.pc.addTransceiver("video", {direction: "recvonly"});
  436. var offer = await self.pc.createOffer();
  437. await self.pc.setLocalDescription(offer);
  438. var session = await new Promise(function(resolve, reject) {
  439. // @see https://github.com/rtcdn/rtcdn-draft
  440. var data = {
  441. api: conf.apiUrl, streamurl: conf.streamUrl, clientip: null, sdp: offer.sdp
  442. };
  443. console.log("Generated offer: ", data);
  444. $.ajax({
  445. type: "POST", url: conf.apiUrl, data: JSON.stringify(data),
  446. contentType:'application/json', dataType: 'json'
  447. }).done(function(data) {
  448. console.log("Got answer: ", data);
  449. if (data.code) {
  450. reject(data); return;
  451. }
  452. resolve(data);
  453. }).fail(function(reason){
  454. reject(reason);
  455. });
  456. });
  457. await self.pc.setRemoteDescription(
  458. new RTCSessionDescription({type: 'answer', sdp: session.sdp})
  459. );
  460. return session;
  461. };
  462. // Close the publisher.
  463. self.close = function() {
  464. self.pc.close();
  465. };
  466. // The callback when got remote stream.
  467. self.onaddstream = function (event) {};
  468. // Internal APIs.
  469. self.__internal = {
  470. defaultPath: '/rtc/v1/play/',
  471. prepareUrl: function (webrtcUrl) {
  472. var urlObject = self.__internal.parse(webrtcUrl);
  473. // If user specifies the schema, use it as API schema.
  474. var schema = urlObject.user_query.schema;
  475. schema = schema ? schema + ':' : window.location.protocol;
  476. var port = urlObject.port || 1985;
  477. if (schema === 'https:') {
  478. port = urlObject.port || 443;
  479. }
  480. // @see https://github.com/rtcdn/rtcdn-draft
  481. var api = urlObject.user_query.play || self.__internal.defaultPath;
  482. if (api.lastIndexOf('/') !== api.length - 1) {
  483. api += '/';
  484. }
  485. apiUrl = schema + '//' + urlObject.server + ':' + port + api;
  486. for (var key in urlObject.user_query) {
  487. if (key !== 'api' && key !== 'play') {
  488. apiUrl += '&' + key + '=' + urlObject.user_query[key];
  489. }
  490. }
  491. // Replace /rtc/v1/play/&k=v to /rtc/v1/play/?k=v
  492. var apiUrl = apiUrl.replace(api + '&', api + '?');
  493. var streamUrl = urlObject.url;
  494. return {apiUrl: apiUrl, streamUrl: streamUrl, schema: schema, urlObject: urlObject, port: port};
  495. },
  496. parse: function (url) {
  497. // @see: http://stackoverflow.com/questions/10469575/how-to-use-location-object-to-parse-url-without-redirecting-the-page-in-javascri
  498. var a = document.createElement("a");
  499. a.href = url.replace("rtmp://", "http://")
  500. .replace("webrtc://", "http://")
  501. .replace("rtc://", "http://");
  502. var vhost = a.hostname;
  503. var app = a.pathname.substr(1, a.pathname.lastIndexOf("/") - 1);
  504. var stream = a.pathname.substr(a.pathname.lastIndexOf("/") + 1);
  505. // parse the vhost in the params of app, that srs supports.
  506. app = app.replace("...vhost...", "?vhost=");
  507. if (app.indexOf("?") >= 0) {
  508. var params = app.substr(app.indexOf("?"));
  509. app = app.substr(0, app.indexOf("?"));
  510. if (params.indexOf("vhost=") > 0) {
  511. vhost = params.substr(params.indexOf("vhost=") + "vhost=".length);
  512. if (vhost.indexOf("&") > 0) {
  513. vhost = vhost.substr(0, vhost.indexOf("&"));
  514. }
  515. }
  516. }
  517. // when vhost equals to server, and server is ip,
  518. // the vhost is __defaultVhost__
  519. if (a.hostname === vhost) {
  520. var re = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
  521. if (re.test(a.hostname)) {
  522. vhost = "__defaultVhost__";
  523. }
  524. }
  525. // parse the schema
  526. var schema = "rtmp";
  527. if (url.indexOf("://") > 0) {
  528. schema = url.substr(0, url.indexOf("://"));
  529. }
  530. var port = a.port;
  531. if (!port) {
  532. if (schema === 'http') {
  533. port = 80;
  534. } else if (schema === 'https') {
  535. port = 443;
  536. } else if (schema === 'rtmp') {
  537. port = 1935;
  538. }
  539. }
  540. var ret = {
  541. url: url,
  542. schema: schema,
  543. server: a.hostname, port: port,
  544. vhost: vhost, app: app, stream: stream
  545. };
  546. self.__internal.fill_query(a.search, ret);
  547. // For webrtc API, we use 443 if page is https, or schema specified it.
  548. if (!ret.port) {
  549. if (schema === 'webrtc' || schema === 'rtc') {
  550. if (ret.user_query.schema === 'https') {
  551. ret.port = 443;
  552. } else if (window.location.href.indexOf('https://') === 0) {
  553. ret.port = 443;
  554. } else {
  555. // For WebRTC, SRS use 1985 as default API port.
  556. ret.port = 1985;
  557. }
  558. }
  559. }
  560. return ret;
  561. },
  562. fill_query: function (query_string, obj) {
  563. // pure user query object.
  564. obj.user_query = {};
  565. if (query_string.length === 0) {
  566. return;
  567. }
  568. // split again for angularjs.
  569. if (query_string.indexOf("?") >= 0) {
  570. query_string = query_string.split("?")[1];
  571. }
  572. var queries = query_string.split("&");
  573. for (var i = 0; i < queries.length; i++) {
  574. var elem = queries[i];
  575. var query = elem.split("=");
  576. obj[query[0]] = query[1];
  577. obj.user_query[query[0]] = query[1];
  578. }
  579. // alias domain for vhost.
  580. if (obj.domain) {
  581. obj.vhost = obj.domain;
  582. }
  583. }
  584. };
  585. self.pc = new RTCPeerConnection(null);
  586. self.pc.onaddstream = function (event) {
  587. if (self.onaddstream) {
  588. self.onaddstream(event);
  589. }
  590. };
  591. return self;
  592. }
  593. var flvPlayer = null;
  594. var hlsPlayer = null;
  595. var stopPlayers = function () {
  596. if (flvPlayer) {
  597. flvPlayer.destroy();
  598. flvPlayer = null;
  599. }
  600. if (hlsPlayer) {
  601. hlsPlayer.destroy();
  602. hlsPlayer = null;
  603. }
  604. };
  605. var hide_for_error = function () {
  606. $('#main_flash_alert').show();
  607. $('#main_info').hide();
  608. $('#main_tips').hide();
  609. $('#video_player').hide();
  610. //$('#btn_play').hide();
  611. stopPlayers();
  612. };
  613. var show_for_ok = function () {
  614. $('#main_flash_alert').hide();
  615. $('#main_info').show();
  616. $('#main_tips').show();
  617. $('#video_player').show();
  618. //$('#btn_play').show();
  619. };
  620. var start_play_live = function (r) {
  621. stopPlayers();
  622. if (!r) return;
  623. // Start play HTTP-FLV.
  624. if (r.stream.indexOf('.flv') > 0) {
  625. if (!flvjs.isSupported()) {
  626. hide_for_error();
  627. return;
  628. }
  629. show_for_ok();
  630. flvPlayer = flvjs.createPlayer({type: 'flv', url: r.url});
  631. flvPlayer.attachMediaElement(document.getElementById('video_player'));
  632. flvPlayer.load();
  633. flvPlayer.play();
  634. return;
  635. }
  636. // Start play HLS.
  637. if (r.stream.indexOf('.m3u8') > 0) {
  638. if (!Hls.isSupported()) {
  639. hide_for_error();
  640. return;
  641. }
  642. show_for_ok();
  643. hlsPlayer = new Hls();
  644. hlsPlayer.loadSource(r.url);
  645. hlsPlayer.attachMedia(document.getElementById('video_player'));
  646. return;
  647. }
  648. console.error('不支持的URL', r.url, r);
  649. $('#video_player').hide();
  650. };
  651. /****
  652. * The parameters for this page:
  653. * schema, the protocol schema, rtmp or http.
  654. * server, the ip of the url.
  655. * port, the rtmp port of url.
  656. * vhost, the vhost of url, can equals to server.
  657. * app, the app of url.
  658. * stream, the stream of url, can endwith .flv or .mp4 or nothing for RTMP.
  659. * autostart, whether auto play the stream.
  660. * buffer, the buffer time in seconds.
  661. * extra params:
  662. * shp_identify, hls+ param.
  663. * for example:
  664. * http://localhost:8088/players/srs_player.html?vhost=ossrs.net&app=live&stream=livestream&server=ossrs.net&port=1935&autostart=true&schema=rtmp
  665. * http://localhost:8088/players/srs_player.html?vhost=ossrs.net&app=live&stream=livestream.flv&server=ossrs.net&port=8080&autostart=true&schema=http
  666. */
  667. var autoLoadPage = function() {
  668. var query = parse_query_string();
  669. // get the vhost and port to set the default url.
  670. // url set to: http://localhost:8080/live/livestream.flv
  671. srs_init_flv("#txt_url", "#main_modal");
  672. srs_init_flv("#txt_url", "#rtc_player_modal");
  673. // consts for buffer and max buffer.
  674. var bts = [0.1, 0.2, 0.3, 0.5, 0.8, 1, 2, 3, 4, 5, 6, 8, 10, 15, 20, 30];
  675. var mbts = [0.6, 0.9, 1.2, 1.5, 2.4, 3, 6, 9, 12, 15, 18, 24, 30, 45, 60, 90];
  676. // the play startup time.
  677. var pst = new Date();
  678. $("#main_modal").on("show", function(){
  679. });
  680. $("#main_modal").on("hide", function(){
  681. });
  682. $("#btn_generate_link").click(function(){
  683. $("#link_modal").modal({show:true, keyboard:true});
  684. });
  685. $("#btn_play").click(function(){
  686. $("#main_modal").modal({show:true, keyboard:true});
  687. var r = parse_rtmp_url($("#txt_rtmp_url").val());
  688. start_play_live(r);
  689. });
  690. if (true) {
  691. for (var i = 0; i < bts.length; i++) {
  692. var bt = bts[i];
  693. var bt_id = "#btn_bt_" + bt.toFixed(1).replace(".", "_");
  694. var bt_fun = function(id, v){
  695. $(bt_id).click(function(){
  696. select_buffer_time(id, v);
  697. // remember the chagned buffer.
  698. if (Number(query.buffer) != srs_player.buffer_time) {
  699. query.buffer = srs_player.buffer_time;
  700. apply_url_change();
  701. }
  702. });
  703. };
  704. bt_fun(bt_id, bt);
  705. }
  706. }
  707. if (true) {
  708. for (var i = 0; i < mbts.length; i++) {
  709. var mbt = mbts[i];
  710. var mbt_id = "#btn_mbt_" + mbt.toFixed(1).replace(".", "_");
  711. var mbt_fun = function(id, v){
  712. $(mbt_id).click(function(){
  713. select_max_buffer_time(id, v);
  714. });
  715. };
  716. mbt_fun(mbt_id, mbt);
  717. }
  718. }
  719. if (true){
  720. $("#btn_sip_query_session").click(function(){
  721. url = $("#txt_api_url").val();
  722. $("#txt_api_url").val();
  723. var apiurl = url + "/api/v1/gb28181?action=sip_query_session"
  724. var ret = http_get(apiurl);
  725. $('#sipSessionMessage').html(syntaxHighlight(ret));
  726. if (ret != undefined && ret.code == 0){
  727. refreshSipSessionList(ret.data);
  728. }
  729. });
  730. var time_query = function(){
  731. $("#btn_sip_query_session").click();
  732. setTimeout(function () {$("#btn_sip_query_session").click()}, 1000);
  733. }
  734. $("#btn_sip_unregister").click(function(){
  735. var id = $("#sipSessionId").text();
  736. if (id.indexOf("id:") != -1) {
  737. var str = id.split(":")
  738. url = $("#txt_api_url").val();
  739. var apiurl = url + "/api/v1/gb28181?action=sip_unregister&id=" + str[1];
  740. var ret = http_get(apiurl);
  741. $('#sipSessionMessage').html(syntaxHighlight(ret));
  742. if (ret != undefined && ret.code == 0){
  743. time_query();
  744. }
  745. }
  746. });
  747. $("#btn_sip_invite").click(function(){
  748. var text = $("#sipSessionId").text();
  749. if (text.indexOf("-->") != -1) {
  750. var str = text.split("-->");
  751. id = str[0];
  752. var str2 = str[1].split(":")
  753. chid = str2[1];
  754. url = $("#txt_api_url").val();
  755. var apiurl = url + "/api/v1/gb28181?action=sip_invite&id=" + id + "&chid="+chid;
  756. var ret = http_get(apiurl);
  757. $('#sipSessionMessage').html(syntaxHighlight(ret));
  758. if (ret != undefined && ret.code == 0){
  759. time_query();
  760. }
  761. }
  762. });
  763. $("#btn_sip_bye").click(function(){
  764. var text = $("#sipSessionId").text();
  765. if (text.indexOf("-->") != -1) {
  766. var str = text.split("-->");
  767. id = str[0];
  768. var str2 = str[1].split(":")
  769. chid = str2[1];
  770. url = $("#txt_api_url").val();
  771. var apiurl = url + "/api/v1/gb28181?action=sip_bye&id=" + id + "&chid="+chid;
  772. var ret = http_get(apiurl);
  773. $('#sipSessionMessage').html(syntaxHighlight(ret));
  774. if (ret != undefined && ret.code == 0){
  775. time_query();
  776. }
  777. }
  778. });
  779. $("#btn_sip_querycatalog").click(function(){
  780. var text = $("#sipSessionId").text();
  781. if (text.indexOf("-->") != -1) {
  782. var str = text.split("-->");
  783. id = str[0];
  784. var str2 = str[1].split(":")
  785. chid = str2[0];
  786. url = $("#txt_api_url").val();
  787. var apiurl = url + "/api/v1/gb28181?action=sip_query_catalog&id=" + id;
  788. var ret = http_get(apiurl);
  789. $('#sipSessionMessage').html(syntaxHighlight(ret));
  790. if (ret != undefined && ret.code == 0){
  791. time_query();
  792. }
  793. }
  794. });
  795. $("#btn_query_channel").click(function(){
  796. url = $("#txt_api_url").val();
  797. var apiurl = url + "/api/v1/gb28181?action=query_channel"
  798. var ret = http_get(apiurl);
  799. $('#gb28181ChannelMessage').html(syntaxHighlight(ret));
  800. if (ret != undefined && ret.code == 0){
  801. refreshGb28181ChList(ret.data);
  802. }
  803. });
  804. $("#btn_delete_channel").click(function(){
  805. var str = $("#gb28181ChannelId").text();
  806. var str_array = str.split("@")
  807. var chid = "";
  808. var id = "";
  809. if (str_array.length != 2){
  810. return;
  811. }
  812. id = str_array[0];
  813. chid = str_array[1];
  814. url = $("#txt_api_url").val();
  815. var apiurl = url + "/api/v1/gb28181?action=delete_channel&id=" + id + "&chid="+chid;
  816. var ret = http_get(apiurl);
  817. $('#gb28181ChannelMessage').html(syntaxHighlight(ret));
  818. if (ret != undefined && ret.code == 0){
  819. $("#btn_query_channel").click();
  820. }
  821. });
  822. var call_ptz_cmd = function(cmd) {
  823. var str = $("#gb28181ChannelId").text();
  824. var str_array = str.split("@")
  825. var chid = "";
  826. var id = "";
  827. if (str_array.length < 1){
  828. return;
  829. }
  830. var speed = "136";
  831. id = str_array[0];
  832. chid = str_array[1];
  833. url = $("#txt_api_url").val();
  834. var apiurl = url + "/api/v1/gb28181?action=sip_ptz&id=" + id + "&chid="+chid+ "&ptzcmd="+cmd + "&speed=" + speed;
  835. var ret = http_get(apiurl);
  836. $('#gb28181ChannelMessage').html(syntaxHighlight(ret));
  837. };
  838. var ptz_cmd = ["up", "down", "right", "left", "zoomin", "zoomout"]
  839. for (var i=0; i<ptz_cmd.length; i++){
  840. var bt_fun = function(id, cmd){
  841. $(bt_id).mousedown(function(){
  842. call_ptz_cmd(cmd);
  843. });
  844. $(bt_id).mouseup(function(){
  845. call_ptz_cmd("stop");
  846. });
  847. };
  848. var bt_id = "#btn_ptz_"+ptz_cmd[i]+ "_rtc";
  849. bt_fun(bt_id, ptz_cmd[i]);
  850. bt_id = "#btn_ptz_"+ptz_cmd[i];
  851. bt_fun(bt_id, ptz_cmd[i]);
  852. }
  853. $("#btn_create_channel").click(function(){
  854. $("#create_channel_modal").modal({show: true, keyboard: false});
  855. });
  856. $("#btn_channel_cancel").click(function(){
  857. $("#create_channel_modal").modal('hide');
  858. });
  859. $("#btn_channel_submit").click(function(){
  860. var chid = $("#txt_channel_id").val();
  861. var app = $("#txt_app").val();
  862. var stream = $("#txt_stream").val();
  863. var port_mode = $("#sel_ch_mode_type").val();
  864. if (chid == ""){
  865. alert("通道id不能为空")
  866. return
  867. }
  868. url = $("#txt_api_url").val();
  869. var apiurl = url + "/api/v1/gb28181?action=create_channel&id=" + chid + "&app=" + app + "&stream=" + stream + "&port_mode="+ port_mode
  870. var ret = http_get(apiurl);
  871. $('#gb28181ChannelMessage').html(syntaxHighlight(ret));
  872. if (ret != undefined && ret.code == 0){
  873. $("#btn_query_channel").click();
  874. }
  875. $("#create_channel_modal").modal('hide');
  876. });
  877. var sdk = null; // Global handler to do cleanup when replaying.
  878. var startPlay = function() {
  879. $('#rtc_media_player').show();
  880. // Close PC when user replay.
  881. if (sdk) {
  882. sdk.close();
  883. }
  884. sdk = new SrsRtcPlayerAsync();
  885. sdk.onaddstream = function (event) {
  886. console.log('Start play, event: ', event);
  887. $('#rtc_media_player').prop('srcObject', event.stream);
  888. };
  889. // For example:
  890. // webrtc://r.ossrs.net/live/livestream
  891. var url = $("#txt_rtc_url").val();
  892. sdk.play(url).then(function(session){
  893. $('#sessionid').html(session.sessionid);
  894. $('#simulator-drop').attr('href', session.simulator + '?drop=1&username=' + session.sessionid);
  895. }).catch(function (reason) {
  896. sdk.close();
  897. $('#rtc_media_player').hide();
  898. console.error(reason);
  899. });
  900. };
  901. $("#btn_rtc_play").click(function(){
  902. $('#rtc_media_player').width(srs_get_player_width);
  903. $('#rtc_media_player').height(srs_get_player_height);
  904. $("#rtc_player_modal").modal({show: true, keyboard: false});
  905. startPlay();
  906. });
  907. $("#rtc_player_modal").on("hide", function(){
  908. if (sdk) {
  909. sdk.close();
  910. }
  911. });
  912. }
  913. };
  914. </script>
  915. </html>