srs_publisher.html 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469
  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. </style>
  12. </head>
  13. <body>
  14. <div class="navbar navbar-fixed-top">
  15. <div class="navbar-inner">
  16. <div class="container">
  17. <a id="srs_index" class="brand" href="#">SRS</a>
  18. <div class="nav-collapse collapse">
  19. <ul class="nav">
  20. <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
  21. <li class="active"><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>
  22. <li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>
  23. <li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>
  24. <li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li>
  25. <li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li>
  26. <li><a id="nav_vlc" href="vlc.html">VLC播放器</a></li>
  27. </ul>
  28. </div>
  29. </div>
  30. </div>
  31. </div>
  32. <div class="container">
  33. <div class="alert alert-info fade in" id="txt_log">
  34. <button type="button" class="close" data-dismiss="alert">×</button>
  35. <strong><span id="txt_log_title">Usage:</span></strong>
  36. <span id="txt_log_msg">设置编码参数,点“发布视频”,允许Flash访问摄像头即可推流</span>
  37. </div>
  38. <div class="control-group">
  39. <div class="form-inline">
  40. <button class="btn" id="btn_video_settings">视频编码配置</button>
  41. <button class="btn" id="btn_audio_settings">音频编码配置</button>
  42. </div>
  43. </div>
  44. <div class="control-group">
  45. <div class="form-inline">
  46. 发布地址:
  47. <input type="text" id="txt_url" class="input-xxlarge" value=""></input>
  48. <button class="btn btn-primary" id="btn_publish">发布视频</button>
  49. </div>
  50. </div>
  51. <div class="control-group">
  52. <div class="form-inline">
  53. 播放地址
  54. 1.<a id="txt_play_realtime" class="input-xxlarge" href="#">RTMP低延时(请发布视频)</a>
  55. 2.<a id="txt_play_url" class="input-xxlarge" href="#">RTMP已转码(请发布视频)</a>
  56. 3.<a id="txt_play_hls" class="input-xxlarge" href="#">HLS-m3u8(请发布视频)</a>
  57. 4.<a id="txt_play_jwplayer" class="input-xxlarge" href="#">HLS-JWPlayer(请发布视频)</a>
  58. </div>
  59. </div>
  60. <div id="video_modal" class="modal hide fade">
  61. <div class="modal-header">
  62. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  63. <h3>视频编码</h3>
  64. </div>
  65. <div class="modal-body">
  66. <div class="form-horizontal">
  67. <div class="control-group">
  68. <label class="control-label" for="sl_cameras">
  69. 摄像头
  70. <a id="sl_cameras_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  71. <img src="img/tooltip.png"/>
  72. </a>
  73. </label>
  74. <div class="controls">
  75. <select class="span4" id="sl_cameras"></select>
  76. </div>
  77. </div>
  78. <div class="control-group">
  79. <label class="control-label" for="sl_vcodec">
  80. Codec
  81. <a id="sl_cameras_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  82. <img src="img/tooltip.png"/>
  83. </a>
  84. </label>
  85. <div class="controls">
  86. <select class="span2" id="sl_vcodec"></select>
  87. </div>
  88. </div>
  89. <div class="control-group">
  90. <label class="control-label" for="sl_profile">
  91. Profile
  92. <a id="sl_profile_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  93. <img src="img/tooltip.png"/>
  94. </a>
  95. </label>
  96. <div class="controls">
  97. <select class="span2" id="sl_profile"></select>
  98. </div>
  99. </div>
  100. <div class="control-group">
  101. <label class="control-label" for="sl_level">
  102. Level
  103. <a id="sl_level_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  104. <img src="img/tooltip.png"/>
  105. </a>
  106. </label>
  107. <div class="controls">
  108. <select class="span2" id="sl_level"></select>
  109. </div>
  110. </div>
  111. <div class="control-group">
  112. <label class="control-label" for="sl_gop">
  113. GOP
  114. <a id="sl_gop_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  115. <img src="img/tooltip.png"/>
  116. </a>
  117. </label>
  118. <div class="controls">
  119. <select class="span2" id="sl_gop"></select>
  120. </div>
  121. </div>
  122. <div class="control-group">
  123. <label class="control-label" for="sl_size">
  124. 尺寸
  125. <a id="sl_size_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  126. <img src="img/tooltip.png"/>
  127. </a>
  128. </label>
  129. <div class="controls">
  130. <select class="span2" id="sl_size"></select>
  131. </div>
  132. </div>
  133. <div class="control-group">
  134. <label class="control-label" for="sl_fps">
  135. 帧率
  136. <a id="sl_fps_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  137. <img src="img/tooltip.png"/>
  138. </a>
  139. </label>
  140. <div class="controls">
  141. <select class="span2" id="sl_fps"></select>
  142. </div>
  143. </div>
  144. <div class="control-group">
  145. <label class="control-label" for="sl_bitrate">
  146. 码率
  147. <a id="sl_bitrate_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  148. <img src="img/tooltip.png"/>
  149. </a>
  150. </label>
  151. <div class="controls">
  152. <select class="span2" id="sl_bitrate"></select>
  153. </div>
  154. </div>
  155. </div>
  156. </div>
  157. <div class="modal-footer">
  158. <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">设置</button>
  159. </div>
  160. </div>
  161. <div id="audio_modal" class="modal hide fade">
  162. <div class="modal-header">
  163. <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  164. <h3>音频编码</h3>
  165. </div>
  166. <div class="modal-body">
  167. <div class="form-horizontal">
  168. <div class="control-group">
  169. <label class="control-label" for="sl_microphones">
  170. 麦克风
  171. <a id="worker_id_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  172. <img src="img/tooltip.png"/>
  173. </a>
  174. </label>
  175. <div class="controls">
  176. <select class="span4" id="sl_microphones"></select>
  177. </div>
  178. </div>
  179. <div class="control-group">
  180. <label class="control-label" for="sl_acodec">
  181. 编码
  182. <a id="sl_acodec_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  183. <img src="img/tooltip.png"/>
  184. </a>
  185. </label>
  186. <div class="controls">
  187. <select class="span2" id="sl_acodec"></select>
  188. </div>
  189. </div>
  190. </div>
  191. </div>
  192. <div class="modal-footer">
  193. <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">设置</button>
  194. </div>
  195. </div>
  196. <div class="container">
  197. <div class="row-fluid">
  198. <div class="span6">
  199. <div class="accordion-group">
  200. <div class="accordion-heading">
  201. <span class="accordion-toggle">
  202. <strong>本地摄像头</strong>
  203. </span>
  204. </div>
  205. <div class="accordion-body collapse in">
  206. <div class="accordion-inner">
  207. <div id="local_publisher"></div>
  208. </div>
  209. </div>
  210. </div>
  211. </div>
  212. <div class="span6">
  213. <div class="accordion-group">
  214. <div class="accordion-heading">
  215. <span class="accordion-toggle">
  216. <strong>远程服务器</strong>
  217. <a id="remote_tips" href="#" data-toggle="tooltip" data-placement="top" title="">
  218. 黑屏<img src="img/tooltip.png"/>
  219. </a>
  220. <a id="remote_player_url" href="#" data-toggle="tooltip" data-placement="top" title="">
  221. 播放地址<img src="img/tooltip.png"/>
  222. </a>
  223. </span>
  224. </div>
  225. <div class="accordion-body collapse in">
  226. <div class="accordion-inner">
  227. <div id="remote_player"></div>
  228. </div>
  229. </div>
  230. </div>
  231. </div>
  232. </div>
  233. </div>
  234. <div class="container">
  235. <div class="row-fluid">
  236. <div class="span6">
  237. <div class="accordion-group">
  238. <div class="accordion-heading">
  239. <span class="accordion-toggle">
  240. <strong>远程服务器</strong>
  241. <a id="low_latecy_tips" href="#" data-toggle="tooltip" data-placement="top" title="">
  242. 低延时<img src="img/tooltip.png"/>
  243. </a>
  244. <a id="realtime_player_url" href="#" data-toggle="tooltip" data-placement="top" title="">
  245. 播放地址<img src="img/tooltip.png"/>
  246. </a>
  247. </span>
  248. </div>
  249. <div class="accordion-body collapse in">
  250. <div class="accordion-inner">
  251. <div id="realtime_player"></div>
  252. </div>
  253. </div>
  254. </div>
  255. </div>
  256. <div class="span6">
  257. </div>
  258. </div>
  259. </div>
  260. <footer>
  261. <p><a href="https://github.com/ossrs/srs">SRS Team &copy; 2013</a></p>
  262. </footer>
  263. </div>
  264. </body>
  265. <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
  266. <script type="text/javascript" src="js/bootstrap.min.js"></script>
  267. <script type="text/javascript" src="js/swfobject.js"></script>
  268. <script type="text/javascript" src="js/json2.js"></script>
  269. <script type="text/javascript" src="js/srs.page.js"></script>
  270. <script type="text/javascript" src="js/srs.log.js"></script>
  271. <script type="text/javascript" src="js/srs.player.js"></script>
  272. <script type="text/javascript" src="js/srs.publisher.js"></script>
  273. <script type="text/javascript" src="js/srs.utility.js"></script>
  274. <script type="text/javascript" src="js/winlin.utility.js"></script>
  275. <script type="text/javascript">
  276. var srs_publisher = null;
  277. var remote_player = null;
  278. var realtime_player = null;
  279. var query = parse_query_string();
  280. $(function(){
  281. // get the vhost and port to set the default url.
  282. // for example: http://192.168.1.213/players/jwplayer6.html?port=1935&vhost=demo
  283. // url set to: rtmp://demo:1935/live/livestream
  284. srs_init_rtmp("#txt_url", null);
  285. if (query.agent == "true") {
  286. document.write(navigator.userAgent);
  287. return;
  288. }
  289. $("#btn_video_settings").click(function(){
  290. $("#video_modal").modal({show:true});
  291. });
  292. $("#btn_audio_settings").click(function(){
  293. $("#audio_modal").modal({show:true});
  294. });
  295. $("#remote_tips").tooltip({
  296. title: "为了支持HLS输出,FLASH编码器输出的流需要经过转码(VP6=>H264,MP3=>aac),所以会黑屏较长时间,请耐心等待"
  297. });
  298. $("#low_latecy_tips").tooltip({
  299. title: "服务器不转码直接转发FLASH编码器的流,所以延迟比支持HLS的流要低很多"
  300. });
  301. $("#realtime_player_url").tooltip({
  302. title: "右键复制RTMP地址"
  303. });
  304. $("#remote_player_url").tooltip({
  305. title: "右键复制RTMP地址"
  306. });
  307. $("#btn_publish").click(on_user_publish);
  308. // for publish, we use randome stream name.
  309. $("#txt_url").val($("#txt_url").val() + "." + new Date().getTime());
  310. // start the publisher.
  311. srs_publisher = new SrsPublisher("local_publisher", 430, 185);
  312. srs_publisher.on_publisher_ready = function(cameras, microphones) {
  313. srs_publisher_initialize_page(
  314. cameras, microphones,
  315. "#sl_cameras", "#sl_microphones",
  316. "#sl_vcodec", "#sl_profile", "#sl_level", "#sl_gop", "#sl_size",
  317. "#sl_fps", "#sl_bitrate",
  318. "#sl_acodec"
  319. );
  320. };
  321. srs_publisher.on_publisher_error = function(code, desc) {
  322. if (!on_publish_stop()) {
  323. return;
  324. }
  325. error(code, desc + "请重试。");
  326. };
  327. srs_publisher.on_publisher_warn = function(code, desc) {
  328. warn(code, desc);
  329. };
  330. srs_publisher.start();
  331. update_play_url();
  332. // if no play specified, donot show the player, for debug the publisher.
  333. if (query.no_play != "true") {
  334. // start the normal player with HLS supported.
  335. remote_player = new SrsPlayer("remote_player", 430, 185);
  336. remote_player.on_player_ready = function() {
  337. this.set_bt(0.8);
  338. };
  339. remote_player.on_player_metadata = function(metadata) {
  340. this.set_dar(0, 0);
  341. this.set_fs("screen", 100);
  342. }
  343. remote_player.start();
  344. // start the realtime player.
  345. realtime_player = new SrsPlayer("realtime_player", 430, 185);
  346. realtime_player.on_player_ready = function() {
  347. this.set_bt(0.8);
  348. };
  349. realtime_player.on_player_metadata = function(metadata) {
  350. this.set_dar(0, 0);
  351. this.set_fs("screen", 100);
  352. }
  353. realtime_player.start();
  354. }
  355. });
  356. function on_publish_stop() {
  357. if (!srs_can_republish()) {
  358. $("#btn_join").attr("disabled", true);
  359. error(0, "您使用的浏览器很弱,请关闭页面后重新打开页面(刷新也不管用)。<br/>推荐使用Chrome/Firefox/Safari/Opera浏览器,支持重试");
  360. srs_log_disabled = true;
  361. return false;
  362. }
  363. return true;
  364. }
  365. /**
  366. * we generate the transcoded stream url for flash publish donot support HLS
  367. * which requires aac, so the publish vhost maybe players for example, we
  368. * use players_pub vhost(transcoded stream to which) for all clients,
  369. * both players and players_pub are write HLS to the sample dir,
  370. * it's ok for the players vhost disabled the HLS, only the
  371. * players_pub enalbed HLS.
  372. */
  373. function update_play_url() {
  374. var url = $("#txt_url").val();
  375. var ret = srs_parse_rtmp_url(url);
  376. var remote_url = "rtmp://" + ret.server + ":" + ret.port + "/" + ret.app + "...vhost..." + srs_get_player_publish_vhost(ret.vhost) + "/" + ret.stream;
  377. $("#realtime_player_url").attr("href", url).attr("target", "_blank");
  378. $("#remote_player_url").attr("href", remote_url).attr("target", "_blank");
  379. var srs_player_url = "http://" + query.host + query.dir + "/srs_player.html?";
  380. srs_player_url += "vhost=" + srs_get_player_publish_vhost(ret.vhost) + "&port=" + ret.port + "&app=" + ret.app + "&stream=" + ret.stream;
  381. srs_player_url += "&autostart=true";
  382. var srs_player_rt_url = "http://" + query.host + query.dir + "/srs_player.html?";
  383. srs_player_rt_url += "vhost=" + ret.vhost + "&port=" + ret.port + "&app=" + ret.app + "&stream=" + ret.stream;
  384. srs_player_rt_url += "&autostart=true";
  385. var jwplayer_url = "http://" + query.host + query.dir + "/jwplayer6.html?";
  386. jwplayer_url += "vhost=" + srs_get_player_publish_vhost(ret.vhost) + "&port=" + ret.port + "&app=" + ret.app + "&stream=" + ret.stream;
  387. jwplayer_url += "&hls_autostart=true";
  388. var hls_url = "http://" + ret.server + ":" + query.http_port + "/" + ret.app + "/" + ret.stream + ".m3u8";
  389. $("#txt_play_realtime").text("RTMP低延时(点击打开)").attr("href", srs_player_rt_url).attr("target", "_blank");
  390. $("#txt_play_url").text("RTMP已转码(点击打开)").attr("href", srs_player_url).attr("target", "_blank");
  391. $("#txt_play_hls").text("HLS-m3u8(点击打开或右键复制)").attr("href", hls_url).attr("target", "_blank");
  392. $("#txt_play_jwplayer").text("HLS-JWPlayer(点击打开)").attr("href", jwplayer_url).attr("target", "_blank");
  393. }
  394. function on_user_publish() {
  395. if ($("#btn_publish").text() == "停止发布") {
  396. srs_publisher.stop();
  397. $("#btn_publish").text("发布视频");
  398. //$("#txt_play_realtime").text("RTMP低延时(请发布视频)").attr("href", "#").attr("target", "_self");
  399. //$("#txt_play_realtime").attr("href", "#").attr("target", "_self");
  400. //$("#txt_play_url").text("RTMP已转码(请发布视频)").attr("href", "#").attr("target", "_self");
  401. //$("#remote_player_url").attr("href", "#").attr("target", "_self");
  402. //$("#txt_play_hls").text("HLS-m3u8(请发布视频)").attr("href", "#").attr("target", "_self");
  403. //$("#txt_play_jwplayer").text("HLS-JWPlayer(请发布视频)").attr("href", "#").attr("target", "_self");
  404. if (!on_publish_stop()) {
  405. return;
  406. }
  407. return;
  408. }
  409. $("#btn_publish").text("停止发布");
  410. update_play_url();
  411. var url = $("#txt_url").val();
  412. var vcodec = {};
  413. var acodec = {};
  414. srs_publiser_get_codec(
  415. vcodec, acodec,
  416. "#sl_cameras", "#sl_microphones",
  417. "#sl_vcodec", "#sl_profile", "#sl_level", "#sl_gop", "#sl_size",
  418. "#sl_fps", "#sl_bitrate",
  419. "#sl_acodec"
  420. );
  421. info("开始推流到服务器");
  422. srs_publisher.publish(url, vcodec, acodec);
  423. if (realtime_player) {
  424. // directly play the url for the realtime player.
  425. realtime_player.stop();
  426. realtime_player.play(url);
  427. }
  428. if (remote_player) {
  429. // the normal player should play the transcoded stream in another vhost.
  430. // for example, publish stream to vhost players,
  431. // the realtime player play the vhost players, which may donot support HLS,
  432. // the normal player play the vhost players_pub, which transcoded to h264/aac with HLS.
  433. var ret = srs_parse_rtmp_url(url);
  434. var pub_url = "rtmp://" + ret.server + ":" + ret.port + "/" + ret.app;
  435. pub_url += "?vhost=" + srs_get_player_publish_vhost(ret.vhost) + "/" + ret.stream;
  436. remote_player.stop();
  437. remote_player.play(pub_url);
  438. }
  439. }
  440. </script>
  441. </html>