winlin

update the bootstrap wizard, use v2

不能预览此文件类型
不能预览此文件类型
@@ -197,6 +197,7 @@ vhost dev { @@ -197,6 +197,7 @@ vhost dev {
197 } 197 }
198 } 198 }
199 } 199 }
  200 +
200 # the http hook callback vhost, srs will invoke the hooks for specified events. 201 # the http hook callback vhost, srs will invoke the hooks for specified events.
201 vhost hooks.callback.vhost.com { 202 vhost hooks.callback.vhost.com {
202 http_hooks { 203 http_hooks {
  1 +.wizard {
  2 + display:none;
  3 +}
  4 +.wizard-modal form {
  5 + margin:0;
  6 + padding:0;
  7 +}
  8 +.wizard-modal.modal {
  9 + width:750px;
  10 + margin-left:-375px;
  11 + top:50%;
  12 +}
  13 +.wizard-modal-footer {
  14 + padding:0;
  15 +}
  16 +.wizard-modal-header.modal-header h3 {
  17 + line-height:35px;
  18 + display:inline
  19 +}
  20 +.wizard-modal-header.modal-header {
  21 + border-bottom:0;
  22 +}
  23 +
  24 +.wizard-subtitle {
  25 + font-weight:bold;
  26 + color:#AFAFAF;
  27 + padding-left:20px;
  28 +}
  29 +
  30 +.wizard-error,
  31 +.wizard-failure,
  32 +.wizard-success,
  33 +.wizard-loading,
  34 +.wizard-card {
  35 + position:relative;
  36 + padding:35px;
  37 + padding-top:20px;
  38 + overflow-y:auto;
  39 + height:300px;
  40 + display:none;
  41 + border-top: 1px solid #EEE;
  42 + margin-right: 5px;
  43 +}
  44 +
  45 +.wizard-nav-link .icon-chevron-right {
  46 + float:right;
  47 + margin-top:12px;
  48 + margin-right:-6px;
  49 + opacity:.25;
  50 +}
  51 +
  52 +li.wizard-nav-item.active .icon-chevron-right {
  53 + opacity:1;
  54 +}
  55 +
  56 +li.wizard-nav-item {
  57 + line-height:40px;
  58 +}
  59 +
  60 +.wizard-no-modal .nav-list > li > a,
  61 +.wizard-modal.modal .nav-list > li > a {
  62 + background-color:#f5f5f5;
  63 + padding:3px 15px 3px 20px;
  64 + cursor:default;
  65 + color:#B4B4B4;
  66 +}
  67 +
  68 +.wizard-no-modal .nav-list li.active > a,
  69 +.wizard-modal.modal .nav-list li.active > a {
  70 + background-color:#08C;
  71 +}
  72 +.wizard-no-modal .nav-list > li.already-visited > a.wizard-nav-link,
  73 +.wizard-modal.modal .nav-list > li.already-visited > a.wizard-nav-link {
  74 + color:#08C;
  75 + cursor:pointer;
  76 +}
  77 +
  78 +.wizard-no-modal .nav-list > li.active > a.wizard-nav-link,
  79 +.wizard-modal.modal .nav-list > li.active > a.wizard-nav-link {
  80 + color:white;
  81 +}
  82 +
  83 +.already-visited > a.wizard-nav-link:hover {
  84 + background-color:#E4E4E4;
  85 +}
  86 +
  87 +.wizard-card > h3 {
  88 + margin-top:0;
  89 + margin-bottom:20px;
  90 + font-size:21px;
  91 + line-height:40px;
  92 + font-weight:normal;
  93 +}
  94 +
  95 +.wizard-progress {
  96 + padding:15px;
  97 + bottom:0;
  98 +}
  99 +.wizard-progress-container {
  100 + padding:20px;
  101 +}
  102 +
  103 +.wizard-steps {
  104 + width:28%;
  105 + height:425px;
  106 + background-color:#f5f5f5;
  107 +}
  108 +
  109 +.wizard-nav-container {
  110 + height:360px;
  111 +}
  112 +
  113 +.nav > li > a.wizard-step-error {
  114 + background-color:#F2DEDE;
  115 + color:#B94A48;
  116 + font-weight:bold;
  117 +}
  118 +
  119 +.wizard-step-error .icon-chevron-right {
  120 + opacity:0;
  121 +}
  122 +
  123 +.wizard-input-section {
  124 + margin-bottom:20px;
  125 +}
  126 +
  127 +.wizard-buttons-container {
  128 + padding:20px;
  129 +}
  130 +
  131 +.wizard-cancel {
  132 + display:none;
  133 + margin-left:20px;
  134 +}
  135 +
  136 +.wizard-close {
  137 + display: none;
  138 +}
  139 +
  140 +.wizard-no-modal .popover.error-popover,
  141 +.wizard-modal .popover.error-popover {
  142 + background-color:#F2DEDE;
  143 + color:#B94A48;
  144 + border-color:#953B39;
  145 +}
  146 +
  147 +.wizard-no-modal .popover.error-popover .arrow::after,
  148 +.wizard-modal .popover.error-popover .arrow::after {
  149 + border-right-color:#F2DEDE;
  150 +}
  151 +
  152 +.wizard-no-modal .popover.error-popover .popover-title,
  153 +.wizard-modal .popover.error-popover .popover-title {
  154 + display:none;
  155 +}
  156 +
  157 +.wizard-no-modal .popover.error-popover .arrow,
  158 +.wizard-modal .popover.error-popover .arrow {
  159 + border-right-color:#953B39;
  160 +}
@@ -31,6 +31,7 @@ @@ -31,6 +31,7 @@
31 <ul class="nav"> 31 <ul class="nav">
32 <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li> 32 <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
33 <li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li> 33 <li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>
  34 + <li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>
34 <li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li> 35 <li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>
35 <li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li> 36 <li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li>
36 <li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li> 37 <li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li>
  1 +!function(a){a.fn.wizard=function(a){return new Wizard(this,a)},a.fn.wizard.logging=!1;var b=function(a,b,c,d,e){this.wizard=a,this.index=c,this.prev=d,this.next=e,this.el=b,this.title=b.find("h3").first().text(),this.name=b.data("cardname")||this.title,this.nav=this._createNavElement(this.title,c),this._disabled=!1,this._loaded=!1,this._events={}};b.prototype={select:function(){this.log("selecting"),this.isSelected()||(this.nav.addClass("active"),this.el.show(),this._loaded||(this.trigger("loaded"),this.reload()),this.trigger("selected"));var a=this.wizard;return a.backButton.toggleClass("disabled",0==this.index),this.index>=a._cards.length-1?(this.log("on last card, changing next button to submit"),a.changeNextButton(a.args.buttons.submitText,"btn-success"),a._readyToSubmit=!0,a.trigger("readySubmit")):(a._readyToSubmit=!1,a.changeNextButton(a.args.buttons.nextText,"btn-primary")),this},_createNavElement:function(b,c){var d=a('<li class="wizard-nav-item"></li>'),e=a('<a class="wizard-nav-link"></a>');return e.data("navindex",c),d.append(e),e.append('<i class="icon-chevron-right"></i>'),e.append(b),d},markVisited:function(){return this.log("marking as visited"),this.nav.addClass("already-visited"),this.trigger("markVisited"),this},unmarkVisited:function(){return this.log("unmarking as visited"),this.nav.removeClass("already-visited"),this.trigger("unmarkVisited"),this},deselect:function(){return this.nav.removeClass("active"),this.el.hide(),this.trigger("deselect"),this},enable:function(){return this.log("enabling"),this.nav.addClass("active"),this._disabled=!1,this.trigger("enabled"),this},disable:function(a){return this.log("disabling"),this._disabled=!0,this.nav.removeClass("active already-visited"),a&&this.el.hide(),this.trigger("disabled"),this},isDisabled:function(){return this._disabled},alreadyVisited:function(){return this.nav.hasClass("already-visited")},isSelected:function(){return this.nav.hasClass("active")},reload:function(){return this._loaded=!0,this.trigger("reload"),this},on:function(){return this.wizard.on.apply(this,arguments)},trigger:function(){return this.callListener("on"+arguments[0]),this.wizard.trigger.apply(this,arguments)},toggleAlert:function(b,c){this.log("toggling alert to: "+c),c="undefined"==typeof c?!0:c,c?this.trigger("showAlert"):this.trigger("hideAlert");var d,e=this.el.children("h3").first().next("div.alert");if(0==e.length){if(!c)return this;this.log("couldn't find existing alert div, creating one"),d=a("<div />"),d.addClass("alert"),d.addClass("hide"),d.insertAfter(this.el.find("h3").first())}else this.log("found existing alert div"),d=e.first();return c?(null!=b&&(this.log("setting alert msg to",b),d.html(b)),d.show()):d.hide(),this},callListener:function(a){a=a.toLowerCase(),this.log("looking for listener "+a);var b=window[this.el.data(a)];if(b){this.log("calling listener "+a),this.wizard;try{b(this)}catch(e){this.log("exception calling listener "+a+": ",e)}}else this.log("didn't find listener "+a)},problem:function(a){this.nav.find("a").toggleClass("wizard-step-error",a)},validate:function(){var b=!1,c=this;this.el.find("[data-validate]").each(function(d,e){c.log("validating individiual inputs"),e=a(e);var f=e.data("validate");if(f){var g={status:!0,title:"Error",msg:""},h=window[f](e);if(a.extend(g,h),g.status){e.parent(".control-group").toggleClass("error",!1);try{e.popover("destroy")}catch(i){e.popover("hide")}}else b=!0,e.parent(".control-group").toggleClass("error",!0),c.wizard.errorPopover(e,g.msg)}}),this.log("after validating inputs, failures is",b);var d=window[this.el.data("validate")];if(d){this.log("running html-embedded card validator");var e=d(this);("undefined"==typeof e||null==e)&&(e=!0),e||(b=!0),this.log("after running html-embedded card validator, failures is",b)}this.log("running listener validator");var f=this.trigger("validate");("undefined"==typeof f||null==f)&&(f=!0),f||(b=!0),this.log("after running listener validator, failures is",b);var g=!b;return g?(this.log("validated, calling listeners"),this.trigger("validated")):(this.log("invalid"),this.trigger("invalid")),g},log:function(){if(window.console&&a.fn.wizard.logging){var b="card '"+this.name+"': ",c=[b];c.push.apply(c,arguments),console.log.apply(console,c)}},isActive:function(){return this.nav.hasClass("active")}},Wizard=function(b,c){var d=['<div class="modal hide wizard-modal" role="dialog">','<div class="wizard-modal-header modal-header">','<button class="wizard-close close" type="button">x</button>','<h3 class="wizard-title"></h3>','<span class="wizard-subtitle"></span>',"</div>",'<div class="pull-left wizard-steps">','<div class="wizard-nav-container">','<ul class="nav nav-list" style="padding-bottom:30px;">',"</ul>","</div>",'<div class="wizard-progress-container">',,'<div class="progress progress-striped">','<div class="bar"></div>',"</div>","</div>","</div>","<form>",'<div class="wizard-cards">','<div class="wizard-card-container">',"</div>",'<div class="wizard-modal-footer">','<div class="wizard-buttons-container">','<button class="btn wizard-cancel wizard-close" type="button">Cancel</button>','<div class="btn-group-single pull-right">','<button class="btn wizard-back" type="button">Back</button>','<button class="btn btn-primary wizard-next" type="button">Next</button>',"</div>","</div>","</div>","</div>","</form>","</div>"],e=['<div class="wizard-no-modal" role="dialog">','<div class="wizard-modal-header modal-header">','<button class="wizard-close close" type="button">x</button>','<h3 class="wizard-title"></h3>','<span class="wizard-subtitle"></span>',"</div>",'<div class="pull-left wizard-steps">','<div class="wizard-nav-container">','<ul class="nav nav-list" style="padding-bottom:30px;">',"</ul>","</div>",'<div class="wizard-progress-container">',,'<div class="progress progress-striped">','<div class="bar"></div>',"</div>","</div>","</div>","<form>",'<div class="wizard-cards">','<div class="wizard-card-container">',"</div>",'<div class="wizard-modal-footer">','<div class="wizard-buttons-container">','<button class="btn wizard-cancel wizard-close" type="button">Cancel</button>','<div class="btn-group-single pull-right">','<button class="btn wizard-back" type="button">Back</button>','<button class="btn btn-primary wizard-next" type="button">Next</button>',"</div>","</div>","</div>","</div>","</form>","</div>"];this.args={submitUrl:"",width:750,showCancel:!1,showClose:!0,progressBarCurrent:!1,increaseHeight:0,buttons:{cancelText:"Cancel",nextText:"Next",backText:"Back",submitText:"Submit",submittingText:"Submitting..."},isModal:!0},a.extend(this.args,c||{});var f=this.args.isModal?d:e;this.args.isModal||(this.args.showCancel=!1,this.args.showClose=!1),this.markup=a(b),this.submitCards=this.markup.find(".wizard-error,.wizard-failure,.wizard-success,.wizard-loading"),this.el=a(f.join("\n")),this.el.find(".wizard-card-container").append(this.markup.find(".wizard-card")).append(this.submitCards),a("body").append(this.el),this.closeButton=this.el.find("button.wizard-close"),this.footer=this.el.find(".wizard-modal-footer"),this.cancelButton=this.footer.find(".wizard-cancel"),this.backButton=this.footer.find(".wizard-back"),this.nextButton=this.footer.find(".wizard-next"),this.progress=this.el.find(".progress"),this._cards=[],this.cards={},this._readyToSubmit=!1,this.percentComplete=0,this._submitting=!1,this._events={},this._firstShow=!0,this._createCards(),this.nextButton.click(this,this._handleNextClick),this.backButton.click(this,this._handleBackClick),this.cancelButton.text(this.args.buttons.cancelText),this.backButton.text(this.args.buttons.backText),this.nextButton.text(this.args.buttons.nextText);var g=360,h=g+this.args.increaseHeight;this.el.find(".wizard-nav-container").css("height",h),this.el.find(".wizard-steps").css("height",h+65+"px"),this.el.find(".wizard-card").css("height",h-60+"px"),this.submitCards.css("height",h-60+"px"),this.args.isModal&&this.el.css("margin-top",-(this.el.height()/2)),this.el.css("width",this.args.width),this.args.isModal&&this.el.css("margin-left",-(this.args.width/2));var j=this;this.closeButton.click(function(){j.reset(),j.close(),j.trigger("closed")}),this.el.find(".wizard-steps").on("click","li.already-visited a.wizard-nav-link",this,function(b){var c=parseInt(a(b.target).data("navindex"));b.data.setCard(c)});var k=this.markup.children("h1").first();k.length&&this.setTitle(k.text()),this.on("submit",this._defaultSubmit)},Wizard.prototype={errorPopover:function(a,b){this.log("launching popover on",a);var c=a.popover({content:b,trigger:"manual"}).popover("show").next(".popover");return c.addClass("error-popover"),c},destroyPopover:function(b){b=a(b),b.parent(".control-group").toggleClass("error",!1);var c=b.prev();try{c.popover("destroy")}catch(d){c.popover("hide")}},hidePopovers:function(){this.log("hiding all popovers");var b=this;this.el.find(".error-popover").each(function(a,c){b.destroyPopover(c)})},eachCard:function(b){return a.each(this._cards,b),this},getActiveCard:function(){this.log("getting active card");var b=null;return a.each(this._cards,function(a,c){return c.isActive()?(b=c,!1):void 0}),b?this.log("found active card",b):this.log("couldn't find an active card"),b},setTitle:function(a){return this.log("setting title to",a),this.el.find(".wizard-title").first().text(a),this},setSubtitle:function(a){return this.log("setting subtitle to",a),this.el.find(".wizard-subtitle").first().text(a),this},changeNextButton:function(a,b){return this.log("changing next button, text: "+a,"class: "+b),"undefined"!=typeof b&&this.nextButton.removeClass("btn-success btn-primary"),b&&this.nextButton.addClass(b),this.nextButton.text(a),this},hide:function(){return this.log("hiding"),this.args.isModal?this.el.modal("hide"):this.el.css("display","none"),this},close:function(){return this.log("closing"),this.args.isModal?this.el.modal("hide"):this.el.css("display","none"),this},show:function(a){return this.log("showing"),this._firstShow&&(this.setCard(0),this._firstShow=!1),this.args.showCancel&&this.cancelButton.show(),this.args.showClose&&this.closeButton.show(),this.args.isModal?this.el.modal(a):this.el.css("display","block"),this},on:function(a,b){return this.log("adding listener to event "+a),this._events[a]=b,this},trigger:function(){var a=arguments[0],b=Array.prototype.slice.call(arguments);b.shift(),b.unshift(this),this.log("firing event "+a);var c=this._events[a],d=null;if("function"==typeof c){this.log("found event handler, calling "+a);try{d=c.apply(this,b)}catch(e){this.log("event handler "+a+" had an exception")}}else this.log("couldn't find an event handler for "+a);return d},reset:function(){return this.log("resetting"),this.updateProgressBar(0),this.hideSubmitCards(),this.setCard(0),this.lockCards(),this.enableNextButton(),this.showButtons(),this.hidePopovers(),this.trigger("reset"),this},log:function(){if(window.console&&a.fn.wizard.logging){var b="wizard "+this.el.id+": ",c=[b];c.push.apply(c,arguments),console.log.apply(console,c)}},_abstractIncrementStep:function(a,b){var d,c=this.getActiveCard();if(c)for(this.log("searching for valid next card");;){if(d=b(c)){if(this.log("looking at card",d.index),d.isDisabled()){this.log("card "+d.index+" is disabled/locked, continuing"),c=d;continue}return this.setCard(c.index+a)}this.log("next card is not defined, breaking");break}else this.log("current card is undefined")},incrementCard:function(){this.log("incrementing card");var a=this._abstractIncrementStep(1,function(a){return a.next});return this.trigger("incrementCard"),a},decrementCard:function(){this.log("decrementing card");var a=this._abstractIncrementStep(-1,function(a){return a.prev});return this.trigger("decrementCard"),a},setCard:function(a){this.log("setting card to "+a),this.hideSubmitCards();var b=this.getActiveCard();if(this._submitting)return this.log("we're submitting the wizard already, can't change cards"),b;var c=this._cards[a];if(c){if(c.isDisabled())return this.log("new card is currently disabled, returning"),b;if(b){if(a>b.index){for(var d=b,e=!1;d.index!=c.index;){if(d.index!=b.index&&(d.prev.deselect(),d.prev.markVisited(),d.select()),e=d.validate(),!e)return d;d=d.next}d.prev.deselect(),d.prev.markVisited()}b.deselect(),b.markVisited()}if(c.select(),this.args.progressBarCurrent)this.percentComplete=100*a/this._cards.length,this.updateProgressBar(this.percentComplete);else{var f=this.percentComplete;this.percentComplete=100*a/this._cards.length,this.percentComplete=Math.max(f,this.percentComplete),this.updateProgressBar(this.percentComplete)}return c}this.log("couldn't find card "+a)},updateProgressBar:function(a){this.log("updating progress to "+a+"%"),this.progress.find(".bar").css({width:a+"%"}),this.percentComplete=a,this.trigger("progressBar",a),100==a?(this.log("progress is 100, animating progress bar"),this.progress.addClass("active")):0==a&&(this.log("progress is 0, disabling animation"),this.progress.removeClass("active"))},getNextCard:function(){var a=this.getActiveCard();return a?a.next:void 0},lockCards:function(){return this.log("locking nav cards"),this.eachCard(function(a,b){b.unmarkVisited()}),this},disableCards:function(){return this.log("disabling all nav cards"),this.eachCard(function(a,b){b.disable()}),this},enableCards:function(){return this.log("enabling all nav cards"),this.eachCard(function(a,b){b.enable()}),this},hideCards:function(){return this.log("hiding cards"),this.eachCard(function(a,b){b.deselect()}),this.hideSubmitCards(),this},hideButtons:function(){return this.log("hiding buttons"),this.cancelButton.hide(),this.closeButton.hide(),this.nextButton.hide(),this.backButton.hide(),this},showButtons:function(){return this.log("showing buttons"),this.args.showCancel&&this.cancelButton.show(),this.args.showClose&&this.closeButton.show(),this.nextButton.show(),this.backButton.show(),this},getCard:function(b){var c=a(b).parents(".wizard-card").first()[0];if(c){var d=null;return this.eachCard(function(a,b){return c==b.el[0]?(d=b,!1):!0}),d}return null},_createCards:function(){var c=null,d=null,e=null,f=this,g=this,h=this.el.find(".wizard-cards .wizard-card");a.each(h,function(h,i){i=a(i),c=e,e=new b(f,i,h,c,d),g._cards.push(e),e.name&&(g.cards[e.name]=e),c&&(c.next=e),g.el.find(".wizard-steps .nav-list").append(e.nav)})},showSubmitCard:function(a){this.log("showing "+a+" submit card");var b=this.el.find(".wizard-"+a);b.length?(this.hideCards(),this.el.find(".wizard-"+a).show()):this.log("couldn't find submit card "+a)},hideSubmitCard:function(a){this.log("hiding "+a+" submit card"),this.el.find(".wizard-"+a).hide()},hideSubmitCards:function(){var b=this;a.each(["success","error","failure","loading"],function(a,c){b.hideSubmitCard(c)})},enableNextButton:function(){return this.log("enabling next button"),this.nextButton.removeAttr("disabled"),this},disableNextButton:function(){return this.log("disabling next button"),this.nextButton.attr("disabled","disabled"),this},serializeArray:function(){var a=this.el.children("form").first();return a.serializeArray()},serialize:function(){var a=this.el.children("form").first();return a.serialize()},submitSuccess:function(){this.log("submit success"),this._submitting=!1,this.showSubmitCard("success"),this.trigger("submitSuccess")},submitFailure:function(){this.log("submit failure"),this._submitting=!1,this.showSubmitCard("failure"),this.trigger("submitFailure")},submitError:function(){this.log("submit error"),this._submitting=!1,this.showSubmitCard("error"),this.trigger("submitError")},_submit:function(){this.log("submitting wizard"),this._submitting=!0,this.lockCards(),this.cancelButton.hide(),this.closeButton.hide(),this.backButton.hide(),this.showSubmitCard("loading"),this.updateProgressBar(100),this.changeNextButton(this.args.buttons.submittingText,!1),this.disableNextButton(),this.trigger("submit"),this.trigger("loading")},_onNextClick:function(){this.log("handling 'next' button click");var a=this.getActiveCard();this._readyToSubmit&&a.validate()?this._submit():a=this.incrementCard()},_onBackClick:function(){this.log("handling 'back' button click"),this.decrementCard()},_handleNextClick:function(a){var b=a.data;b._onNextClick.call(b)},_handleBackClick:function(a){var b=a.data;b._onBackClick.call(b)},_defaultSubmit:function(b){a.ajax({type:"POST",url:b.args.submitUrl,data:b.serialize(),dataType:"json",success:function(){b.submitSuccess(),b.hideButtons(),b.updateProgressBar(0)},error:function(){b.submitFailure(),b.hideButtons()}})}}}(window.jQuery);
@@ -20,6 +20,7 @@ function padding(number, length, prefix) { @@ -20,6 +20,7 @@ function padding(number, length, prefix) {
20 function update_nav() { 20 function update_nav() {
21 $("#nav_srs_player").attr("href", "srs_player.html" + window.location.search); 21 $("#nav_srs_player").attr("href", "srs_player.html" + window.location.search);
22 $("#nav_srs_publisher").attr("href", "srs_publisher.html" + window.location.search); 22 $("#nav_srs_publisher").attr("href", "srs_publisher.html" + window.location.search);
  23 + $("#nav_srs_chat").attr("href", "srs_chat.html" + window.location.search);
23 $("#nav_srs_bwt").attr("href", "srs_bwt.html" + window.location.search); 24 $("#nav_srs_bwt").attr("href", "srs_bwt.html" + window.location.search);
24 $("#nav_jwplayer6").attr("href", "jwplayer6.html" + window.location.search); 25 $("#nav_jwplayer6").attr("href", "jwplayer6.html" + window.location.search);
25 $("#nav_osmf").attr("href", "osmf.html" + window.location.search); 26 $("#nav_osmf").attr("href", "osmf.html" + window.location.search);
@@ -83,6 +83,7 @@ @@ -83,6 +83,7 @@
83 <ul class="nav"> 83 <ul class="nav">
84 <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li> 84 <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
85 <li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li> 85 <li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>
  86 + <li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>
86 <li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li> 87 <li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>
87 <li class="active"><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li> 88 <li class="active"><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li>
88 <li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li> 89 <li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li>
@@ -79,6 +79,7 @@ @@ -79,6 +79,7 @@
79 <ul class="nav"> 79 <ul class="nav">
80 <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li> 80 <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
81 <li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li> 81 <li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>
  82 + <li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>
82 <li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li> 83 <li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>
83 <li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li> 84 <li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li>
84 <li class="active"><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li> 85 <li class="active"><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li>
@@ -28,6 +28,7 @@ @@ -28,6 +28,7 @@
28 <ul class="nav"> 28 <ul class="nav">
29 <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li> 29 <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
30 <li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li> 30 <li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>
  31 + <li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>
31 <li class="active"><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li> 32 <li class="active"><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>
32 <li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li> 33 <li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li>
33 <li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li> 34 <li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li>
  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 + <link rel="stylesheet" type="text/css" href="css/bootstrap-wizard.css"/>
  8 + <script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
  9 + <script type="text/javascript" src="js/bootstrap.min.js"></script>
  10 + <script type="text/javascript" src="js/bootstrap-wizard.min.js"></script>
  11 + <script type="text/javascript" src="js/swfobject.js"></script>
  12 + <script type="text/javascript" src="js/srs.js"></script>
  13 + <style>
  14 + body{
  15 + padding-top: 55px;
  16 + }
  17 + </style>
  18 + <script type="text/javascript">
  19 + var srs_publisher = null;
  20 + var remote_player = null;
  21 + var realtime_player = null;
  22 + var wizard = null;
  23 +
  24 + $(function(){
  25 + // get the vhost and port to set the default url.
  26 + // for example: http://192.168.1.213/players/jwplayer6.html?port=1935&vhost=demo
  27 + // url set to: rtmp://demo:1935/live/livestream
  28 + srs_init("#txt_url", null, null);
  29 +
  30 + $("#btn_video_settings").click(function(){
  31 + $("#video_modal").modal({show:true});
  32 + });
  33 + $("#btn_audio_settings").click(function(){
  34 + $("#audio_modal").modal({show:true});
  35 + });
  36 +
  37 + $("#remote_tips").tooltip({
  38 + title: "为了支持HLS输出,FLASH编码器输出的流需要经过转码(VP6=>H264,MP3=>aac),所以会黑屏较长时间,请耐心等待"
  39 + });
  40 + $("#low_latecy_tips").tooltip({
  41 + title: "服务器不转码直接转发FLASH编码器的流,所以延迟比支持HLS的流要低很多"
  42 + });
  43 +
  44 + $("#btn_publish").click(on_user_publish);
  45 +
  46 + // for publish, we use randome stream name.
  47 + $("#txt_url").val($("#txt_url").val() + "." + new Date().getTime());
  48 +
  49 + // start the publisher.
  50 + srs_publisher = new SrsPublisher("local_publisher", 430, 185);
  51 + srs_publisher.on_publisher_ready = function(cameras, microphones) {
  52 + $("#sl_cameras").empty();
  53 + for (var i = 0; i < cameras.length; i++) {
  54 + $("#sl_cameras").append("<option value='" + i + "'>" + cameras[i] + "</option");
  55 + }
  56 + // optional: select the first no "virtual" signed.
  57 + for (var i = 0; i < cameras.length; i++) {
  58 + if (cameras[i].toLowerCase().indexOf("virtual") == -1) {
  59 + $("#sl_cameras option[value='" + i + "']").attr("selected", true);
  60 + break;
  61 + }
  62 + }
  63 +
  64 + $("#sl_microphones").empty();
  65 + for (var i = 0; i < microphones.length; i++) {
  66 + $("#sl_microphones").append("<option value='" + i + "'>" + microphones[i] + "</option");
  67 + }
  68 +
  69 + $("#sl_vcodec").empty();
  70 + var vcodecs = ["h264", "vp6"];
  71 + for (var i = 0; i < vcodecs.length; i++) {
  72 + $("#sl_vcodec").append("<option value='" + vcodecs[i] + "'>" + vcodecs[i] + "</option");
  73 + }
  74 +
  75 + $("#sl_profile").empty();
  76 + var profiles = ["baseline", "main"];
  77 + for (var i = 0; i < profiles.length; i++) {
  78 + $("#sl_profile").append("<option value='" + profiles[i] + "'>" + profiles[i] + "</option");
  79 + }
  80 +
  81 + $("#sl_level").empty();
  82 + var levels = ["1", "1b", "1.1", "1.2", "1.3",
  83 + "2", "2.1", "2.2", "3", "3.1", "3.2", "4", "4.1", "4.2", "5", "5.1"];
  84 + for (var i = 0; i < levels.length; i++) {
  85 + $("#sl_level").append("<option value='" + levels[i] + "'>" + levels[i] + "</option");
  86 + }
  87 + $("#sl_level option[value='4.1']").attr("selected", true);
  88 +
  89 + $("#sl_gop").empty();
  90 + var gops = ["0.3", "0.5", "1", "2", "3", "4",
  91 + "5", "6", "7", "8", "9", "10", "15", "20"];
  92 + for (var i = 0; i < gops.length; i++) {
  93 + $("#sl_gop").append("<option value='" + gops[i] + "'>" + gops[i] + "秒</option");
  94 + }
  95 + $("#sl_gop option[value='5']").attr("selected", true);
  96 +
  97 + $("#sl_size").empty();
  98 + var sizes = ["176x144", "320x240", "352x240",
  99 + "352x288", "460x240", "640x480", "720x480", "720x576", "800x600",
  100 + "1024x768", "1280x720", "1360x768", "1920x1080"];
  101 + for (i = 0; i < sizes.length; i++) {
  102 + $("#sl_size").append("<option value='" + sizes[i] + "'>" + sizes[i] + "</option");
  103 + }
  104 + $("#sl_size option[value='460x240']").attr("selected", true);
  105 +
  106 + $("#sl_fps").empty();
  107 + var fpses = ["5", "10", "15", "20", "24", "25", "29.97", "30"];
  108 + for (i = 0; i < fpses.length; i++) {
  109 + $("#sl_fps").append("<option value='" + fpses[i] + "'>" + Number(fpses[i]).toFixed(2) + " 帧/秒</option");
  110 + }
  111 + $("#sl_fps option[value='15']").attr("selected", true);
  112 +
  113 + $("#sl_bitrate").empty();
  114 + var bitrates = ["50", "200", "350", "500", "650", "800",
  115 + "950", "1000", "1200", "1500", "1800", "2000", "3000", "5000"];
  116 + for (i = 0; i < bitrates.length; i++) {
  117 + $("#sl_bitrate").append("<option value='" + bitrates[i] + "'>" + bitrates[i] + " kbps</option");
  118 + }
  119 + $("#sl_bitrate option[value='350']").attr("selected", true);
  120 + };
  121 + srs_publisher.on_publisher_error = function(code, desc) {
  122 + error(code, desc);
  123 + };
  124 + srs_publisher.on_publisher_warn = function(code, desc) {
  125 + warn(code, desc);
  126 + };
  127 + srs_publisher.start();
  128 +
  129 + //wizard = $("#main_wizard").wizard({});
  130 + //wizard.show();
  131 +
  132 + // if no play specified, donot show the player, for debug the publisher.
  133 + var query = parse_query_string();
  134 + if (query.no_play != "true") {
  135 + // start the normal player with HLS supported.
  136 + remote_player = new SrsPlayer("remote_player", 430, 185);
  137 + remote_player.on_player_ready = function() {
  138 + remote_player.set_bt(0.8);
  139 + remote_player.set_fs("screen", 100);
  140 + };
  141 + remote_player.start();
  142 +
  143 + // start the realtime player.
  144 + realtime_player = new SrsPlayer("realtime_player", 430, 185);
  145 + realtime_player.on_player_ready = function() {
  146 + realtime_player.set_bt(0.8);
  147 + realtime_player.set_fs("screen", 100);
  148 + };
  149 + realtime_player.start();
  150 + }
  151 + });
  152 +
  153 + /**
  154 + * we generate the transcoded stream url for flash publish donot support HLS
  155 + * which requires aac, so the publish vhost maybe players for example, we
  156 + * use players_pub vhost(transcoded stream to which) for all clients,
  157 + * both players and players_pub are write HLS to the sample dir,
  158 + * it's ok for the players vhost disabled the HLS, only the
  159 + * players_pub enalbed HLS.
  160 + */
  161 + function update_play_url() {
  162 + var url = $("#txt_url").val();
  163 + var ret = srs_parse_rtmp_url(url);
  164 + var query = parse_query_string();
  165 +
  166 + var srs_player_url = "http://" + query.host + query.dir + "/srs_player.html?";
  167 + srs_player_url += "vhost=" + srs_get_player_publish_vhost(ret.vhost) + "&port=" + ret.port + "&app=" + ret.app + "&stream=" + ret.stream;
  168 + srs_player_url += "&autostart=true";
  169 +
  170 + var srs_player_rt_url = "http://" + query.host + query.dir + "/srs_player.html?";
  171 + srs_player_rt_url += "vhost=" + ret.vhost + "&port=" + ret.port + "&app=" + ret.app + "&stream=" + ret.stream;
  172 + srs_player_rt_url += "&autostart=true";
  173 +
  174 + var jwplayer_url = "http://" + query.host + query.dir + "/jwplayer6.html?";
  175 + jwplayer_url += "vhost=" + srs_get_player_publish_vhost(ret.vhost) + "&port=" + ret.port + "&app=" + ret.app + "&stream=" + ret.stream;
  176 + jwplayer_url += "&hls_autostart=true";
  177 +
  178 + var hls_url = "http://" + ret.server + ":" + query.http_port + "/" + ret.app + "/" + ret.stream + ".m3u8";
  179 +
  180 + $("#txt_play_realtime").text("RTMP低延时(点击打开)").attr("href", srs_player_rt_url).attr("target", "_blank");
  181 + $("#txt_play_url").text("RTMP已转码(点击打开)").attr("href", srs_player_url).attr("target", "_blank");
  182 + $("#txt_play_hls").text("HLS-m3u8(点击打开或右键复制)").attr("href", hls_url).attr("target", "_blank");
  183 + $("#txt_play_jwplayer").text("HLS-JWPlayer(点击打开)").attr("href", jwplayer_url).attr("target", "_blank");
  184 + }
  185 + function on_user_publish() {
  186 + if ($("#btn_publish").text() == "停止发布") {
  187 + srs_publisher.stop();
  188 + $("#btn_publish").text("发布视频");
  189 + $("#txt_play_realtime").text("RTMP低延时(请发布视频)").attr("href", "#").attr("target", "_self");
  190 + $("#txt_play_url").text("RTMP已转码(请发布视频)").attr("href", "#").attr("target", "_self");
  191 + $("#txt_play_hls").text("HLS-m3u8(请发布视频)").attr("href", "#").attr("target", "_self");
  192 + $("#txt_play_jwplayer").text("HLS-JWPlayer(请发布视频)").attr("href", "#").attr("target", "_self");
  193 + return;
  194 + }
  195 +
  196 + $("#btn_publish").text("停止发布");
  197 +
  198 + update_play_url();
  199 +
  200 + var url = $("#txt_url").val();
  201 + var vcodec = {};
  202 + var acodec = {};
  203 +
  204 + acodec.device_code = $("#sl_microphones").val();
  205 + acodec.device_name = $("#sl_microphones").text();
  206 +
  207 + vcodec.device_code = $("#sl_cameras").find("option:selected").val();
  208 + vcodec.device_name = $("#sl_cameras").find("option:selected").text();
  209 +
  210 + vcodec.codec = $("#sl_vcodec").find("option:selected").val();
  211 + vcodec.profile = $("#sl_profile").find("option:selected").val();
  212 + vcodec.level = $("#sl_level").find("option:selected").val();
  213 + vcodec.fps = $("#sl_fps").find("option:selected").val();
  214 + vcodec.gop = $("#sl_gop").find("option:selected").val();
  215 + vcodec.size = $("#sl_size").find("option:selected").val();
  216 + vcodec.bitrate = $("#sl_bitrate").find("option:selected").val();
  217 +
  218 + info("开始推流到服务器");
  219 + srs_publisher.publish(url, vcodec, acodec);
  220 +
  221 + if (realtime_player) {
  222 + // directly play the url for the realtime player.
  223 + realtime_player.stop();
  224 + realtime_player.play(url);
  225 + }
  226 +
  227 + if (remote_player) {
  228 + // the normal player should play the transcoded stream in another vhost.
  229 + // for example, publish stream to vhost players,
  230 + // the realtime player play the vhost players, which may donot support HLS,
  231 + // the normal player play the vhost players_pub, which transcoded to h264/aac with HLS.
  232 + var ret = srs_parse_rtmp_url(url);
  233 + var pub_url = "rtmp://" + ret.server + ":" + ret.port + "/" + ret.app;
  234 + pub_url += "?vhost=" + srs_get_player_publish_vhost(ret.vhost) + "/" + ret.stream;
  235 + remote_player.stop();
  236 + remote_player.play(pub_url);
  237 + }
  238 + }
  239 +
  240 + function info(desc) {
  241 + $("#txt_log").addClass("alert-info").removeClass("alert-error").removeClass("alert-warn");
  242 + $("#txt_log_title").text("Info:");
  243 + $("#txt_log_msg").text(desc);
  244 + }
  245 + function warn(code, desc) {
  246 + $("#txt_log").removeClass("alert-info").removeClass("alert-error").addClass("alert-warn");
  247 + $("#txt_log_title").text("Warn:");
  248 + $("#txt_log_msg").text("code: " + code + ", " + desc);
  249 + }
  250 + function error(code, desc) {
  251 + $("#txt_log").removeClass("alert-info").addClass("alert-error").removeClass("alert-warn");
  252 + $("#txt_log_title").text("Error:");
  253 + $("#txt_log_msg").text("code: " + code + ", " + desc);
  254 + }
  255 + </script>
  256 +</head>
  257 +<body>
  258 +<div class="navbar navbar-fixed-top">
  259 + <div class="navbar-inner">
  260 + <div class="container">
  261 + <a class="brand" href="index.html">SRS</a>
  262 + <div class="nav-collapse collapse">
  263 + <ul class="nav">
  264 + <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
  265 + <li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>
  266 + <li class="active"><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>
  267 + <li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>
  268 + <li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li>
  269 + <li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li>
  270 + <li><a id="nav_vlc" href="vlc.html">VLC播放器</a></li>
  271 + </ul>
  272 + </div>
  273 + </div>
  274 + </div>
  275 +</div>
  276 +<div class="container">
  277 + <div class="alert alert-info fade in" id="txt_log">
  278 + <button type="button" class="close" data-dismiss="alert">×</button>
  279 + <strong><span id="txt_log_title">Usage:</span></strong>
  280 + <span id="txt_log_msg">设置编码参数,点“发布视频”,允许Flash访问摄像头即可推流</span>
  281 + </div>
  282 + <!-- http://www.panopta.com/2013/02/06/bootstrap-application-wizard/ -->
  283 + <!-- https://github.com/amoffat/bootstrap-application-wizard -->
  284 +<div class="wizard" id="main_wizard" data-title="Wizard Title">
  285 + <div class="wizard-card" data-cardname="card1">
  286 + <h3>Card 1</h3>
  287 + Some content
  288 + </div>
  289 +
  290 + <div class="wizard-card" data-cardname="card2">
  291 + <h3>Card 2</h3>
  292 + Some content
  293 + </div>
  294 +</div>
  295 + <div class="control-group">
  296 + <div class="form-inline">
  297 + <button class="btn" id="btn_video_settings">视频编码配置</button>
  298 + <button class="btn" id="btn_audio_settings">音频编码配置</button>
  299 + </div>
  300 + </div>
  301 + <div class="control-group">
  302 + <div class="form-inline">
  303 + 发布地址:
  304 + <input type="text" id="txt_url" class="input-xxlarge" value=""></input>
  305 + <button class="btn btn-primary" id="btn_publish">发布视频</button>
  306 + </div>
  307 + </div>
  308 + <div class="control-group">
  309 + <div class="form-inline">
  310 + 播放地址
  311 + 1.<a id="txt_play_realtime" class="input-xxlarge" href="#">RTMP低延时(请发布视频)</a>
  312 + 2.<a id="txt_play_url" class="input-xxlarge" href="#">RTMP已转码(请发布视频)</a>
  313 + 3.<a id="txt_play_hls" class="input-xxlarge" href="#">HLS-m3u8(请发布视频)</a>
  314 + 4.<a id="txt_play_jwplayer" class="input-xxlarge" href="#">HLS-JWPlayer(请发布视频)</a>
  315 + </div>
  316 + </div>
  317 + <div id="video_modal" class="modal hide fade">
  318 + <div class="modal-header">
  319 + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  320 + <h3>视频编码</h3>
  321 + </div>
  322 + <div class="modal-body">
  323 + <div class="form-horizontal">
  324 + <div class="control-group">
  325 + <label class="control-label" for="sl_cameras">
  326 + 摄像头
  327 + <a id="sl_cameras_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  328 + <img src="img/tooltip.png"/>
  329 + </a>
  330 + </label>
  331 + <div class="controls">
  332 + <select class="span4" id="sl_cameras"></select>
  333 + </div>
  334 + </div>
  335 + <div class="control-group">
  336 + <label class="control-label" for="sl_vcodec">
  337 + Codec
  338 + <a id="sl_cameras_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  339 + <img src="img/tooltip.png"/>
  340 + </a>
  341 + </label>
  342 + <div class="controls">
  343 + <select class="span2" id="sl_vcodec"></select>
  344 + </div>
  345 + </div>
  346 + <div class="control-group">
  347 + <label class="control-label" for="sl_profile">
  348 + Profile
  349 + <a id="sl_profile_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  350 + <img src="img/tooltip.png"/>
  351 + </a>
  352 + </label>
  353 + <div class="controls">
  354 + <select class="span2" id="sl_profile"></select>
  355 + </div>
  356 + </div>
  357 + <div class="control-group">
  358 + <label class="control-label" for="sl_level">
  359 + Level
  360 + <a id="sl_level_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  361 + <img src="img/tooltip.png"/>
  362 + </a>
  363 + </label>
  364 + <div class="controls">
  365 + <select class="span2" id="sl_level"></select>
  366 + </div>
  367 + </div>
  368 + <div class="control-group">
  369 + <label class="control-label" for="sl_gop">
  370 + GOP
  371 + <a id="sl_gop_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  372 + <img src="img/tooltip.png"/>
  373 + </a>
  374 + </label>
  375 + <div class="controls">
  376 + <select class="span2" id="sl_gop"></select>
  377 + </div>
  378 + </div>
  379 + <div class="control-group">
  380 + <label class="control-label" for="sl_size">
  381 + 尺寸
  382 + <a id="sl_size_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  383 + <img src="img/tooltip.png"/>
  384 + </a>
  385 + </label>
  386 + <div class="controls">
  387 + <select class="span2" id="sl_size"></select>
  388 + </div>
  389 + </div>
  390 + <div class="control-group">
  391 + <label class="control-label" for="sl_fps">
  392 + 帧率
  393 + <a id="sl_fps_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  394 + <img src="img/tooltip.png"/>
  395 + </a>
  396 + </label>
  397 + <div class="controls">
  398 + <select class="span2" id="sl_fps"></select>
  399 + </div>
  400 + </div>
  401 + <div class="control-group">
  402 + <label class="control-label" for="sl_bitrate">
  403 + 码率
  404 + <a id="sl_bitrate_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  405 + <img src="img/tooltip.png"/>
  406 + </a>
  407 + </label>
  408 + <div class="controls">
  409 + <select class="span2" id="sl_bitrate"></select>
  410 + </div>
  411 + </div>
  412 + </div>
  413 + </div>
  414 + <div class="modal-footer">
  415 + <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">设置</button>
  416 + </div>
  417 + </div>
  418 + <div id="audio_modal" class="modal hide fade">
  419 + <div class="modal-header">
  420 + <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
  421 + <h3>音频编码</h3>
  422 + </div>
  423 + <div class="modal-body">
  424 + <div class="form-horizontal">
  425 + <div class="control-group">
  426 + <label class="control-label" for="sl_microphones">
  427 + 麦克风
  428 + <a id="worker_id_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
  429 + <img src="img/tooltip.png"/>
  430 + </a>
  431 + </label>
  432 + <div class="controls">
  433 + <select class="span4" id="sl_microphones"></select>
  434 + </div>
  435 + </div>
  436 + </div>
  437 + </div>
  438 + <div class="modal-footer">
  439 + <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">设置</button>
  440 + </div>
  441 + </div>
  442 + <div class="container">
  443 + <div class="row-fluid">
  444 + <div class="span6">
  445 + <div class="accordion-group">
  446 + <div class="accordion-heading">
  447 + <span class="accordion-toggle" data-toggle="collapse" href="#collapse1">
  448 + <strong>本地摄像头</strong>
  449 + </span>
  450 + </div>
  451 + <div id="collapse1" class="accordion-body collapse in">
  452 + <div class="accordion-inner">
  453 + <div id="local_publisher"></div>
  454 + </div>
  455 + </div>
  456 + </div>
  457 + </div>
  458 + <div class="span6">
  459 + <div class="accordion-group">
  460 + <div class="accordion-heading">
  461 + <span class="accordion-toggle" data-toggle="collapse" href="#collapse2">
  462 + <strong>远程服务器</strong>
  463 + <a id="remote_tips" href="#" data-toggle="tooltip" data-placement="top" title="">
  464 + 黑屏<img src="img/tooltip.png"/>
  465 + </a>
  466 + </span>
  467 + </div>
  468 + <div id="collapse2" class="accordion-body collapse in">
  469 + <div class="accordion-inner">
  470 + <div id="remote_player"></div>
  471 + </div>
  472 + </div>
  473 + </div>
  474 + </div>
  475 + </div>
  476 + </div>
  477 + <div class="container">
  478 + <div class="row-fluid">
  479 + <div class="span6">
  480 + <div class="accordion-group">
  481 + <div class="accordion-heading">
  482 + <span class="accordion-toggle" data-toggle="collapse" href="#collapse3">
  483 + <strong>远程服务器</strong>
  484 + <a id="low_latecy_tips" href="#" data-toggle="tooltip" data-placement="top" title="">
  485 + 低延时<img src="img/tooltip.png"/>
  486 + </a>
  487 + </span>
  488 + </div>
  489 + <div id="collapse3" class="accordion-body collapse in">
  490 + <div class="accordion-inner">
  491 + <div id="realtime_player"></div>
  492 + </div>
  493 + </div>
  494 + </div>
  495 + </div>
  496 + <div class="span6">
  497 + </div>
  498 + </div>
  499 + </div>
  500 + <footer>
  501 + <p><a href="https://github.com/winlinvip/simple-rtmp-server">SRS Team &copy; 2013</a></p>
  502 + </footer>
  503 +</div>
  504 +</body>
  505 +
@@ -269,6 +269,7 @@ @@ -269,6 +269,7 @@
269 <ul class="nav"> 269 <ul class="nav">
270 <li class="active"><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li> 270 <li class="active"><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
271 <li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li> 271 <li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>
  272 + <li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>
272 <li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li> 273 <li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>
273 <li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li> 274 <li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li>
274 <li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li> 275 <li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li>
@@ -257,6 +257,7 @@ @@ -257,6 +257,7 @@
257 <ul class="nav"> 257 <ul class="nav">
258 <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li> 258 <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
259 <li class="active"><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li> 259 <li class="active"><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>
  260 + <li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>
260 <li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li> 261 <li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>
261 <li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li> 262 <li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li>
262 <li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li> 263 <li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li>
@@ -29,6 +29,7 @@ @@ -29,6 +29,7 @@
29 <ul class="nav"> 29 <ul class="nav">
30 <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li> 30 <li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
31 <li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li> 31 <li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>
  32 + <li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>
32 <li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li> 33 <li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>
33 <li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li> 34 <li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li>
34 <li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li> 35 <li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li>
@@ -39,7 +40,7 @@ @@ -39,7 +40,7 @@
39 </div> 40 </div>
40 </div> 41 </div>
41 <div class="container"> 42 <div class="container">
42 - <iframe id="main_frame" width="100%" height="800" frameBorder="0"></iframe> 43 + <iframe id="main_frame" width="100%" height="600" frameBorder="0"></iframe>
43 </div> 44 </div>
44 <div class="container"> 45 <div class="container">
45 <hr> 46 <hr>