|
|
|
|
<!DOCTYPE html>
|
|
|
|
|
<html>
|
|
|
|
|
<head>
|
|
|
|
|
<title>SRS</title>
|
|
|
|
|
<meta charset="utf-8">
|
|
|
|
|
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"/>
|
|
|
|
|
<script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
|
|
|
|
|
<script type="text/javascript" src="js/bootstrap.min.js"></script>
|
|
|
|
|
<script type="text/javascript" src="js/swfobject.js"></script>
|
|
|
|
|
<script type="text/javascript" src="js/json2.js"></script>
|
|
|
|
|
<script type="text/javascript" src="js/srs.page.js"></script>
|
|
|
|
|
<script type="text/javascript" src="js/srs.log.js"></script>
|
|
|
|
|
<script type="text/javascript" src="js/srs.player.js"></script>
|
|
|
|
|
<script type="text/javascript" src="js/srs.publisher.js"></script>
|
|
|
|
|
<script type="text/javascript" src="js/srs.utility.js"></script>
|
|
|
|
|
<style>
|
|
|
|
|
body{
|
|
|
|
|
padding-top: 55px;
|
|
|
|
|
}
|
|
|
|
|
</style>
|
|
|
|
|
<script type="text/javascript">
|
|
|
|
|
var srs_publisher = null;
|
|
|
|
|
var realtime_player = null;
|
|
|
|
|
var api_server = null;
|
|
|
|
|
var self_chat = null;
|
|
|
|
|
var global_chat_user_id = 200;
|
|
|
|
|
var previous_chats = [];
|
|
|
|
|
var no_play = false;
|
|
|
|
|
|
|
|
|
|
var query = parse_query_string();
|
|
|
|
|
$(function(){
|
|
|
|
|
// get the vhost and port to set the default url.
|
|
|
|
|
// for example: http://192.168.1.213/players/jwplayer6.html?port=1935&vhost=demo
|
|
|
|
|
// url set to: rtmp://demo:1935/live/livestream
|
|
|
|
|
srs_init_publish("#txt_url");
|
|
|
|
|
|
|
|
|
|
if (query.agent == "true") {
|
|
|
|
|
document.write(navigator.userAgent);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$("#realtime_player_url").tooltip({
|
|
|
|
|
title: "右键复制RTMP地址"
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// if no play specified, donot show the player, for debug the publisher.
|
|
|
|
|
if (query.no_play == "true") {
|
|
|
|
|
no_play = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$("#btn_video_settings").click(function(){
|
|
|
|
|
$("#video_modal").modal({show:true});
|
|
|
|
|
});
|
|
|
|
|
$("#btn_audio_settings").click(function(){
|
|
|
|
|
$("#audio_modal").modal({show:true});
|
|
|
|
|
});
|
|
|
|
|
$("#btn_join").click(on_user_publish);
|
|
|
|
|
|
|
|
|
|
// for publish, we use randome stream name.
|
|
|
|
|
$("#txt_url").val($("#txt_url").val() + "." + new Date().getTime());
|
|
|
|
|
|
|
|
|
|
// start the publisher.
|
|
|
|
|
srs_publisher = new SrsPublisher("local_publisher", 430, 185);
|
|
|
|
|
srs_publisher.on_publisher_ready = function(cameras, microphones) {
|
|
|
|
|
srs_chat_initialize_page(
|
|
|
|
|
cameras, microphones,
|
|
|
|
|
"#sl_cameras", "#sl_microphones",
|
|
|
|
|
"#sl_vcodec", "#sl_profile", "#sl_level", "#sl_gop", "#sl_size",
|
|
|
|
|
"#sl_fps", "#sl_bitrate"
|
|
|
|
|
);
|
|
|
|
|
};
|
|
|
|
|
srs_publisher.on_publisher_error = function(code, desc) {
|
|
|
|
|
if (!on_publish_stop()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
error(code, desc + "请重试。");
|
|
|
|
|
};
|
|
|
|
|
srs_publisher.on_publisher_warn = function(code, desc) {
|
|
|
|
|
warn(code, desc);
|
|
|
|
|
};
|
|
|
|
|
srs_publisher.start();
|
|
|
|
|
|
|
|
|
|
update_play_url();
|
|
|
|
|
|
|
|
|
|
if (!no_play) {
|
|
|
|
|
// start the realtime player.
|
|
|
|
|
realtime_player = new SrsPlayer("realtime_player", 430, 185);
|
|
|
|
|
realtime_player.on_player_ready = function() {
|
|
|
|
|
this.set_bt(0.5);
|
|
|
|
|
};
|
|
|
|
|
realtime_player.on_player_metadata = function(metadata) {
|
|
|
|
|
this.set_dar(0, 0);
|
|
|
|
|
this.set_fs("screen", 100);
|
|
|
|
|
|
|
|
|
|
info("推流到服务器成功。请戴耳机聊天,否则音箱的声音会进入麦克风造成回声。");
|
|
|
|
|
}
|
|
|
|
|
realtime_player.start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 2x8 users
|
|
|
|
|
for (var i = 0; i < 8; i++) {
|
|
|
|
|
var tr = $("<tr></tr>").hide();
|
|
|
|
|
$("#lst_chats").append(tr);
|
|
|
|
|
|
|
|
|
|
for (var j = 0; j < 2; j++) {
|
|
|
|
|
tr.append($("<td></td>").attr("id", "td_" + (i * 8 + j)));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// remove border of row.
|
|
|
|
|
$("#lst_chats").find("td").css("border", "none");
|
|
|
|
|
|
|
|
|
|
$("#txt_name").focus();
|
|
|
|
|
|
|
|
|
|
api_server = "http://" + query.hostname + ":" + srs_get_api_server_port() + "/api/v1/chats";
|
|
|
|
|
refresh();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
function on_publish_stop() {
|
|
|
|
|
if (!srs_can_republish()) {
|
|
|
|
|
$("#btn_join").attr("disabled", true);
|
|
|
|
|
error(0, "您使用的浏览器很弱,请关闭页面后重新打开页面(刷新也不管用)。<br/>推荐使用Chrome/Firefox/Safari/Opera浏览器,支持重试");
|
|
|
|
|
|
|
|
|
|
srs_log_disabled = true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function update_play_url() {
|
|
|
|
|
var url = $("#txt_url").val();
|
|
|
|
|
|
|
|
|
|
$("#realtime_player_url").attr("href", url).attr("target", "_blank");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function refresh() {
|
|
|
|
|
if (!self_chat) {
|
|
|
|
|
setTimeout(refresh, 1000);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$.ajax({
|
|
|
|
|
type : "GET",
|
|
|
|
|
async : true,
|
|
|
|
|
url : api_server,
|
|
|
|
|
contentType: "text/html",
|
|
|
|
|
data : "",
|
|
|
|
|
dataType : "json",
|
|
|
|
|
complete : function() {
|
|
|
|
|
},
|
|
|
|
|
error : function(ret) {
|
|
|
|
|
setTimeout(refresh, 5000);
|
|
|
|
|
warn(101, "查询会议室失败:" + JSON.stringify(ret));
|
|
|
|
|
},
|
|
|
|
|
success : function(ret) {
|
|
|
|
|
if(0 != ret["code"]) {
|
|
|
|
|
warn(102, "查询会议室失败: " + JSON.stringify(ret));
|
|
|
|
|
setTimeout(refresh, 5000);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var chats = ret["data"]["chats"];
|
|
|
|
|
var server_time = ret["now"];
|
|
|
|
|
|
|
|
|
|
on_get_chats(chats);
|
|
|
|
|
setTimeout(refresh, 5000);
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
function on_get_chats(chats) {
|
|
|
|
|
if (!self_chat) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// get self, check self is valid?
|
|
|
|
|
var _self_chat = null;
|
|
|
|
|
for (var i = 0; i < chats.length; i++) {
|
|
|
|
|
var chat = chats[i];
|
|
|
|
|
if (self_chat && self_chat.id == chat.id) {
|
|
|
|
|
_self_chat = chat;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// rejoin if invalid.
|
|
|
|
|
if (!_self_chat) {
|
|
|
|
|
on_user_exit_chat(function(){
|
|
|
|
|
on_user_join_chat(function(){
|
|
|
|
|
info("重新加入会议室成功");
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
render_chat_room(chats);
|
|
|
|
|
|
|
|
|
|
if (!self_chat) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// update self heartbeat.
|
|
|
|
|
var url = api_server + "/" + self_chat.id;
|
|
|
|
|
|
|
|
|
|
var chat = {};
|
|
|
|
|
chat.localtime = new Date().getTime();
|
|
|
|
|
|
|
|
|
|
// publish to api server to requires an id.
|
|
|
|
|
$.ajax({
|
|
|
|
|
type : "PUT",
|
|
|
|
|
async : true,
|
|
|
|
|
url : url,
|
|
|
|
|
contentType: "text/html",
|
|
|
|
|
data : JSON.stringify(chat),
|
|
|
|
|
dataType : "json",
|
|
|
|
|
complete : function() {
|
|
|
|
|
},
|
|
|
|
|
error : function(ret) {
|
|
|
|
|
warn(105, "更新会议室信息失败:" + JSON.stringify(ret));
|
|
|
|
|
},
|
|
|
|
|
success : function(ret) {
|
|
|
|
|
if(0 != ret["code"]) {
|
|
|
|
|
warn(106, "更新会议室信息失败:: " + JSON.stringify(ret));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
function render_chat_room(original_chats) {
|
|
|
|
|
if (!self_chat) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var chats = [];
|
|
|
|
|
for (var i = 0; i < original_chats.length; i++) {
|
|
|
|
|
var chat = original_chats[i];
|
|
|
|
|
|
|
|
|
|
// ignore the self.
|
|
|
|
|
if (self_chat && self_chat.id == chat.id) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
chats.push(chat);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// new added chat
|
|
|
|
|
for (var i = 0; i < chats.length; i++) {
|
|
|
|
|
var chat = chats[i];
|
|
|
|
|
|
|
|
|
|
// if previous exists, ignore, only add new here.
|
|
|
|
|
var previous_chat = get_previous_chat_user(previous_chats, chat.id);
|
|
|
|
|
if (previous_chat) {
|
|
|
|
|
// update reference.
|
|
|
|
|
chat.ui = previous_chat.ui;
|
|
|
|
|
chat.parent = previous_chat.parent;
|
|
|
|
|
chat.player = previous_chat.player;
|
|
|
|
|
if (chat.player) {
|
|
|
|
|
chat.player.private_object = chat;
|
|
|
|
|
}
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// removed chat
|
|
|
|
|
for (var i = 0; i < previous_chats.length; i++) {
|
|
|
|
|
var chat = previous_chats[i];
|
|
|
|
|
|
|
|
|
|
var new_chat = get_previous_chat_user(chats, chat.id);
|
|
|
|
|
if (new_chat) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (chat.player) {
|
|
|
|
|
chat.player.stop();
|
|
|
|
|
}
|
|
|
|
|
$("#div_" + chat.id).remove();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// hide empty rows.
|
|
|
|
|
$("#lst_chats").find("tr").each(function(){
|
|
|
|
|
var empty = true;
|
|
|
|
|
|
|
|
|
|
$(this).find("td").each(function(){
|
|
|
|
|
if ($(this).html() != "") {
|
|
|
|
|
empty = false;
|
|
|
|
|
return false; // abort each
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (empty) {
|
|
|
|
|
$(this).hide();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
// render the chat
|
|
|
|
|
for (var i = 0; i < chats.length; i++) {
|
|
|
|
|
var chat = chats[i];
|
|
|
|
|
|
|
|
|
|
// if redered, ignore.
|
|
|
|
|
if (chat.parent) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// generate the ui of chat
|
|
|
|
|
if (!chat.ui) {
|
|
|
|
|
global_chat_user_id++;
|
|
|
|
|
|
|
|
|
|
// username: a str indicates the user name.
|
|
|
|
|
// url: a str indicates the url of user stream.
|
|
|
|
|
// join_date: a str indicates the join timestamp in seconds.
|
|
|
|
|
// join_date_str: friendly formated time.
|
|
|
|
|
var obj = $("<div/>").html($("#template").html());
|
|
|
|
|
if (true) {
|
|
|
|
|
// save current ui object to the chat.
|
|
|
|
|
chat.ui = obj;
|
|
|
|
|
|
|
|
|
|
$(obj).attr("chat_id", chat.id);
|
|
|
|
|
$(obj).attr("id", "div_" + chat.id); // for specifed chat: $("#div_" + chat_id)
|
|
|
|
|
$(obj).attr("class", "div_chat"); // for all chats: $(".div_chat")
|
|
|
|
|
$(obj).find("#chat_player").attr("id", "rp_" + chat.id); // for specifed player: $("#rp_" + chat_id)
|
|
|
|
|
$(obj).find("#chat_player_raw").attr("id", "rp_raw_" + chat.id); // for specifed player: $("#rp_raw_" + chat_id)
|
|
|
|
|
$(obj).find("#user_name").text(chat.username);
|
|
|
|
|
$(obj).find("#user_player_url").attr("href", chat.url);
|
|
|
|
|
$(obj).find("#join_date").text(chat.join_date_str);
|
|
|
|
|
$(obj).find("#collapseM").attr("id", "collapse_" + global_chat_user_id);
|
|
|
|
|
$(obj).find("#headerN").attr("href", "#collapse_" + global_chat_user_id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// find a idle td to render the chat.
|
|
|
|
|
var parent = null;
|
|
|
|
|
$("#lst_chats").find("td").each(function(){
|
|
|
|
|
if ($(this).html() != "") {
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
parent = $(this);
|
|
|
|
|
return false; // abort each
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!parent) {
|
|
|
|
|
warn("没有可用的位置展示流。");
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
$(parent).append(chat.ui);
|
|
|
|
|
$(parent).parent().show();
|
|
|
|
|
|
|
|
|
|
// when ui elements appent to the page,
|
|
|
|
|
// create the player, or flash will failed.
|
|
|
|
|
if (!chat.parent) {
|
|
|
|
|
chat.parent = $(parent);
|
|
|
|
|
|
|
|
|
|
if (!no_play) {
|
|
|
|
|
// start the realtime player.
|
|
|
|
|
var _player = new SrsPlayer("rp_raw_" + chat.id, 430, 185, chat);
|
|
|
|
|
_player.on_player_ready = function() {
|
|
|
|
|
this.set_bt(0.5);
|
|
|
|
|
this.play();
|
|
|
|
|
};
|
|
|
|
|
_player.on_player_metadata = function(metadata) {
|
|
|
|
|
this.set_dar(0, 0);
|
|
|
|
|
this.set_fs("screen", 100);
|
|
|
|
|
}
|
|
|
|
|
_player.start(chat.url);
|
|
|
|
|
|
|
|
|
|
chat.player = _player;
|
|
|
|
|
} else {
|
|
|
|
|
chat.player = null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$(obj).find("#collapse_main").on('hidden', function(){
|
|
|
|
|
var id = $(this).parent().attr("chat_id");
|
|
|
|
|
var chat = get_previous_chat_user(previous_chats, id);
|
|
|
|
|
if (!chat || !chat.player) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
chat.player.stop();
|
|
|
|
|
});
|
|
|
|
|
$(obj).find("#collapse_main").on('shown', function(){
|
|
|
|
|
var id = $(this).parent().attr("chat_id");
|
|
|
|
|
var chat = get_previous_chat_user(previous_chats, id);
|
|
|
|
|
if (!chat || !chat.player) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
chat.player.play();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
previous_chats = chats;
|
|
|
|
|
}
|
|
|
|
|
function get_previous_chat_user(arr, id) {
|
|
|
|
|
for (var i = 0; i < arr.length; i++) {
|
|
|
|
|
var chat = arr[i];
|
|
|
|
|
if (id == chat.id) {
|
|
|
|
|
return chat;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function on_user_publish() {
|
|
|
|
|
if ($("#txt_name").val() == "") {
|
|
|
|
|
$("#txt_name").focus().parent().parent().addClass("error");
|
|
|
|
|
warn(100, "请输入您的名字");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$("#txt_name").parent().parent().removeClass("error");
|
|
|
|
|
|
|
|
|
|
// join chat.
|
|
|
|
|
if (!self_chat) {
|
|
|
|
|
on_user_join_chat();
|
|
|
|
|
} else {
|
|
|
|
|
on_user_exit_chat();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
function on_user_exit_chat(complete_pfn) {
|
|
|
|
|
srs_publisher.stop();
|
|
|
|
|
$("#btn_join").text("加入会议");
|
|
|
|
|
|
|
|
|
|
if (realtime_player) {
|
|
|
|
|
realtime_player.stop();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!self_chat) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// removed chat
|
|
|
|
|
for (var i = 0; i < previous_chats.length; i++) {
|
|
|
|
|
var chat = previous_chats[i];
|
|
|
|
|
|
|
|
|
|
if (chat.player) {
|
|
|
|
|
chat.player.stop();
|
|
|
|
|
}
|
|
|
|
|
$("#div_" + chat.id).remove();
|
|
|
|
|
}
|
|
|
|
|
previous_chats = [];
|
|
|
|
|
|
|
|
|
|
var url = api_server + "/" + self_chat.id;
|
|
|
|
|
// whatever, cleanup local chat.
|
|
|
|
|
self_chat = null;
|
|
|
|
|
|
|
|
|
|
$("#btn_join").attr("disabled", true);
|
|
|
|
|
|
|
|
|
|
// publish to api server to requires an id.
|
|
|
|
|
$.ajax({
|
|
|
|
|
type : "DELETE",
|
|
|
|
|
async : true,
|
|
|
|
|
url : url,
|
|
|
|
|
contentType: "text/html",
|
|
|
|
|
data : "",
|
|
|
|
|
dataType : "json",
|
|
|
|
|
complete : function() {
|
|
|
|
|
if (!on_publish_stop()) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
$("#btn_join").attr("disabled", false);
|
|
|
|
|
if (complete_pfn) {
|
|
|
|
|
complete_pfn();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
error : function(ret) {
|
|
|
|
|
warn(103, "退出会议室失败");
|
|
|
|
|
},
|
|
|
|
|
success : function(ret) {
|
|
|
|
|
if(0 != ret["code"]) {
|
|
|
|
|
warn(104, "退出会议室失败");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
info("退出会议室成功");
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
function on_user_join_chat(complete_pfn) {
|
|
|
|
|
if (self_chat) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var url = $("#txt_url").val();
|
|
|
|
|
var vcodec = {};
|
|
|
|
|
var acodec = {};
|
|
|
|
|
srs_publiser_get_codec(
|
|
|
|
|
vcodec, acodec,
|
|
|
|
|
"#sl_cameras", "#sl_microphones",
|
|
|
|
|
"#sl_vcodec", "#sl_profile", "#sl_level", "#sl_gop", "#sl_size",
|
|
|
|
|
"#sl_fps", "#sl_bitrate"
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
var chat = {};
|
|
|
|
|
chat.id = -1;
|
|
|
|
|
chat.username = $("#txt_name").val();
|
|
|
|
|
chat.agent = navigator.userAgent;
|
|
|
|
|
chat.url = url;
|
|
|
|
|
chat.vcodec = vcodec;
|
|
|
|
|
chat.acodec = acodec;
|
|
|
|
|
|
|
|
|
|
$("#btn_join").attr("disabled", true);
|
|
|
|
|
|
|
|
|
|
// publish to api server to requires an id.
|
|
|
|
|
$.ajax({
|
|
|
|
|
type : "POST",
|
|
|
|
|
async : true,
|
|
|
|
|
url : api_server,
|
|
|
|
|
contentType: "text/html",
|
|
|
|
|
data : JSON.stringify(chat),
|
|
|
|
|
dataType : "json",
|
|
|
|
|
complete : function() {
|
|
|
|
|
$("#btn_join").attr("disabled", false);
|
|
|
|
|
if (complete_pfn) {
|
|
|
|
|
complete_pfn();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
error : function(ret) {
|
|
|
|
|
warn(105, "创建会议室失败:" + JSON.stringify(ret));
|
|
|
|
|
},
|
|
|
|
|
success : function(ret) {
|
|
|
|
|
if(0 != ret["code"]) {
|
|
|
|
|
warn(106, "创建会议室失败: " + JSON.stringify(ret));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
chat.id = ret["data"];
|
|
|
|
|
|
|
|
|
|
// success, start publish.
|
|
|
|
|
self_chat = chat;
|
|
|
|
|
|
|
|
|
|
$("#btn_join").text("退出会议");
|
|
|
|
|
|
|
|
|
|
info("开始推流到服务器。请戴耳机聊天,否则音箱的声音会进入麦克风造成回声。");
|
|
|
|
|
srs_publisher.publish(url, vcodec, acodec);
|
|
|
|
|
|
|
|
|
|
if (realtime_player) {
|
|
|
|
|
// directly play the url for the realtime player.
|
|
|
|
|
realtime_player.stop();
|
|
|
|
|
realtime_player.play(url, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
</script>
|
|
|
|
|
</head>
|
|
|
|
|
<body>
|
|
|
|
|
<div class="navbar navbar-fixed-top">
|
|
|
|
|
<div class="navbar-inner">
|
|
|
|
|
<div class="container">
|
|
|
|
|
<a class="brand" href="index.html">SRS</a>
|
|
|
|
|
<div class="nav-collapse collapse">
|
|
|
|
|
<ul class="nav">
|
|
|
|
|
<li><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
|
|
|
|
|
<li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>
|
|
|
|
|
<li class="active"><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>
|
|
|
|
|
<li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>
|
|
|
|
|
<li><a id="nav_jwplayer6" href="jwplayer6.html">JWPlayer6播放器</a></li>
|
|
|
|
|
<li><a id="nav_osmf" href="osmf.html">AdobeOSMF播放器</a></li>
|
|
|
|
|
<li><a id="nav_vlc" href="vlc.html">VLC播放器</a></li>
|
|
|
|
|
</ul>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="container">
|
|
|
|
|
<!-- for the log -->
|
|
|
|
|
<div class="alert alert-info fade in" id="txt_log">
|
|
|
|
|
<button type="button" class="close" data-dismiss="alert">×</button>
|
|
|
|
|
<strong><span id="txt_log_title">Usage:</span></strong>
|
|
|
|
|
<span id="txt_log_msg">输入名字,设点“加入会议”按钮</span>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
<div class="form-inline">
|
|
|
|
|
<button class="btn input-small" id="btn_video_settings">摄像头</button>
|
|
|
|
|
<button class="btn input-small" id="btn_audio_settings">麦克风</button>
|
|
|
|
|
<input type="text" id="txt_name" class="input-large" placeholder="请输入您的名字..." value=""></input>
|
|
|
|
|
<button class="btn input-small" id="btn_join">加入会议</button>
|
|
|
|
|
<input type="text" id="txt_url" class="input-mini hide" value=""></input>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<table id="lst_chats" class="table">
|
|
|
|
|
<tr>
|
|
|
|
|
<td>
|
|
|
|
|
<div class="accordion-group">
|
|
|
|
|
<div class="accordion-heading">
|
|
|
|
|
<span class="accordion-toggle">
|
|
|
|
|
<strong>[我的] 本地摄像头</strong>
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="accordion-body collapse in">
|
|
|
|
|
<div class="accordion-inner">
|
|
|
|
|
<div id="local_publisher"></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
<td>
|
|
|
|
|
<div class="accordion-group">
|
|
|
|
|
<div class="accordion-heading">
|
|
|
|
|
<span class="accordion-toggle">
|
|
|
|
|
<strong>[我的] 远程服务器流</strong>
|
|
|
|
|
<a id="realtime_player_url" href="#" data-toggle="tooltip" data-placement="top" title="">
|
|
|
|
|
播放地址<img src="img/tooltip.png"/>
|
|
|
|
|
</a>
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="accordion-body collapse in">
|
|
|
|
|
<div class="accordion-inner">
|
|
|
|
|
<div id="realtime_player"></div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</td>
|
|
|
|
|
</tr>
|
|
|
|
|
</table>
|
|
|
|
|
<div class="container hide" id="template">
|
|
|
|
|
<div class="accordion-group" id="collapse_main">
|
|
|
|
|
<div class="accordion-heading" title="点击展开或收起,收起后停止播放流,展开时从服务器请求流">
|
|
|
|
|
<span id="headerN" class="accordion-toggle" data-toggle="collapse" href="#collapseN">
|
|
|
|
|
<strong>[<a href="#"><span id="user_name">XX</span></a>]</strong>
|
|
|
|
|
<strong>加入时间</strong>[<span id="join_date"></span>]
|
|
|
|
|
<a id="user_player_url" href="#" data-toggle="tooltip" data-placement="top" title="">
|
|
|
|
|
播放地址<img src="img/tooltip.png"/>
|
|
|
|
|
</a>
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div id="collapseM" class="accordion-body collapse in">
|
|
|
|
|
<div class="accordion-inner">
|
|
|
|
|
<div id="chat_player">
|
|
|
|
|
<div id="chat_player_raw">
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<table class="table">
|
|
|
|
|
</table>
|
|
|
|
|
<div id="video_modal" class="modal hide fade">
|
|
|
|
|
<div class="modal-header">
|
|
|
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
|
|
|
|
<h3>视频编码</h3>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="modal-body">
|
|
|
|
|
<div class="form-horizontal">
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
<label class="control-label" for="sl_cameras">
|
|
|
|
|
摄像头
|
|
|
|
|
<a id="sl_cameras_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
|
|
|
|
|
<img src="img/tooltip.png"/>
|
|
|
|
|
</a>
|
|
|
|
|
</label>
|
|
|
|
|
<div class="controls">
|
|
|
|
|
<select class="span4" id="sl_cameras"></select>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
<label class="control-label" for="sl_vcodec">
|
|
|
|
|
Codec
|
|
|
|
|
<a id="sl_cameras_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
|
|
|
|
|
<img src="img/tooltip.png"/>
|
|
|
|
|
</a>
|
|
|
|
|
</label>
|
|
|
|
|
<div class="controls">
|
|
|
|
|
<select class="span2" id="sl_vcodec"></select>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
<label class="control-label" for="sl_profile">
|
|
|
|
|
Profile
|
|
|
|
|
<a id="sl_profile_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
|
|
|
|
|
<img src="img/tooltip.png"/>
|
|
|
|
|
</a>
|
|
|
|
|
</label>
|
|
|
|
|
<div class="controls">
|
|
|
|
|
<select class="span2" id="sl_profile"></select>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
<label class="control-label" for="sl_level">
|
|
|
|
|
Level
|
|
|
|
|
<a id="sl_level_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
|
|
|
|
|
<img src="img/tooltip.png"/>
|
|
|
|
|
</a>
|
|
|
|
|
</label>
|
|
|
|
|
<div class="controls">
|
|
|
|
|
<select class="span2" id="sl_level"></select>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
<label class="control-label" for="sl_gop">
|
|
|
|
|
GOP
|
|
|
|
|
<a id="sl_gop_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
|
|
|
|
|
<img src="img/tooltip.png"/>
|
|
|
|
|
</a>
|
|
|
|
|
</label>
|
|
|
|
|
<div class="controls">
|
|
|
|
|
<select class="span2" id="sl_gop"></select>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
<label class="control-label" for="sl_size">
|
|
|
|
|
尺寸
|
|
|
|
|
<a id="sl_size_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
|
|
|
|
|
<img src="img/tooltip.png"/>
|
|
|
|
|
</a>
|
|
|
|
|
</label>
|
|
|
|
|
<div class="controls">
|
|
|
|
|
<select class="span2" id="sl_size"></select>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
<label class="control-label" for="sl_fps">
|
|
|
|
|
帧率
|
|
|
|
|
<a id="sl_fps_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
|
|
|
|
|
<img src="img/tooltip.png"/>
|
|
|
|
|
</a>
|
|
|
|
|
</label>
|
|
|
|
|
<div class="controls">
|
|
|
|
|
<select class="span2" id="sl_fps"></select>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
<label class="control-label" for="sl_bitrate">
|
|
|
|
|
码率
|
|
|
|
|
<a id="sl_bitrate_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
|
|
|
|
|
<img src="img/tooltip.png"/>
|
|
|
|
|
</a>
|
|
|
|
|
</label>
|
|
|
|
|
<div class="controls">
|
|
|
|
|
<select class="span2" id="sl_bitrate"></select>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="modal-footer">
|
|
|
|
|
<button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">设置</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div id="audio_modal" class="modal hide fade">
|
|
|
|
|
<div class="modal-header">
|
|
|
|
|
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
|
|
|
|
<h3>音频编码</h3>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="modal-body">
|
|
|
|
|
<div class="form-horizontal">
|
|
|
|
|
<div class="control-group">
|
|
|
|
|
<label class="control-label" for="sl_microphones">
|
|
|
|
|
麦克风
|
|
|
|
|
<a id="worker_id_tips" href="#" data-toggle="tooltip" data-placement="right" title="">
|
|
|
|
|
<img src="img/tooltip.png"/>
|
|
|
|
|
</a>
|
|
|
|
|
</label>
|
|
|
|
|
<div class="controls">
|
|
|
|
|
<select class="span4" id="sl_microphones"></select>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="modal-footer">
|
|
|
|
|
<button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">设置</button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<hr/>
|
|
|
|
|
<footer>
|
|
|
|
|
<p><a href="https://github.com/winlinvip/simple-rtmp-server">SRS Team © 2013</a></p>
|
|
|
|
|
</footer>
|
|
|
|
|
</div>
|
|
|
|
|
</body>
|
|
|
|
|
|