srs_chat.html 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  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. .accordion-group {
  12. width: 310px;
  13. }
  14. </style>
  15. </head>
  16. <body>
  17. <div class="navbar navbar-fixed-top">
  18. <div class="navbar-inner">
  19. <div class="container">
  20. <a id="srs_index" class="brand" href="#">SRS</a>
  21. <div class="nav-collapse collapse">
  22. <ul class="nav">
  23. <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
  24. <li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>
  25. <li class="active"><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>
  26. <li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>
  27. <li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li>
  28. <li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li>
  29. <li><a id="nav_vlc" href="vlc.html">VLC播放器</a></li>
  30. </ul>
  31. </div>
  32. </div>
  33. </div>
  34. </div>
  35. <div class="container">
  36. <!-- for the log -->
  37. <div class="alert alert-info fade in" id="txt_log">
  38. <button type="button" class="close" data-dismiss="alert">×</button>
  39. <strong><span id="txt_log_title">Usage:</span></strong>
  40. <span id="txt_log_msg">输入名字,设点“加入会议”按钮</span>
  41. </div>
  42. <div class="control-group">
  43. <div class="form-inline">
  44. <button class="btn input-small" id="btn_video_settings">摄像头</button>
  45. <button class="btn input-small" id="btn_audio_settings">麦克风</button>
  46. <input type="text" id="txt_name" class="input-large" placeholder="请输入您的名字..." value=""></input>
  47. <button class="btn input-small" id="btn_join">加入会议</button>
  48. <input type="text" id="txt_url" class="input-mini hide" value=""></input>
  49. </div>
  50. </div>
  51. <table id="lst_chats" class="table">
  52. <tr>
  53. <td id="td_0">
  54. <div class="accordion-group">
  55. <div class="accordion-heading">
  56. <span class="accordion-toggle">
  57. <strong>[我的] 本地摄像头</strong>
  58. </span>
  59. </div>
  60. <div class="accordion-body collapse in">
  61. <div class="accordion-inner">
  62. <div id="local_publisher"></div>
  63. </div>
  64. </div>
  65. </div>
  66. </td>
  67. <td id="td_1">
  68. <div class="accordion-group">
  69. <div class="accordion-heading">
  70. <span class="accordion-toggle">
  71. <strong>[我的] 远程服务器流</strong>
  72. <a id="realtime_player_url" href="#" data-toggle="tooltip" data-placement="top" title="">
  73. 播放地址<img src="img/tooltip.png"/>
  74. </a>
  75. </span>
  76. </div>
  77. <div class="accordion-body collapse in">
  78. <div class="accordion-inner">
  79. <div id="realtime_player"></div>
  80. </div>
  81. </div>
  82. </div>
  83. </td>
  84. <td id="td_2"></td>
  85. </tr>
  86. </table>
  87. <div class="container hide" id="template">
  88. <div class="accordion-group" id="collapse_main">
  89. <div class="accordion-heading" title="点击展开或收起,收起后停止播放流,展开时从服务器请求流">
  90. <span id="headerN" class="accordion-toggle" data-toggle="collapse" href="#collapseN">
  91. <strong>[<a href="#"><span id="user_name">XX</span></a>]</strong>
  92. <strong>加入时间</strong>[<span id="join_date"></span>]
  93. <a id="user_player_url" href="#" data-toggle="tooltip" data-placement="top" title="">
  94. 播放地址<img src="img/tooltip.png"/>
  95. </a>
  96. </span>
  97. </div>
  98. <div id="collapseM" class="accordion-body collapse in">
  99. <div class="accordion-inner">
  100. <div id="chat_player">
  101. <div id="chat_player_raw">
  102. </div>
  103. </div>
  104. </div>
  105. </div>
  106. </div>
  107. </div>
  108. <table class="table">
  109. </table>
  110. <div id="video_modal" class="modal hide fade">
  111. <div class="modal-header">
  112. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  113. <h3>视频编码</h3>
  114. </div>
  115. <div class="modal-body">
  116. <div class="form-horizontal">
  117. <div class="control-group">
  118. <label class="control-label" for="sl_cameras">
  119. 摄像头
  120. <a id="sl_cameras_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  121. <img src="img/tooltip.png"/>
  122. </a>
  123. </label>
  124. <div class="controls">
  125. <select class="span4" id="sl_cameras"></select>
  126. </div>
  127. </div>
  128. <div class="control-group">
  129. <label class="control-label" for="sl_vcodec">
  130. Codec
  131. <a id="sl_cameras_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  132. <img src="img/tooltip.png"/>
  133. </a>
  134. </label>
  135. <div class="controls">
  136. <select class="span2" id="sl_vcodec"></select>
  137. </div>
  138. </div>
  139. <div class="control-group">
  140. <label class="control-label" for="sl_profile">
  141. Profile
  142. <a id="sl_profile_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  143. <img src="img/tooltip.png"/>
  144. </a>
  145. </label>
  146. <div class="controls">
  147. <select class="span2" id="sl_profile"></select>
  148. </div>
  149. </div>
  150. <div class="control-group">
  151. <label class="control-label" for="sl_level">
  152. Level
  153. <a id="sl_level_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  154. <img src="img/tooltip.png"/>
  155. </a>
  156. </label>
  157. <div class="controls">
  158. <select class="span2" id="sl_level"></select>
  159. </div>
  160. </div>
  161. <div class="control-group">
  162. <label class="control-label" for="sl_gop">
  163. GOP
  164. <a id="sl_gop_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  165. <img src="img/tooltip.png"/>
  166. </a>
  167. </label>
  168. <div class="controls">
  169. <select class="span2" id="sl_gop"></select>
  170. </div>
  171. </div>
  172. <div class="control-group">
  173. <label class="control-label" for="sl_size">
  174. 尺寸
  175. <a id="sl_size_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  176. <img src="img/tooltip.png"/>
  177. </a>
  178. </label>
  179. <div class="controls">
  180. <select class="span2" id="sl_size"></select>
  181. </div>
  182. </div>
  183. <div class="control-group">
  184. <label class="control-label" for="sl_fps">
  185. 帧率
  186. <a id="sl_fps_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  187. <img src="img/tooltip.png"/>
  188. </a>
  189. </label>
  190. <div class="controls">
  191. <select class="span2" id="sl_fps"></select>
  192. </div>
  193. </div>
  194. <div class="control-group">
  195. <label class="control-label" for="sl_bitrate">
  196. 码率
  197. <a id="sl_bitrate_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  198. <img src="img/tooltip.png"/>
  199. </a>
  200. </label>
  201. <div class="controls">
  202. <select class="span2" id="sl_bitrate"></select>
  203. </div>
  204. </div>
  205. </div>
  206. </div>
  207. <div class="modal-footer">
  208. <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">设置</button>
  209. </div>
  210. </div>
  211. <div id="audio_modal" class="modal hide fade">
  212. <div class="modal-header">
  213. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  214. <h3>音频编码</h3>
  215. </div>
  216. <div class="modal-body">
  217. <div class="form-horizontal">
  218. <div class="control-group">
  219. <label class="control-label" for="sl_microphones">
  220. 麦克风
  221. <a id="worker_id_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  222. <img src="img/tooltip.png"/>
  223. </a>
  224. </label>
  225. <div class="controls">
  226. <select class="span4" id="sl_microphones"></select>
  227. </div>
  228. </div>
  229. <div class="control-group">
  230. <label class="control-label" for="sl_acodec">
  231. 编码
  232. <a id="sl_acodec_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  233. <img src="img/tooltip.png"/>
  234. </a>
  235. </label>
  236. <div class="controls">
  237. <select class="span2" id="sl_acodec"></select>
  238. </div>
  239. </div>
  240. </div>
  241. </div>
  242. <div class="modal-footer">
  243. <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">设置</button>
  244. </div>
  245. </div>
  246. <hr/>
  247. <footer>
  248. <p><a href="https://github.com/ossrs/srs">SRS Team &copy; 2013</a></p>
  249. </footer>
  250. </div>
  251. </body>
  252. <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
  253. <script type="text/javascript" src="js/bootstrap.min.js"></script>
  254. <script type="text/javascript" src="js/swfobject.js"></script>
  255. <script type="text/javascript" src="js/json2.js"></script>
  256. <script type="text/javascript" src="js/srs.page.js"></script>
  257. <script type="text/javascript" src="js/srs.log.js"></script>
  258. <script type="text/javascript" src="js/srs.player.js"></script>
  259. <script type="text/javascript" src="js/srs.publisher.js"></script>
  260. <script type="text/javascript" src="js/srs.utility.js"></script>
  261. <script type="text/javascript" src="js/winlin.utility.js"></script>
  262. <script type="text/javascript">
  263. var srs_publisher = null;
  264. var realtime_player = null;
  265. var api_server = null;
  266. var self_chat = null;
  267. var global_chat_user_id = 200;
  268. var previous_chats = [];
  269. var no_play = false;
  270. var query = parse_query_string();
  271. $(function(){
  272. // get the vhost and port to set the default url.
  273. // for example: http://192.168.1.213/players/jwplayer6.html?port=1935&vhost=demo
  274. // url set to: rtmp://demo:1935/live/livestream
  275. srs_init_publish("#txt_url");
  276. // support 5x3+1 users
  277. for (var i = 0; i < 5; i++) {
  278. var tr = $("<tr></tr>").hide();
  279. $("#lst_chats").append(tr);
  280. for (var j = 0; j < 3; j++) {
  281. tr.append($("<td></td>").attr("id", "td_" + ((i+1) * 8 + j)));
  282. }
  283. }
  284. // remove border of row.
  285. $("#lst_chats").find("td").css("border", "none").css("padding", "2px")
  286. .css("padding-left", "0px").css("width", "327px");
  287. if (query.agent == "true") {
  288. document.write(navigator.userAgent);
  289. return;
  290. }
  291. $("#realtime_player_url").tooltip({
  292. title: "右键复制RTMP地址"
  293. });
  294. // if no play specified, donot show the player, for debug the publisher.
  295. if (query.no_play == "true") {
  296. no_play = true;
  297. }
  298. $("#btn_video_settings").click(function(){
  299. $("#video_modal").modal({show:true});
  300. });
  301. $("#btn_audio_settings").click(function(){
  302. $("#audio_modal").modal({show:true});
  303. });
  304. $("#btn_join").click(on_user_publish);
  305. // for publish, we use randome stream name.
  306. $("#txt_url").val($("#txt_url").val() + "." + new Date().getTime());
  307. // start the publisher.
  308. srs_publisher = new SrsPublisher("local_publisher", 280, 180);
  309. srs_publisher.on_publisher_ready = function(cameras, microphones) {
  310. srs_chat_initialize_page(
  311. cameras, microphones,
  312. "#sl_cameras", "#sl_microphones",
  313. "#sl_vcodec", "#sl_profile", "#sl_level", "#sl_gop", "#sl_size",
  314. "#sl_fps", "#sl_bitrate",
  315. "#sl_acodec"
  316. );
  317. };
  318. srs_publisher.on_publisher_error = function(code, desc) {
  319. if (!on_publish_stop()) {
  320. return;
  321. }
  322. error(code, desc + "请重试。");
  323. };
  324. srs_publisher.on_publisher_warn = function(code, desc) {
  325. warn(code, desc);
  326. };
  327. srs_publisher.start();
  328. update_play_url();
  329. if (!no_play) {
  330. // start the realtime player.
  331. realtime_player = new SrsPlayer("realtime_player", 280, 180);
  332. realtime_player.on_player_ready = function() {
  333. this.set_bt(0.5);
  334. };
  335. realtime_player.on_player_metadata = function(metadata) {
  336. this.set_dar(0, 0);
  337. this.set_fs("screen", 100);
  338. info("推流到服务器成功。请戴耳机聊天,否则音箱的声音会进入麦克风造成回声。");
  339. }
  340. realtime_player.start();
  341. }
  342. $("#txt_name").focus();
  343. api_server = "http://" + query.hostname + ":" + srs_get_api_server_port() + "/api/v1/chats";
  344. refresh();
  345. });
  346. function on_publish_stop() {
  347. if (!srs_can_republish()) {
  348. $("#btn_join").attr("disabled", true);
  349. error(0, "您使用的浏览器很弱,请关闭页面后重新打开页面(刷新也不管用)。<br/>推荐使用Chrome/Firefox/Safari/Opera浏览器,支持重试");
  350. srs_log_disabled = true;
  351. return false;
  352. }
  353. return true;
  354. }
  355. function update_play_url() {
  356. var url = $("#txt_url").val();
  357. $("#realtime_player_url").attr("href", url).attr("target", "_blank");
  358. }
  359. function refresh() {
  360. if (!self_chat) {
  361. setTimeout(refresh, 1000);
  362. return;
  363. }
  364. $.ajax({
  365. type : "GET",
  366. async : true,
  367. url : api_server,
  368. contentType: "text/html",
  369. data : "",
  370. dataType : "json",
  371. complete : function() {
  372. },
  373. error : function(ret) {
  374. setTimeout(refresh, 5000);
  375. warn(101, "查询会议室失败:" + JSON.stringify(ret));
  376. },
  377. success : function(ret) {
  378. if(0 != ret["code"]) {
  379. warn(102, "查询会议室失败: " + JSON.stringify(ret));
  380. setTimeout(refresh, 5000);
  381. return;
  382. }
  383. var chats = ret["data"]["chats"];
  384. var server_time = ret["now"];
  385. on_get_chats(chats);
  386. setTimeout(refresh, 5000);
  387. }
  388. });
  389. }
  390. function on_get_chats(chats) {
  391. if (!self_chat) {
  392. return;
  393. }
  394. // get self, check self is valid?
  395. var _self_chat = null;
  396. for (var i = 0; i < chats.length; i++) {
  397. var chat = chats[i];
  398. if (self_chat && self_chat.id == chat.id) {
  399. _self_chat = chat;
  400. break;
  401. }
  402. }
  403. // rejoin if invalid.
  404. if (!_self_chat) {
  405. on_user_exit_chat(function(){
  406. on_user_join_chat(function(){
  407. info("重新加入会议室成功");
  408. });
  409. });
  410. return;
  411. }
  412. render_chat_room(chats);
  413. if (!self_chat) {
  414. return;
  415. }
  416. // update self heartbeat.
  417. var url = api_server + "/" + self_chat.id;
  418. var chat = {};
  419. chat.localtime = new Date().getTime();
  420. // publish to api server to requires an id.
  421. $.ajax({
  422. type : "PUT",
  423. async : true,
  424. url : url,
  425. contentType: "text/html",
  426. data : JSON.stringify(chat),
  427. dataType : "json",
  428. complete : function() {
  429. },
  430. error : function(ret) {
  431. warn(105, "更新会议室信息失败:" + JSON.stringify(ret));
  432. },
  433. success : function(ret) {
  434. if(0 != ret["code"]) {
  435. warn(106, "更新会议室信息失败:: " + JSON.stringify(ret));
  436. return;
  437. }
  438. }
  439. });
  440. }
  441. function render_chat_room(original_chats) {
  442. if (!self_chat) {
  443. return;
  444. }
  445. var chats = [];
  446. for (var i = 0; i < original_chats.length; i++) {
  447. var chat = original_chats[i];
  448. // ignore the self.
  449. if (self_chat && self_chat.id == chat.id) {
  450. continue;
  451. }
  452. chats.push(chat);
  453. }
  454. // new added chat
  455. for (var i = 0; i < chats.length; i++) {
  456. var chat = chats[i];
  457. // if previous exists, ignore, only add new here.
  458. var previous_chat = get_previous_chat_user(previous_chats, chat.id);
  459. if (previous_chat) {
  460. // update reference.
  461. chat.ui = previous_chat.ui;
  462. chat.parent = previous_chat.parent;
  463. chat.player = previous_chat.player;
  464. if (chat.player) {
  465. chat.player.private_object = chat;
  466. }
  467. continue;
  468. }
  469. }
  470. // removed chat
  471. for (var i = 0; i < previous_chats.length; i++) {
  472. var chat = previous_chats[i];
  473. var new_chat = get_previous_chat_user(chats, chat.id);
  474. if (new_chat) {
  475. continue;
  476. }
  477. if (chat.player) {
  478. chat.player.stop();
  479. }
  480. $("#div_" + chat.id).remove();
  481. }
  482. // hide empty rows.
  483. $("#lst_chats").find("tr").each(function(){
  484. var empty = true;
  485. $(this).find("td").each(function(){
  486. if ($(this).html() != "") {
  487. empty = false;
  488. return false; // abort each
  489. }
  490. return true;
  491. });
  492. if (empty) {
  493. $(this).hide();
  494. }
  495. });
  496. // render the chat
  497. for (var i = 0; i < chats.length; i++) {
  498. var chat = chats[i];
  499. // if redered, ignore.
  500. if (chat.parent) {
  501. continue;
  502. }
  503. // generate the ui of chat
  504. if (!chat.ui) {
  505. global_chat_user_id++;
  506. // username: a str indicates the user name.
  507. // url: a str indicates the url of user stream.
  508. // join_date: a str indicates the join timestamp in seconds.
  509. // join_date_str: friendly formated time.
  510. var obj = $("<div/>").html($("#template").html());
  511. if (true) {
  512. // save current ui object to the chat.
  513. chat.ui = obj;
  514. $(obj).attr("chat_id", chat.id);
  515. $(obj).attr("id", "div_" + chat.id); // for specifed chat: $("#div_" + chat_id)
  516. $(obj).attr("class", "div_chat"); // for all chats: $(".div_chat")
  517. $(obj).find("#chat_player").attr("id", "rp_" + chat.id); // for specifed player: $("#rp_" + chat_id)
  518. $(obj).find("#chat_player_raw").attr("id", "rp_raw_" + chat.id); // for specifed player: $("#rp_raw_" + chat_id)
  519. $(obj).find("#user_name").text(chat.username);
  520. $(obj).find("#user_player_url").attr("href", chat.url);
  521. $(obj).find("#join_date").text(chat.join_date_str.split(" ")[1]);
  522. $(obj).find("#collapseM").attr("id", "collapse_" + global_chat_user_id);
  523. $(obj).find("#headerN").attr("href", "#collapse_" + global_chat_user_id);
  524. }
  525. }
  526. // find a idle td to render the chat.
  527. var parent = null;
  528. $("#lst_chats").find("td").each(function(){
  529. if ($(this).html() != "") {
  530. return true;
  531. }
  532. parent = $(this);
  533. return false; // abort each
  534. });
  535. if (!parent) {
  536. warn("没有可用的位置展示流。");
  537. break;
  538. }
  539. $(parent).append(chat.ui);
  540. $(parent).parent().show();
  541. // when ui elements appent to the page,
  542. // create the player, or flash will failed.
  543. if (!chat.parent) {
  544. chat.parent = $(parent);
  545. if (!no_play) {
  546. // start the realtime player.
  547. var _player = new SrsPlayer("rp_raw_" + chat.id, 240, 180, chat);
  548. _player.on_player_ready = function() {
  549. this.set_bt(0.5);
  550. this.play();
  551. };
  552. _player.on_player_metadata = function(metadata) {
  553. this.set_dar(0, 0);
  554. this.set_fs("screen", 100);
  555. }
  556. _player.start(chat.url);
  557. chat.player = _player;
  558. } else {
  559. chat.player = null;
  560. }
  561. $(obj).find("#collapse_main").on('hidden', function(){
  562. var id = $(this).parent().attr("chat_id");
  563. var chat = get_previous_chat_user(previous_chats, id);
  564. if (!chat || !chat.player) {
  565. return;
  566. }
  567. chat.player.stop();
  568. });
  569. $(obj).find("#collapse_main").on('shown', function(){
  570. var id = $(this).parent().attr("chat_id");
  571. var chat = get_previous_chat_user(previous_chats, id);
  572. if (!chat || !chat.player) {
  573. return;
  574. }
  575. chat.player.play();
  576. });
  577. }
  578. }
  579. previous_chats = chats;
  580. }
  581. function get_previous_chat_user(arr, id) {
  582. for (var i = 0; i < arr.length; i++) {
  583. var chat = arr[i];
  584. if (id == chat.id) {
  585. return chat;
  586. }
  587. }
  588. return null;
  589. }
  590. function on_user_publish() {
  591. if ($("#txt_name").val() == "") {
  592. $("#txt_name").focus().parent().parent().addClass("error");
  593. warn(100, "请输入您的名字");
  594. return;
  595. }
  596. $("#txt_name").parent().parent().removeClass("error");
  597. // join chat.
  598. if (!self_chat) {
  599. on_user_join_chat();
  600. } else {
  601. on_user_exit_chat();
  602. }
  603. }
  604. function on_user_exit_chat(complete_pfn) {
  605. srs_publisher.stop();
  606. $("#btn_join").text("加入会议");
  607. if (realtime_player) {
  608. realtime_player.stop();
  609. }
  610. if (!self_chat) {
  611. return;
  612. }
  613. // removed chat
  614. for (var i = 0; i < previous_chats.length; i++) {
  615. var chat = previous_chats[i];
  616. if (chat.player) {
  617. chat.player.stop();
  618. }
  619. $("#div_" + chat.id).remove();
  620. }
  621. previous_chats = [];
  622. var url = api_server + "/" + self_chat.id;
  623. // whatever, cleanup local chat.
  624. self_chat = null;
  625. $("#btn_join").attr("disabled", true);
  626. // publish to api server to requires an id.
  627. $.ajax({
  628. type : "DELETE",
  629. async : true,
  630. url : url,
  631. contentType: "text/html",
  632. data : "",
  633. dataType : "json",
  634. complete : function() {
  635. if (!on_publish_stop()) {
  636. return;
  637. }
  638. $("#btn_join").attr("disabled", false);
  639. if (complete_pfn) {
  640. complete_pfn();
  641. }
  642. },
  643. error : function(ret) {
  644. warn(103, "退出会议室失败");
  645. },
  646. success : function(ret) {
  647. if(0 != ret["code"]) {
  648. warn(104, "退出会议室失败");
  649. return;
  650. }
  651. info("退出会议室成功");
  652. }
  653. });
  654. }
  655. function on_user_join_chat(complete_pfn) {
  656. if (self_chat) {
  657. return;
  658. }
  659. var url = $("#txt_url").val();
  660. var vcodec = {};
  661. var acodec = {};
  662. srs_publiser_get_codec(
  663. vcodec, acodec,
  664. "#sl_cameras", "#sl_microphones",
  665. "#sl_vcodec", "#sl_profile", "#sl_level", "#sl_gop", "#sl_size",
  666. "#sl_fps", "#sl_bitrate",
  667. "#sl_acodec"
  668. );
  669. var chat = {};
  670. chat.id = -1;
  671. chat.username = $("#txt_name").val();
  672. chat.agent = navigator.userAgent;
  673. chat.url = url;
  674. chat.vcodec = vcodec;
  675. chat.acodec = acodec;
  676. $("#btn_join").attr("disabled", true);
  677. // publish to api server to requires an id.
  678. $.ajax({
  679. type : "POST",
  680. async : true,
  681. url : api_server,
  682. contentType: "text/html",
  683. data : JSON.stringify(chat),
  684. dataType : "json",
  685. complete : function() {
  686. $("#btn_join").attr("disabled", false);
  687. if (complete_pfn) {
  688. complete_pfn();
  689. }
  690. },
  691. error : function(ret) {
  692. warn(105, "创建会议室失败:" + JSON.stringify(ret));
  693. },
  694. success : function(ret) {
  695. if(0 != ret["code"]) {
  696. warn(106, "创建会议室失败: " + JSON.stringify(ret));
  697. return;
  698. }
  699. chat.id = ret["data"];
  700. // success, start publish.
  701. self_chat = chat;
  702. $("#btn_join").text("退出会议");
  703. info("开始推流到服务器。请戴耳机聊天,否则音箱的声音会进入麦克风造成回声。");
  704. srs_publisher.publish(url, vcodec, acodec);
  705. if (realtime_player) {
  706. // directly play the url for the realtime player.
  707. realtime_player.stop();
  708. realtime_player.play(url, 0);
  709. }
  710. }
  711. });
  712. }
  713. </script>
  714. </html>