1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-03-09 15:49:59 +00:00

Merge branch '2.0release' into develop

This commit is contained in:
winlin 2015-08-20 18:13:17 +08:00
commit ce8f446494
18 changed files with 2040 additions and 1380 deletions

View file

@ -6,6 +6,7 @@
<script type="text/javascript" src="players/js/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="players/js/srs.page.js"></script>
<script type="text/javascript" src="players/js/srs.utility.js"></script>
<script type="text/javascript" src="players/js/winlin.utility.js"></script>
</head>
<body>
<script type="text/javascript">

View file

@ -4,35 +4,11 @@
<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/srs.page.js"></script>
<script type="text/javascript" src="js/srs.utility.js"></script>
<style>
body{
padding-top: 55px;
}
</style>
<script type="text/javascript">
$(function(){
update_nav();
var query = parse_query_string();
var url = "srs_chat.html?vhost=" + srs_get_player_vhost();
for (var key in query.user_query) {
if (key == "vhost") {
continue;
}
url += "&" + key + "=" + query[key];
}
setTimeout(function(){
window.location.href = url;
}, 100);
});
</script>
</head>
<body>
<div class="navbar navbar-fixed-top">
@ -59,5 +35,30 @@
<p><a href="https://github.com/simple-rtmp-server/srs">SRS Team &copy; 2013</a></p>
</footer>
</div>
<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/srs.page.js"></script>
<script type="text/javascript" src="js/srs.utility.js"></script>
<script type="text/javascript" src="js/winlin.utility.js"></script>
<script type="text/javascript">
$(function(){
update_nav();
var query = parse_query_string();
var url = "srs_chat.html?vhost=" + srs_get_player_vhost();
for (var key in query.user_query) {
if (key == "vhost") {
continue;
}
url += "&" + key + "=" + query[key];
}
setTimeout(function(){
window.location.href = url;
}, 100);
});
</script>
</body>

View file

@ -3,7 +3,7 @@
//////////////////////////////////////////////////////////////////////////////////
// to query the swf anti cache.
function srs_get_version_code() { return "1.23"; }
function srs_get_version_code() { return "1.25"; }
/**
* player specified size.
@ -135,9 +135,15 @@ function build_default_hls_url() {
* @param hls_url the div id contains the hls stream url to play
* @param modal_player the div id contains the modal player
*/
function srs_init_rtmp(rtmp_url, modal_player) {
srs_init(rtmp_url, null, modal_player);
}
function srs_init_hls(hls_url, modal_player) {
srs_init(null, hls_url, modal_player);
}
function srs_init(rtmp_url, hls_url, modal_player) {
update_nav();
if (rtmp_url) {
$(rtmp_url).val(build_default_rtmp_url());
}

View file

@ -30,6 +30,32 @@ function SrsPlayer(container, width, height, private_object) {
this.meatadata = {}; // for on_player_metadata
this.time = 0; // current stream time.
this.buffer_length = 0; // current stream buffer length.
this.kbps = 0; // current stream bitrate(video+audio) in kbps.
this.fps = 0; // current stream video fps.
this.rtime = 0; // flash relative time in ms.
this.__fluency = {
total_empty_count: 0,
total_empty_time: 0,
current_empty_time: 0
};
this.__fluency.on_stream_empty = function(time) {
this.total_empty_count++;
this.current_empty_time = time;
};
this.__fluency.on_stream_full = function(time) {
if (this.current_empty_time > 0) {
this.total_empty_time += time - this.current_empty_time;
this.current_empty_time = 0;
}
};
this.__fluency.calc = function(time) {
var den = this.total_empty_count * 4 + this.total_empty_time * 2 + time;
if (den > 0) {
return time * 100 / den;
}
return 0;
};
}
/**
* user can set some callback, then start the player.
@ -49,6 +75,8 @@ SrsPlayer.prototype.start = function(url) {
flashvars.on_player_ready = "__srs_on_player_ready";
flashvars.on_player_metadata = "__srs_on_player_metadata";
flashvars.on_player_timer = "__srs_on_player_timer";
flashvars.on_player_empty = "__srs_on_player_empty";
flashvars.on_player_full = "__srs_on_player_full";
var params = {};
params.wmode = "opaque";
@ -112,6 +140,18 @@ SrsPlayer.prototype.pause = function() {
SrsPlayer.prototype.resume = function() {
this.callbackObj.ref.__resume();
}
/**
* get the stream fluency, where 100 is 100%.
*/
SrsPlayer.prototype.fluency = function() {
return this.__fluency.calc(this.rtime);
}
/**
* get the stream empty count.
*/
SrsPlayer.prototype.empty_count = function() {
return this.__fluency.total_empty_count;
}
/**
* to set the DAR, for example, DAR=16:9 where num=16,den=9.
* @param num, for example, 16.
@ -148,7 +188,13 @@ SrsPlayer.prototype.on_player_ready = function() {
SrsPlayer.prototype.on_player_metadata = function(metadata) {
// ignore.
}
SrsPlayer.prototype.on_player_timer = function(time, buffer_length) {
SrsPlayer.prototype.on_player_timer = function(time, buffer_length, kbps, fps, rtime) {
// ignore.
}
SrsPlayer.prototype.on_player_empty = function(time) {
// ignore.
}
SrsPlayer.prototype.on_player_full = function(time) {
// ignore.
}
function __srs_find_player(id) {
@ -177,7 +223,7 @@ function __srs_on_player_metadata(id, metadata) {
player.on_player_metadata(metadata);
}
function __srs_on_player_timer(id, time, buffer_length) {
function __srs_on_player_timer(id, time, buffer_length, kbps, fps, rtime) {
var player = __srs_find_player(id);
buffer_length = Math.max(0, buffer_length);
@ -189,6 +235,19 @@ function __srs_on_player_timer(id, time, buffer_length) {
// so set the data before invoke it.
player.time = time;
player.buffer_length = buffer_length;
player.on_player_timer(time, buffer_length);
player.kbps = kbps;
player.fps = fps;
player.rtime = rtime;
player.on_player_timer(time, buffer_length, kbps, fps, rtime);
}
function __srs_on_player_empty(id, time) {
var player = __srs_find_player(id);
player.__fluency.on_stream_empty(time);
player.on_player_empty(time);
}
function __srs_on_player_full(id, time) {
var player = __srs_find_player(id);
player.__fluency.on_stream_full(time);
player.on_player_full(time);
}

View file

@ -1,154 +1,8 @@
/**
* padding the output.
* padding(3, 5, '0') is 00003
* padding(3, 5, 'x') is xxxx3
* @see http://blog.csdn.net/win_lin/article/details/12065413
*/
function padding(number, length, prefix) {
if(String(number).length >= length){
return String(number);
}
return padding(prefix+number, length, prefix);
}
/**
* parse the query string to object.
* parse the url location object as: host(hostname:http_port), pathname(dir/filename)
* for example, url http://192.168.1.168:1980/ui/players.html?vhost=player.vhost.com&app=test&stream=livestream
* parsed to object:
{
host : "192.168.1.168:1980",
hostname : "192.168.1.168",
http_port : 1980,
pathname : "/ui/players.html",
dir : "/ui",
filename : "/players.html",
vhost : "player.vhost.com",
app : "test",
stream : "livestream"
}
*/
function parse_query_string(){
var obj = {};
// add the uri object.
// parse the host(hostname:http_port), pathname(dir/filename)
obj.host = window.location.host;
obj.hostname = window.location.hostname;
obj.http_port = (window.location.port == "")? 80:window.location.port;
obj.pathname = window.location.pathname;
if (obj.pathname.lastIndexOf("/") <= 0) {
obj.dir = "/";
obj.filename = "";
} else {
obj.dir = obj.pathname.substr(0, obj.pathname.lastIndexOf("/"));
obj.filename = obj.pathname.substr(obj.pathname.lastIndexOf("/"));
}
// pure user query object.
obj.user_query = {};
// parse the query string.
var query_string = String(window.location.search).replace(" ", "").split("?")[1];
if(query_string == undefined){
return obj;
}
var queries = query_string.split("&");
$(queries).each(function(){
var query = this.split("=");
obj[query[0]] = query[1];
obj.user_query[query[0]] = query[1];
});
return obj;
}
/**
* parse the rtmp url,
* for example: rtmp://demo.srs.com:1935/live...vhost...players/livestream
* @return object {server, port, vhost, app, stream}
*/
function srs_parse_rtmp_url(rtmp_url) {
// @see: http://stackoverflow.com/questions/10469575/how-to-use-location-object-to-parse-url-without-redirecting-the-page-in-javascri
var a = document.createElement("a");
a.href = rtmp_url.replace("rtmp://", "http://");
var vhost = a.hostname;
var port = (a.port == "")? "1935":a.port;
var app = a.pathname.substr(1, a.pathname.lastIndexOf("/") - 1);
var stream = a.pathname.substr(a.pathname.lastIndexOf("/") + 1);
// parse the vhost in the params of app, that srs supports.
app = app.replace("...vhost...", "?vhost=");
if (app.indexOf("?") >= 0) {
var params = app.substr(app.indexOf("?"));
app = app.substr(0, app.indexOf("?"));
if (params.indexOf("vhost=") > 0) {
vhost = params.substr(params.indexOf("vhost=") + "vhost=".length);
if (vhost.indexOf("&") > 0) {
vhost = vhost.substr(0, vhost.indexOf("&"));
}
}
}
var ret = {
server: a.hostname, port: port,
vhost: vhost, app: app, stream: stream
};
return ret;
}
/**
* get the agent.
* @return an object specifies some browser.
* for example, get_browser_agents().MSIE
*/
function get_browser_agents() {
var agent = navigator.userAgent;
/**
WindowsPC platform, Win7:
chrome 31.0.1650.63:
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
firefox 23.0.1:
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101
Firefox/23.0
safari 5.1.7(7534.57.2):
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2
(KHTML, like Gecko) Version/5.1.7 Safari/534.57.2
opera 15.0.1147.153:
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
OPR/15.0.1147.153
360 6.2.1.272:
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64;
Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729;
.NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C;
.NET4.0E)
IE 10.0.9200.16750(update: 10.0.12):
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64;
Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729;
.NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C;
.NET4.0E)
*/
return {
// platform
Android: agent.indexOf("Android") != -1,
Windows: agent.indexOf("Windows") != -1,
iPhone: agent.indexOf("iPhone") != -1,
// Windows Browsers
Chrome: agent.indexOf("Chrome") != -1,
Firefox: agent.indexOf("Firefox") != -1,
QQBrowser: agent.indexOf("QQBrowser") != -1,
MSIE: agent.indexOf("MSIE") != -1,
// Android Browsers
Opera: agent.indexOf("Presto") != -1,
MQQBrowser: agent.indexOf("MQQBrowser") != -1
};
return parse_rtmp_url(rtmp_url);
}

View file

@ -0,0 +1,571 @@
// winlin.utility.js
/**
* common utilities
* depends: jquery1.10
* https://code.csdn.net/snippets/147103
* @see: http://blog.csdn.net/win_lin/article/details/17994347
* v 1.0.11
*/
/**
* padding the output.
* padding(3, 5, '0') is 00003
* padding(3, 5, 'x') is xxxx3
* @see http://blog.csdn.net/win_lin/article/details/12065413
*/
function padding(number, length, prefix) {
if(String(number).length >= length){
return String(number);
}
return padding(prefix+number, length, prefix);
}
/**
* extends system array, to remove all specified elem.
* @param arr the array to remove elem from.
* @param elem the elem to remove.
* @remark all elem will be removed.
* for example,
* arr = [10, 15, 20, 30, 20, 40]
* system_array_remove(arr, 10) // arr=[15, 20, 30, 20, 40]
* system_array_remove(arr, 20) // arr=[15, 30, 40]
*/
function system_array_remove(arr, elem) {
if (!arr) {
return;
}
var removed = true;
var i = 0;
while (removed) {
removed = false;
for (; i < arr.length; i++) {
if (elem == arr[i]) {
arr.splice(i, 1);
removed = true;
break;
}
}
}
}
/**
* whether the array contains specified element.
* @param arr the array to find.
* @param elem_or_function the element value or compare function.
* @returns true contains elem; otherwise false.
* for example,
* arr = [10, 15, 20, 30, 20, 40]
* system_array_contains(arr, 10) // true
* system_array_contains(arr, 11) // false
* system_array_contains(arr, function(elem){return elem == 30;}); // true
* system_array_contains(arr, function(elem){return elem == 60;}); // false
*/
function system_array_contains(arr, elem_or_function) {
return system_array_get(arr, elem_or_function) != null;
}
/**
* get the specified element from array
* @param arr the array to find.
* @param elem_or_function the element value or compare function.
* @returns the matched elem; otherwise null.
* for example,
* arr = [10, 15, 20, 30, 20, 40]
* system_array_get(arr, 10) // 10
* system_array_get(arr, 11) // null
* system_array_get(arr, function(elem){return elem == 30;}); // 30
* system_array_get(arr, function(elem){return elem == 60;}); // null
*/
function system_array_get(arr, elem_or_function) {
for (var i = 0; i < arr.length; i++) {
if (typeof elem_or_function == "function") {
if (elem_or_function(arr[i])) {
return arr[i];
}
} else {
if (elem_or_function == arr[i]) {
return arr[i];
}
}
}
return null;
}
/**
* to iterate on array.
* @param arr the array to iterate on.
* @param pfn the function to apply on it
* for example,
* arr = [10, 15, 20, 30, 20, 40]
* system_array_foreach(arr, function(elem, index){
* console.log('index=' + index + ',elem=' + elem);
* });
*/
function system_array_foreach(arr, pfn) {
for (var i = 0; i < arr.length; i++) {
if (pfn) {
pfn(arr[i], i)
}
}
}
/**
* array sort asc, for example:
* [a, b] in [10, 11, 9]
* then sort to: [9, 10, 11]
* Usage, for example:
obj.data.data.sort(function(a, b){
return array_sort_asc(a.metadata.meta_id, b.metadata.meta_id);
});
* @see: http://blog.csdn.net/win_lin/article/details/17994347
* @remark, if need desc, use -1*array_sort_asc(a,b)
*/
function array_sort_asc(elem_a, elem_b) {
if (elem_a > elem_b) {
return 1;
}
return (elem_a < elem_b)? -1 : 0;
}
function array_sort_desc(elem_a, elem_b) {
return -1 * array_sort_asc(elem_a, elem_b);
}
function system_array_sort_asc(elem_a, elem_b) {
return array_sort_asc(elem_a, elem_b);
}
function system_array_sort_desc(elem_a, elem_b) {
return -1 * array_sort_asc(elem_a, elem_b);
}
/**
* parse the query string to object.
* parse the url location object as: host(hostname:http_port), pathname(dir/filename)
* for example, url http://192.168.1.168:1980/ui/players.html?vhost=player.vhost.com&app=test&stream=livestream
* parsed to object:
{
host : "192.168.1.168:1980",
hostname : "192.168.1.168",
http_port : 1980,
pathname : "/ui/players.html",
dir : "/ui",
filename : "/players.html",
vhost : "player.vhost.com",
app : "test",
stream : "livestream"
}
* @see: http://blog.csdn.net/win_lin/article/details/17994347
*/
function parse_query_string(){
var obj = {};
// add the uri object.
// parse the host(hostname:http_port), pathname(dir/filename)
obj.host = window.location.host;
obj.hostname = window.location.hostname;
obj.http_port = (window.location.port == "")? 80:window.location.port;
obj.pathname = window.location.pathname;
if (obj.pathname.lastIndexOf("/") <= 0) {
obj.dir = "/";
obj.filename = "";
} else {
obj.dir = obj.pathname.substr(0, obj.pathname.lastIndexOf("/"));
obj.filename = obj.pathname.substr(obj.pathname.lastIndexOf("/"));
}
// pure user query object.
obj.user_query = {};
// parse the query string.
var query_string = String(window.location.search).replace(" ", "").split("?")[1];
if(query_string == undefined){
query_string = String(window.location.hash).replace(" ", "").split("#")[1];
if(query_string == undefined){
return obj;
}
}
var queries = query_string.split("&");
$(queries).each(function(){
var query = this.split("=");
obj[query[0]] = query[1];
obj.user_query[query[0]] = query[1];
});
return obj;
}
/**
* parse the rtmp url,
* for example: rtmp://demo.srs.com:1935/live...vhost...players/livestream
* @return object {server, port, vhost, app, stream}
* for exmaple, rtmp_url is rtmp://demo.srs.com:1935/live...vhost...players/livestream
* parsed to object:
{
server: "demo.srs.com",
port: 1935,
vhost: "players",
app: "live",
stream: "livestream"
}
*/
function parse_rtmp_url(rtmp_url) {
// @see: http://stackoverflow.com/questions/10469575/how-to-use-location-object-to-parse-url-without-redirecting-the-page-in-javascri
var a = document.createElement("a");
a.href = rtmp_url.replace("rtmp://", "http://").replace("?", "...").replace("=", "...");
var vhost = a.hostname;
var port = (a.port == "")? "1935":a.port;
var app = a.pathname.substr(1, a.pathname.lastIndexOf("/") - 1);
var stream = a.pathname.substr(a.pathname.lastIndexOf("/") + 1);
// parse the vhost in the params of app, that srs supports.
app = app.replace("...vhost...", "?vhost=");
if (app.indexOf("?") >= 0) {
var params = app.substr(app.indexOf("?"));
app = app.substr(0, app.indexOf("?"));
if (params.indexOf("vhost=") > 0) {
vhost = params.substr(params.indexOf("vhost=") + "vhost=".length);
if (vhost.indexOf("&") > 0) {
vhost = vhost.substr(0, vhost.indexOf("&"));
}
}
}
// when vhost equals to server, and server is ip,
// the vhost is __defaultVhost__
if (a.hostname == vhost) {
var re = /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/;
if (re.test(a.hostname)) {
vhost = "__defaultVhost__";
}
}
var ret = {
server: a.hostname, port: port,
vhost: vhost, app: app, stream: stream
};
return ret;
}
/**
* get the agent.
* @return an object specifies some browser.
* for example, get_browser_agents().MSIE
* @see: http://blog.csdn.net/win_lin/article/details/17994347
*/
function get_browser_agents() {
var agent = navigator.userAgent;
/**
WindowsPC platform, Win7:
chrome 31.0.1650.63:
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36
firefox 23.0.1:
Mozilla/5.0 (Windows NT 6.1; WOW64; rv:23.0) Gecko/20100101
Firefox/23.0
safari 5.1.7(7534.57.2):
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.57.2
(KHTML, like Gecko) Version/5.1.7 Safari/534.57.2
opera 15.0.1147.153:
Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36
(KHTML, like Gecko) Chrome/28.0.1500.95 Safari/537.36
OPR/15.0.1147.153
360 6.2.1.272:
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64;
Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729;
.NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C;
.NET4.0E)
IE 10.0.9200.16750(update: 10.0.12):
Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64;
Trident/6.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729;
.NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.2; .NET4.0C;
.NET4.0E)
*/
return {
// platform
Android: agent.indexOf("Android") != -1,
Windows: agent.indexOf("Windows") != -1,
iPhone: agent.indexOf("iPhone") != -1,
// Windows Browsers
Chrome: agent.indexOf("Chrome") != -1,
Firefox: agent.indexOf("Firefox") != -1,
QQBrowser: agent.indexOf("QQBrowser") != -1,
MSIE: agent.indexOf("MSIE") != -1,
// Android Browsers
Opera: agent.indexOf("Presto") != -1,
MQQBrowser: agent.indexOf("MQQBrowser") != -1
};
}
/**
* format relative seconds to HH:MM:SS,
* for example, 210s formated to 00:03:30
* @see: http://blog.csdn.net/win_lin/article/details/17994347
* @usage relative_seconds_to_HHMMSS(210)
*/
function relative_seconds_to_HHMMSS(seconds){
var date = new Date();
date.setTime(Number(seconds) * 1000);
var ret = padding(date.getUTCHours(), 2, '0')
+ ":" + padding(date.getUTCMinutes(), 2, '0')
+ ":" + padding(date.getUTCSeconds(), 2, '0');
return ret;
}
/**
* format absolute seconds to HH:MM:SS,
* for example, 1389146480s (2014-01-08 10:01:20 GMT+0800) formated to 10:01:20
* @see: http://blog.csdn.net/win_lin/article/details/17994347
* @usage absolute_seconds_to_HHMMSS(new Date().getTime() / 1000)
*/
function absolute_seconds_to_HHMMSS(seconds){
var date = new Date();
date.setTime(Number(seconds) * 1000);
var ret = padding(date.getHours(), 2, '0')
+ ":" + padding(date.getMinutes(), 2, '0')
+ ":" + padding(date.getSeconds(), 2, '0');
return ret;
}
/**
* format absolute seconds to YYYY-mm-dd,
* for example, 1389146480s (2014-01-08 10:01:20 GMT+0800) formated to 2014-01-08
* @see: http://blog.csdn.net/win_lin/article/details/17994347
* @usage absolute_seconds_to_YYYYmmdd(new Date().getTime() / 1000)
*/
function absolute_seconds_to_YYYYmmdd(seconds) {
var date = new Date();
date.setTime(Number(seconds) * 1000);
var ret = date.getFullYear()
+ "-" + padding(date.getMonth() + 1, 2, '0')
+ "-" + padding(date.getDate(), 2, '0');
return ret;
}
/**
* parse the date in str to Date object.
* @param str the date in str, format as "YYYY-mm-dd", for example, 2014-12-11
* @returns a date object.
* @usage YYYYmmdd_parse("2014-12-11")
*/
function YYYYmmdd_parse(str) {
var date = new Date();
date.setTime(Date.parse(str));
return date;
}
/**
* async refresh function call. to avoid multiple call.
* @remark AsyncRefresh is for jquery to refresh the speicified pfn in a page;
* if angularjs, use AsyncRefresh2 to change pfn, cancel previous request for angularjs use singleton object.
* @param refresh_interval the default refresh interval ms.
* @see: http://blog.csdn.net/win_lin/article/details/17994347
* the pfn can be implements as following:
var async_refresh = new AsyncRefresh(pfn, 3000);
function pfn() {
if (!async_refresh.refresh_is_enabled()) {
async_refresh.request(100);
return;
}
$.ajax({
type: 'GET', async: true, url: 'xxxxx',
complete: function(){
if (!async_refresh.refresh_is_enabled()) {
async_refresh.request(0);
} else {
async_refresh.request(async_refresh.refresh_interval);
}
},
success: function(res){
// if donot allow refresh, directly return.
if (!async_refresh.refresh_is_enabled()) {
return;
}
// render the res.
}
});
}
*/
function AsyncRefresh(pfn, refresh_interval) {
this.refresh_interval = refresh_interval;
this.__handler = null;
this.__pfn = pfn;
this.__enabled = true;
}
/**
* disable the refresher, the pfn must check the refresh state.
*/
AsyncRefresh.prototype.refresh_disable = function() {
this.__enabled = false;
}
AsyncRefresh.prototype.refresh_enable = function() {
this.__enabled = true;
}
AsyncRefresh.prototype.refresh_is_enabled = function() {
return this.__enabled;
}
/**
* start new async request
* @param timeout the timeout in ms.
* user can use the refresh_interval of the AsyncRefresh object,
* which initialized in constructor.
*/
AsyncRefresh.prototype.request = function(timeout) {
if (this.__handler) {
clearTimeout(this.__handler);
}
this.__handler = setTimeout(this.__pfn, timeout);
}
/**
* async refresh v2, support cancellable refresh, and change the refresh pfn.
* @remakr for angularjs. if user only need jquery, maybe AsyncRefresh is better.
* @see: http://blog.csdn.net/win_lin/article/details/17994347
* Usage:
bsmControllers.controller('CServers', ['$scope', 'MServer', function($scope, MServer){
async_refresh2.refresh_change(function(){
// 获取服务器列表
MServer.servers_load({}, function(data){
$scope.servers = data.data.servers;
async_refresh2.request();
});
}, 3000);
async_refresh2.request(0);
}]);
bsmControllers.controller('CStreams', ['$scope', 'MStream', function($scope, MStream){
async_refresh2.refresh_change(function(){
// 获取流列表
MStream.streams_load({}, function(data){
$scope.streams = data.data.streams;
async_refresh2.request();
});
}, 3000);
async_refresh2.request(0);
}]);
*/
function AsyncRefresh2() {
/**
* the function callback before call the pfn.
* the protype is function():bool, which return true to invoke, false to abort the call.
* null to ignore this callback.
*
* for example, user can abort the refresh by find the class popover:
* async_refresh2.on_before_call_pfn = function() {
* if ($(".popover").length > 0) {
* async_refresh2.request();
* return false;
* }
* return true;
* };
*/
this.on_before_call_pfn = null;
// use a anonymous function to call, and check the enabled when actually invoke.
this.__call = {
pfn: null,
timeout: 0,
__enabled: false,
__handler: null
};
}
// singleton
var async_refresh2 = new AsyncRefresh2();
/**
* initialize or refresh change. cancel previous request, setup new request.
* @param pfn a function():void to request after timeout. null to disable refresher.
* @param timeout the timeout in ms, to call pfn. null to disable refresher.
*/
AsyncRefresh2.prototype.initialize = function(pfn, timeout) {
this.refresh_change(pfn, timeout);
}
/**
* stop refresh, the refresh pfn is set to null.
*/
AsyncRefresh2.prototype.stop = function() {
this.refresh_change(null, null);
}
/**
* change refresh pfn, the old pfn will set to disabled.
*/
AsyncRefresh2.prototype.refresh_change = function(pfn, timeout) {
// cancel the previous call.
if (this.__call.__handler) {
clearTimeout(this.__handler);
}
this.__call.__enabled = false;
// setup new call.
this.__call = {
pfn: pfn,
timeout: timeout,
__enabled: true,
__handler: null
};
}
/**
* start new request, we never auto start the request,
* user must start new request when previous completed.
* @param timeout [optional] if not specified, use the timeout in initialize or refresh_change.
*/
AsyncRefresh2.prototype.request = function(timeout) {
var self = this;
var this_call = this.__call;
// clear previous timeout.
if (this_call.__handler) {
clearTimeout(this_call.__handler);
}
// override the timeout
if (timeout == undefined) {
timeout = this_call.timeout;
}
// if user disabled refresher.
if (this_call.pfn == null || timeout == null) {
return;
}
this_call.__handler = setTimeout(function(){
// cancelled by refresh_change, ignore.
if (!this_call.__enabled) {
return;
}
// callback if the handler installled.
if (self.on_before_call_pfn) {
if (!self.on_before_call_pfn()) {
return;
}
}
// do the actual call.
this_call.pfn();
}, timeout);
}
// other components.
/**
* jquery/bootstrap pager.
* depends: jquery1.10, boostrap2
* https://code.csdn.net/snippets/146160
* @see: http://blog.csdn.net/win_lin/article/details/17628631
*/

View file

@ -11,6 +11,7 @@
<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>
<script type="text/javascript" src="js/winlin.utility.js"></script>
<style>
body{
padding-top: 55px;

View file

@ -5,9 +5,10 @@
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
setTimeout(function(){
window.location.href = "players/index.html" + window.location.search;
}, 500);
</script>
</body>
</body>
<script type="text/javascript">
setTimeout(function(){
window.location.href = "players/index.html" + window.location.search;
}, 500);
</script>
</html>

View file

@ -4,14 +4,6 @@
<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/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;
@ -21,58 +13,6 @@
margin-left: -350px;
}
</style>
<script type="text/javascript">
function osmf_play(url) {
$("#div_container").remove();
var div_container = $("<div/>");
$(div_container).attr("id", "div_container");
$("#player").append(div_container);
var player = $("<div/>");
$(player).attr("id", "player_id");
$(div_container).append(player);
var flashvars = {};
flashvars.src = url;
flashvars.streamType = "live"; // live or recorded
flashvars.autoPlay = true;
flashvars.controlBarAutoHide = false;
flashvars.scaleMode = "stretch";
flashvars.bufferTime = 0.8;
var params = {};
params.allowFullScreen = true;
var attributes = {};
swfobject.embedSWF(
"js/StrobeMediaPlayback.swf", "player_id",
srs_get_player_width(), srs_get_player_height(),
"11.1", "js/AdobeFlashPlayerInstall.swf",
flashvars, params, attributes
);
}
$(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("#txt_url", null, "#main_modal");
$("#main_modal").on("hide", function(){
osmf_play("http://localhost");
$("#div_container").remove();
});
$("#main_modal").on("show", function(){
var url = $("#txt_url").val();
osmf_play(url);
});
$("#btn_play").click(function(){
$("#main_modal").modal({show:true, keyboard:false});
});
});
</script>
</head>
<body>
<div class="navbar navbar-fixed-top">
@ -120,3 +60,65 @@
</footer>
</div>
</body>
<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/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>
<script type="text/javascript" src="js/winlin.utility.js"></script>
<script type="text/javascript">
function osmf_play(url) {
$("#div_container").remove();
var div_container = $("<div/>");
$(div_container).attr("id", "div_container");
$("#player").append(div_container);
var player = $("<div/>");
$(player).attr("id", "player_id");
$(div_container).append(player);
var flashvars = {};
flashvars.src = url;
flashvars.streamType = "live"; // live or recorded
flashvars.autoPlay = true;
flashvars.controlBarAutoHide = false;
flashvars.scaleMode = "stretch";
flashvars.bufferTime = 0.8;
var params = {};
params.allowFullScreen = true;
var attributes = {};
swfobject.embedSWF(
"js/StrobeMediaPlayback.swf", "player_id",
srs_get_player_width(), srs_get_player_height(),
"11.1", "js/AdobeFlashPlayerInstall.swf",
flashvars, params, attributes
);
}
$(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_rtmp("#txt_url", "#main_modal");
$("#main_modal").on("hide", function(){
osmf_play("http://localhost");
$("#div_container").remove();
});
$("#main_modal").on("show", function(){
var url = $("#txt_url").val();
osmf_play(url);
});
$("#btn_play").click(function(){
$("#main_modal").modal({show:true, keyboard:false});
});
});
</script>
</html>

View file

@ -3,14 +3,16 @@
<head>
<title>SRS</title>
<meta charset="utf-8">
<script type="text/javascript" src="players/js/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="players/js/srs.page.js"></script>
<script type="text/javascript" src="players/js/srs.utility.js"></script>
</head>
<body>
<script type="text/javascript">
setTimeout(function(){
window.location.href = "players/index.html" + window.location.search;
}, 500);
</script>
</body>
<script type="text/javascript" src="players/js/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="players/js/srs.page.js"></script>
<script type="text/javascript" src="players/js/srs.utility.js"></script>
<script type="text/javascript" src="players/js/winlin.utility.js"></script>
<script type="text/javascript">
setTimeout(function(){
window.location.href = "players/index.html" + window.location.search;
}, 500);
</script>
</html>

View file

@ -4,15 +4,6 @@
<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/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>
<script type="text/javascript" src="srs_bwt/src/srs.bandwidth.js"></script>
<style>
body{
padding-top: 55px;
@ -22,62 +13,6 @@
margin-left: -350px;
}
</style>
<script type="text/javascript">
var bandwidth = null;
$(function(){
srs_init_bwt("#txt_url");
$("#btn_play").click(on_click_play);
$("#main_modal").on("show", on_start_bandwidth_test);
$("#main_modal").on("hide", on_stop_bandwidth_test);
});
function on_click_play() {
$("#check_status").text("");
$("#check_info").text("");
$("#progress_bar").width("0%");
$("#main_modal").modal({show:true, keyboard:false});
}
function on_start_bandwidth_test() {
$("#div_container").remove();
$("#progress_bar").removeClass("bar-danger");
var div_container = $("<div/>");
$(div_container).attr("id", "div_container");
$("#player").append(div_container);
var player = $("<div/>");
$(player).attr("id", "player_id");
$(div_container).append(player);
var url = $("#txt_url").val();
bandwidth = new SrsBandwidth("player_id", 100, 1);
bandwidth.on_bandwidth_ready = function() {
this.check_bandwidth(url);
}
bandwidth.on_update_progress = function(percent) {
$("#progress_bar").width(percent + "%");
}
bandwidth.on_update_status = function(status) {
$("#check_status").text(status);
}
bandwidth.on_srs_info = function(srs_server, srs_primary, srs_authors, srs_id, srs_pid, srs_server_ip) {
$("#check_info").text(
"server:" + srs_server + ", primary:" + srs_primary + ", authors:" + srs_authors +
", srs_id:" + srs_id + ", srs_pid:" + srs_pid + ", ip:" + srs_server_ip
);
}
bandwidth.on_error = function(code) {
$("#progress_bar").addClass("bar-danger");
}
bandwidth.render(url);
}
function on_stop_bandwidth_test() {
bandwidth.stop();
}
</script>
</head>
<body>
<div class="navbar navbar-fixed-top">
@ -139,4 +74,70 @@
</div>
</div>
</body>
<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/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>
<script type="text/javascript" src="js/winlin.utility.js"></script>
<script type="text/javascript" src="srs_bwt/src/srs.bandwidth.js"></script>
<script type="text/javascript">
var bandwidth = null;
$(function(){
srs_init_bwt("#txt_url");
$("#btn_play").click(on_click_play);
$("#main_modal").on("show", on_start_bandwidth_test);
$("#main_modal").on("hide", on_stop_bandwidth_test);
});
function on_click_play() {
$("#check_status").text("");
$("#check_info").text("");
$("#progress_bar").width("0%");
$("#main_modal").modal({show:true, keyboard:false});
}
function on_start_bandwidth_test() {
$("#div_container").remove();
$("#progress_bar").removeClass("bar-danger");
var div_container = $("<div/>");
$(div_container).attr("id", "div_container");
$("#player").append(div_container);
var player = $("<div/>");
$(player).attr("id", "player_id");
$(div_container).append(player);
var url = $("#txt_url").val();
bandwidth = new SrsBandwidth("player_id", 100, 1);
bandwidth.on_bandwidth_ready = function() {
this.check_bandwidth(url);
}
bandwidth.on_update_progress = function(percent) {
$("#progress_bar").width(percent + "%");
}
bandwidth.on_update_status = function(status) {
$("#check_status").text(status);
}
bandwidth.on_srs_info = function(srs_server, srs_primary, srs_authors, srs_id, srs_pid, srs_server_ip) {
$("#check_info").text(
"server:" + srs_server + ", primary:" + srs_primary + ", authors:" + srs_authors +
", srs_id:" + srs_id + ", srs_pid:" + srs_pid + ", ip:" + srs_server_ip
);
}
bandwidth.on_error = function(code) {
$("#progress_bar").addClass("bar-danger");
}
bandwidth.render(url);
}
function on_stop_bandwidth_test() {
bandwidth.stop();
}
</script>
</html>

File diff suppressed because it is too large Load diff

View file

@ -4,15 +4,6 @@
<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;
@ -21,7 +12,7 @@
margin-top: -20px;
padding-top: 3px;
}
#div_play_time {
.div_play_time {
margin-top: 10px;
}
#pb_buffer_bg {
@ -29,250 +20,6 @@
margin-bottom: 10px;
}
</style>
<script type="text/javascript">
var srs_player = null;
var url = null;
var __active_dar = null;
function select_dar(dar_id, num, den) {
srs_player.set_dar(num, den);
if (__active_dar) {
__active_dar.removeClass("active");
}
__active_dar = $(dar_id).parent();
__active_dar.addClass("active");
}
var __active_size = null;
function select_fs_size(size_id, refer, percent) {
srs_player.set_fs(refer, percent);
if (__active_size) {
__active_size.removeClass("active");
}
__active_size = $(size_id).parent();
__active_size.addClass("active");
}
var __active_bt = null;
function select_buffer_time(bt_id, buffer_time) {
srs_player.set_bt(buffer_time);
if (__active_bt) {
__active_bt.removeClass("active");
}
__active_bt = $(bt_id).parent();
__active_bt.addClass("active");
}
$(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("#txt_url", null, "#main_modal");
$("#fs_tips").tooltip({
title: "点击视频进入或退出全屏"
});
$("#main_modal").on("show", function(){
if (srs_player) {
return;
}
$("#div_container").remove();
var div_container = $("<div/>");
$(div_container).attr("id", "div_container");
$("#player").append(div_container);
var player = $("<div/>");
$(player).attr("id", "player_id");
$(div_container).append(player);
srs_player = new SrsPlayer("player_id", srs_get_player_width(), srs_get_player_height());
srs_player.on_player_ready = function() {
select_buffer_time("#btn_bt_0_1", 0.1);
this.play(url);
};
srs_player.on_player_metadata = function(metadata) {
$("#btn_dar_original").text("视频原始比例" + "(" + metadata.width + ":" + metadata.height + ")");
select_dar("#btn_dar_original", 0, 0);
select_fs_size("#btn_fs_size_screen_100", "screen", 100);
};
srs_player.on_player_timer = function(time, buffer_length) {
var buffer = buffer_length / this.buffer_time * 100;
$("#pb_buffer").width(Number(buffer).toFixed(1) + "%");
$("#pb_buffer_bg").attr("title",
"缓冲区长度:" + Number(buffer_length).toFixed(1) + "秒("
+ Number(buffer).toFixed(1) + "%)");
var time_str = "";
// day
time_str = padding(parseInt(time / 24 / 3600), 2, '0') + " ";
// hour
time = time % (24 * 3600);
time_str += padding(parseInt(time / 3600), 2, '0') + ":";
// minute
time = time % (3600);
time_str += padding(parseInt(time / 60), 2, '0') + ":";
// seconds
time = time % (60);
time_str += padding(parseInt(time), 2, '0');
// show
$("#txt_time").val(time_str);
};
srs_player.start();
});
$("#main_modal").on("hide", function(){
if ($("#main_modal").is(":visible")) {
return;
}
if (srs_player) {
srs_player.stop();
srs_player = null;
}
});
$("#btn_play").click(function(){
url = $("#txt_url").val();
$("#main_modal").modal({show:true, keyboard:false});
});
$("#btn_pause").click(function(){
if ($("#btn_pause").text() == "暂停") {
$("#btn_pause").text("继续");
srs_player.pause();
} else {
$("#btn_pause").text("暂停");
srs_player.resume();
}
});
$("#srs_publish").click(function(){
url = $("#srs_publish").text();
$("#main_modal").modal({show:true, keyboard:false});
});
$("#srs_publish_ld").click(function(){
url = $("#srs_publish_ld").text();
$("#main_modal").modal({show:true, keyboard:false});
});
$("#srs_publish_sd").click(function(){
url = $("#srs_publish_sd").text();
$("#main_modal").modal({show:true, keyboard:false});
});
$("#srs_publish_fw").click(function(){
url = $("#srs_publish_fw").text();
$("#main_modal").modal({show:true, keyboard:false});
});
$("#srs_publish_fw_ld").click(function(){
url = $("#srs_publish_fw_ld").text();
$("#main_modal").modal({show:true, keyboard:false});
});
$("#srs_publish_fw_sd").click(function(){
url = $("#srs_publish_fw_sd").text();
$("#main_modal").modal({show:true, keyboard:false});
});
var query = parse_query_string();
var jwplayer_url = "http://" + query.host + query.dir + "/jwplayer6.html?vhost=demo.srs.com&app=live&hls_autostart=true";
$("#srs_publish_hls").attr("href", jwplayer_url + "&stream=livestream");
$("#srs_publish_ld_hls").attr("href", jwplayer_url + "&stream=livestream_ld");
$("#srs_publish_sd_hls").attr("href", jwplayer_url + "&stream=livestream_sd");
var jwplayer_url = "http://" + query.host + query.dir + "/jwplayer6.html?vhost=demo.srs.com&app=forward/live&hls_autostart=true";
$("#srs_publish_fw_hls").attr("href", jwplayer_url + "&stream=livestream");
$("#srs_publish_fw_ld_hls").attr("href", jwplayer_url + "&stream=livestream_ld");
$("#srs_publish_fw_sd_hls").attr("href", jwplayer_url + "&stream=livestream_sd");
if (true) {
$("#btn_dar_original").click(function(){
select_dar("#btn_dar_original", 0, 0);
});
$("#btn_dar_21_9").click(function(){
select_dar("#btn_dar_21_9", 21, 9);
});
$("#btn_dar_16_9").click(function(){
select_dar("#btn_dar_16_9", 16, 9);
});
$("#btn_dar_4_3").click(function(){
select_dar("#btn_dar_4_3", 4, 3);
});
$("#btn_dar_fill").click(function(){
select_dar("#btn_dar_fill", -1, -1);
});
}
if (true) {
$("#btn_fs_size_video_100").click(function(){
select_fs_size("#btn_fs_size_video_100", "video", 100);
});
$("#btn_fs_size_video_75").click(function(){
select_fs_size("#btn_fs_size_video_75", "video", 75);
});
$("#btn_fs_size_video_50").click(function(){
select_fs_size("#btn_fs_size_video_50", "video", 50);
});
$("#btn_fs_size_screen_100").click(function(){
select_fs_size("#btn_fs_size_screen_100", "screen", 100);
});
$("#btn_fs_size_screen_75").click(function(){
select_fs_size("#btn_fs_size_screen_75", "screen", 75);
});
$("#btn_fs_size_screen_50").click(function(){
select_fs_size("#btn_fs_size_screen_50", "screen", 50);
});
}
if (true) {
$("#btn_bt_0_1").click(function(){
select_buffer_time("#btn_bt_0_1", 0.1);
});
$("#btn_bt_0_2").click(function(){
select_buffer_time("#btn_bt_0_2", 0.2);
});
$("#btn_bt_0_3").click(function(){
select_buffer_time("#btn_bt_0_3", 0.3);
});
$("#btn_bt_0_5").click(function(){
select_buffer_time("#btn_bt_0_5", 0.5);
});
$("#btn_bt_0_8").click(function(){
select_buffer_time("#btn_bt_0_8", 0.8);
});
$("#btn_bt_1").click(function(){
select_buffer_time("#btn_bt_1", 1);
});
$("#btn_bt_2").click(function(){
select_buffer_time("#btn_bt_2", 2);
});
$("#btn_bt_3").click(function(){
select_buffer_time("#btn_bt_3", 3);
});
$("#btn_bt_5").click(function(){
select_buffer_time("#btn_bt_5", 5);
});
$("#btn_bt_10").click(function(){
select_buffer_time("#btn_bt_10", 10);
});
$("#btn_bt_30").click(function(){
select_buffer_time("#btn_bt_30", 30);
});
}
var query = parse_query_string();
if (query.autostart == "true") {
url = $("#txt_url").val();
$("#main_modal").modal({show:true, keyboard:false});
}
});
</script>
</head>
<body>
<div class="navbar navbar-fixed-top">
@ -300,8 +47,62 @@
</div>
<div class="form-inline">
URL:
<input type="text" id="txt_url" class="input-xxlarge" value=""></input>
<input type="text" id="txt_url" class="input-xxlarge" value="">
<button class="btn btn-primary" id="btn_play">播放视频</button>
<button class="btn" id="btn_generate_link">生成链接</button>
</div>
<div id="link_modal" class="modal hide fade">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3><a href="https://github.com/simple-rtmp-server/srs">SRS Link Generator</a></h3>
</div>
<div class="modal-body">
<div class="form-horizontal">
<div class="control-group">
<label class="control-label" for="link_server">服务器地址</label>
<div class="controls">
<span id="link_server" class="span4 uneditable-input"></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="link_port">服务器端口</label>
<div class="controls">
<span id="link_port" class="span2 uneditable-input"></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="link_vhost">RTMP Vhost</label>
<div class="controls">
<span id="link_vhost" class="span4 uneditable-input"></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="link_app">RTMP App</label>
<div class="controls">
<span id="link_app" class="span4 uneditable-input"></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="link_stream">RTMP Stream</label>
<div class="controls">
<span id="link_stream" class="span4 uneditable-input"></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="link_rtmp">RTMP地址</label>
<div class="controls">
<span id="link_rtmp" class="span4 uneditable-input"></span>
</div>
</div>
<div class="control-group">
<label class="control-label" for="link_url">播放链接地址</label>
<div class="controls">
<div style="margin-top:5px;"><a href="#" id="link_url" target="_blank">请右键拷贝此链接地址.</a></div>
</div>
</div>
</div>
</div>
<div class="modal-footer"></div>
</div>
<div class="container">
<hr/>
@ -480,57 +281,82 @@
</div>
</div>
<div class="modal-footer" id="my_modal_footer">
<div class="input-prepend" id="div_play_time">
<span class="add-on" title="播放时长">@T</span>
<input class="span2" style="width:85px" id="txt_time" type="text" placeholder="天 时:分:秒">
<div>
<div class="btn-group dropup">
<button class="btn dropdown-toggle" data-toggle="dropdown">
设置全屏比例大小<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a id="btn_fs_size_screen_100" href="#">屏幕大小(100%)</a></li>
<li><a id="btn_fs_size_screen_75" href="#">屏幕大小(75%)</a></li>
<li><a id="btn_fs_size_screen_50" href="#">屏幕大小(50%)</a></li>
<li><a id="btn_fs_size_video_100" href="#">视频大小(100%)</a></li>
<li><a id="btn_fs_size_video_75" href="#">视频大小(75%)</a></li>
<li><a id="btn_fs_size_video_50" href="#">视频大小(50%)</a></li>
</ul>
</div>
<div class="btn-group dropup">
<button class="btn dropdown-toggle" data-toggle="dropdown">设置显示比例<span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a id="btn_dar_original" href="#">视频原始比例</a></li>
<li><a id="btn_dar_21_9" href="#">宽屏影院(21:9)</a></li>
<li><a id="btn_dar_16_9" href="#">宽屏电视(16:9)</a></li>
<li><a id="btn_dar_4_3" href="#">窄屏(4:3)</a></li>
<li><a id="btn_dar_fill" href="#">填充(容器比例)</a></li>
</ul>
</div>
<div class="btn-group dropup">
<button class="btn dropdown-toggle" data-toggle="dropdown">设置缓冲区大小<span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a id="btn_bt_0_1" href="#">0.1秒(实时)</a></li>
<li><a id="btn_bt_0_2" href="#">0.2秒(实时)</a></li>
<li><a id="btn_bt_0_3" href="#">0.3秒(实时)</a></li>
<li><a id="btn_bt_0_5" href="#">0.5秒(实时)</a></li>
<li><a id="btn_bt_0_8" href="#">0.8秒(会议)</a></li>
<li><a id="btn_bt_1" href="#">1秒(低延迟)</a></li>
<li><a id="btn_bt_2" href="#">2秒(较低延时)</a></li>
<li><a id="btn_bt_3" href="#">3秒(流畅播放)</a></li>
<li><a id="btn_bt_5" href="#">5秒(网速较低)</a></li>
<li><a id="btn_bt_10" href="#">10秒(无所谓延迟)</a></li>
<li><a id="btn_bt_30" href="#">30秒(流畅第一)</a></li>
</ul>
</div>
<div class="btn-group dropup">
<a id="btn_fullscreen" class="btn">进入全屏</a>
</div>
<div class="btn-group dropup">
<button id="btn_pause" class="btn">暂停播放</button>
<button id="btn_resume" class="btn hide">继续播放</button>
</div>
<div class="btn-group dropup">
<button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">关闭播放器</button>
</div>
</div>
<div class="btn-group dropup">
<button class="btn dropdown-toggle" data-toggle="dropdown">
<a id="fs_tips" href="#" data-toggle="tooltip" data-placement="top" title="">
<img src="img/tooltip.png"/>
</a>
全屏大小<span class="caret"></span>
</button>
<ul class="dropdown-menu">
<li><a id="btn_fs_size_screen_100" href="#">屏幕大小(100%)</a></li>
<li><a id="btn_fs_size_screen_75" href="#">屏幕大小(75%)</a></li>
<li><a id="btn_fs_size_screen_50" href="#">屏幕大小(50%)</a></li>
<li><a id="btn_fs_size_video_100" href="#">视频大小(100%)</a></li>
<li><a id="btn_fs_size_video_75" href="#">视频大小(75%)</a></li>
<li><a id="btn_fs_size_video_50" href="#">视频大小(50%)</a></li>
</ul>
<div class="hide" id="fullscreen_tips">
<font color="red">点击视频</font>进入全屏模式~<br/>
由于安全原因Flash全屏无法使用JS触发
</div>
<div class="btn-group dropup">
<button class="btn dropdown-toggle" data-toggle="dropdown">显示比例<span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a id="btn_dar_original" href="#">视频原始比例</a></li>
<li><a id="btn_dar_21_9" href="#">宽屏影院(21:9)</a></li>
<li><a id="btn_dar_16_9" href="#">宽屏电视(16:9)</a></li>
<li><a id="btn_dar_4_3" href="#">窄屏(4:3)</a></li>
<li><a id="btn_dar_fill" href="#">填充(容器比例)</a></li>
</ul>
</div>
<div class="btn-group dropup">
<button class="btn dropdown-toggle" data-toggle="dropdown">缓冲区<span class="caret"></span></button>
<ul class="dropdown-menu">
<li><a id="btn_bt_0_1" href="#">0.1秒(实时)</a></li>
<li><a id="btn_bt_0_2" href="#">0.2秒(实时)</a></li>
<li><a id="btn_bt_0_3" href="#">0.3秒(实时)</a></li>
<li><a id="btn_bt_0_5" href="#">0.5秒(实时)</a></li>
<li><a id="btn_bt_0_8" href="#">0.8秒(会议)</a></li>
<li><a id="btn_bt_1" href="#">1秒(低延迟)</a></li>
<li><a id="btn_bt_2" href="#">2秒(较低延时)</a></li>
<li><a id="btn_bt_3" href="#">3秒(流畅播放)</a></li>
<li><a id="btn_bt_5" href="#">5秒(网速较低)</a></li>
<li><a id="btn_bt_10" href="#">10秒(无所谓延迟)</a></li>
<li><a id="btn_bt_30" href="#">30秒(流畅第一)</a></li>
</ul>
</div>
<div class="btn-group dropup">
<button id="btn_pause" class="btn">暂停</button>
</div>
<div class="btn-group dropup">
<button class="btn btn-primary" data-dismiss="modal" aria-hidden="true">关闭</button>
<div>
<div class="input-prepend div_play_time" title="视频的播放流畅度">
<span class="add-on">@F</span>
<input class="span2" style="width:57px" id="txt_fluency" type="text" placeholder="100%">
</div>
<div class="input-prepend div_play_time" title="视频总共卡顿次数">
<span class="add-on">@E</span>
<input class="span2" style="width:85px" id="txt_empty_count" type="text" placeholder="0">
</div>
<div class="input-prepend div_play_time" title="视频当前的帧率FPS">
<span class="add-on">@F</span>
<input class="span2" style="width:85px" id="txt_fps" type="text" placeholder="fps">
</div>
<div class="input-prepend div_play_time" title="视频当前的码率(视频+音频)单位Kbps">
<span class="add-on">@B</span>
<input class="span2" style="width:85px" id="txt_bitrate" type="text" placeholder="kbps">
</div>
<div class="input-prepend div_play_time" title="播放时长,格式:天 时:分:秒">
<span class="add-on">@T</span>
<input class="span2" style="width:85px" id="txt_time" type="text" placeholder="天 时:分:秒">
</div>
</div>
</div>
</div>
@ -538,4 +364,282 @@
<p><a href="https://github.com/simple-rtmp-server/srs">SRS Team &copy; 2013</a></p>
</footer>
</div>
</body>
</body>
<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>
<script type="text/javascript" src="js/winlin.utility.js"></script>
<script type="text/javascript">
var srs_player = null;
var url = null;
var __active_dar = null;
function select_dar(dar_id, num, den) {
srs_player.set_dar(num, den);
if (__active_dar) {
__active_dar.removeClass("active");
}
__active_dar = $(dar_id).parent();
__active_dar.addClass("active");
}
var __active_size = null;
function select_fs_size(size_id, refer, percent) {
srs_player.set_fs(refer, percent);
if (__active_size) {
__active_size.removeClass("active");
}
__active_size = $(size_id).parent();
__active_size.addClass("active");
}
var __active_bt = null;
function select_buffer_time(bt_id, buffer_time) {
srs_player.set_bt(buffer_time);
if (__active_bt) {
__active_bt.removeClass("active");
}
__active_bt = $(bt_id).parent();
__active_bt.addClass("active");
}
$(function(){
var query = parse_query_string();
// 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_rtmp("#txt_url", "#main_modal");
$("#main_modal").on("show", function(){
if (srs_player) {
return;
}
$("#div_container").remove();
var div_container = $("<div/>");
$(div_container).attr("id", "div_container");
$("#player").append(div_container);
var player = $("<div/>");
$(player).attr("id", "player_id");
$(div_container).append(player);
srs_player = new SrsPlayer("player_id", srs_get_player_width(), srs_get_player_height());
srs_player.on_player_ready = function() {
select_buffer_time("#btn_bt_0_1", 0.1);
this.play(url);
};
srs_player.on_player_metadata = function(metadata) {
$("#btn_dar_original").text("视频原始比例" + "(" + metadata.width + ":" + metadata.height + ")");
select_dar("#btn_dar_original", 0, 0);
select_fs_size("#btn_fs_size_screen_100", "screen", 100);
};
srs_player.on_player_timer = function(time, buffer_length, kbps, fps, rtime) {
var buffer = buffer_length / this.buffer_time * 100;
$("#pb_buffer").width(Number(buffer).toFixed(1) + "%");
$("#pb_buffer_bg").attr("title",
"缓冲区长度:" + Number(buffer_length).toFixed(1) + "秒("
+ Number(buffer).toFixed(1) + "%)");
$("#txt_bitrate").val(kbps.toFixed(1) + "kbps");
$("#txt_fps").val(fps.toFixed(1) + "fps");
$("#txt_empty_count").val(srs_player.empty_count() + "次卡顿");
$("#txt_fluency").val(srs_player.fluency().toFixed(2) + "%");
var time_str = "";
// day
time_str = padding(parseInt(time / 24 / 3600), 2, '0') + " ";
// hour
time = time % (24 * 3600);
time_str += padding(parseInt(time / 3600), 2, '0') + ":";
// minute
time = time % (3600);
time_str += padding(parseInt(time / 60), 2, '0') + ":";
// seconds
time = time % (60);
time_str += padding(parseInt(time), 2, '0');
// show
$("#txt_time").val(time_str);
};
srs_player.start();
});
$("#main_modal").on("hide", function(){
if (srs_player) {
srs_player.stop();
srs_player = null;
}
});
$("#btn_generate_link").click(function(){
var rtmp = parse_rtmp_url($("#txt_url").val());
var url = "http://" + query.host + query.pathname + "?"
+ "vhost=" + rtmp.vhost + "&app=" + rtmp.app + "&stream=" + rtmp.stream
+ "&server=" + rtmp.server + "&port=" + rtmp.port
+ "&autostart=true";
$("#link_server").text(rtmp.server);
$("#link_port").text(rtmp.port);
$("#link_vhost").text(rtmp.vhost);
$("#link_app").text(rtmp.app);
$("#link_stream").text(rtmp.stream);
$("#link_rtmp").text($("#txt_url").val());
$("#link_url").attr("href", url);
$("#link_modal").modal({show:true, keyboard:true});
});
$("#btn_play").click(function(){
url = $("#txt_url").val();
$("#main_modal").modal({show:true, keyboard:true});
});
$("#btn_fullscreen").click(function(){
$("#fullscreen_tips").toggle();
});
$("#btn_pause").click(function() {
$("#btn_resume").toggle();
$("#btn_pause").toggle();
srs_player.pause();
});
$("#btn_resume").click(function(){
$("#btn_resume").toggle();
$("#btn_pause").toggle();
srs_player.resume();
});
if (true) {
$("#srs_publish").click(function () {
url = $("#srs_publish").text();
$("#main_modal").modal({show: true, keyboard: false});
});
$("#srs_publish_ld").click(function () {
url = $("#srs_publish_ld").text();
$("#main_modal").modal({show: true, keyboard: false});
});
$("#srs_publish_sd").click(function () {
url = $("#srs_publish_sd").text();
$("#main_modal").modal({show: true, keyboard: false});
});
$("#srs_publish_fw").click(function () {
url = $("#srs_publish_fw").text();
$("#main_modal").modal({show: true, keyboard: false});
});
$("#srs_publish_fw_ld").click(function () {
url = $("#srs_publish_fw_ld").text();
$("#main_modal").modal({show: true, keyboard: false});
});
$("#srs_publish_fw_sd").click(function () {
url = $("#srs_publish_fw_sd").text();
$("#main_modal").modal({show: true, keyboard: false});
});
}
var jwplayer_url = "http://" + query.host + query.dir + "/jwplayer6.html?vhost=demo.srs.com&app=live&hls_autostart=true";
if (true) {
$("#srs_publish_hls").attr("href", jwplayer_url + "&stream=livestream");
$("#srs_publish_ld_hls").attr("href", jwplayer_url + "&stream=livestream_ld");
$("#srs_publish_sd_hls").attr("href", jwplayer_url + "&stream=livestream_sd");
var jwplayer_url = "http://" + query.host + query.dir + "/jwplayer6.html?vhost=demo.srs.com&app=forward/live&hls_autostart=true";
$("#srs_publish_fw_hls").attr("href", jwplayer_url + "&stream=livestream");
$("#srs_publish_fw_ld_hls").attr("href", jwplayer_url + "&stream=livestream_ld");
$("#srs_publish_fw_sd_hls").attr("href", jwplayer_url + "&stream=livestream_sd");
}
if (true) {
$("#btn_dar_original").click(function(){
select_dar("#btn_dar_original", 0, 0);
});
$("#btn_dar_21_9").click(function(){
select_dar("#btn_dar_21_9", 21, 9);
});
$("#btn_dar_16_9").click(function(){
select_dar("#btn_dar_16_9", 16, 9);
});
$("#btn_dar_4_3").click(function(){
select_dar("#btn_dar_4_3", 4, 3);
});
$("#btn_dar_fill").click(function(){
select_dar("#btn_dar_fill", -1, -1);
});
}
if (true) {
$("#btn_fs_size_video_100").click(function(){
select_fs_size("#btn_fs_size_video_100", "video", 100);
});
$("#btn_fs_size_video_75").click(function(){
select_fs_size("#btn_fs_size_video_75", "video", 75);
});
$("#btn_fs_size_video_50").click(function(){
select_fs_size("#btn_fs_size_video_50", "video", 50);
});
$("#btn_fs_size_screen_100").click(function(){
select_fs_size("#btn_fs_size_screen_100", "screen", 100);
});
$("#btn_fs_size_screen_75").click(function(){
select_fs_size("#btn_fs_size_screen_75", "screen", 75);
});
$("#btn_fs_size_screen_50").click(function(){
select_fs_size("#btn_fs_size_screen_50", "screen", 50);
});
}
if (true) {
$("#btn_bt_0_1").click(function(){
select_buffer_time("#btn_bt_0_1", 0.1);
});
$("#btn_bt_0_2").click(function(){
select_buffer_time("#btn_bt_0_2", 0.2);
});
$("#btn_bt_0_3").click(function(){
select_buffer_time("#btn_bt_0_3", 0.3);
});
$("#btn_bt_0_5").click(function(){
select_buffer_time("#btn_bt_0_5", 0.5);
});
$("#btn_bt_0_8").click(function(){
select_buffer_time("#btn_bt_0_8", 0.8);
});
$("#btn_bt_1").click(function(){
select_buffer_time("#btn_bt_1", 1);
});
$("#btn_bt_2").click(function(){
select_buffer_time("#btn_bt_2", 2);
});
$("#btn_bt_3").click(function(){
select_buffer_time("#btn_bt_3", 3);
});
$("#btn_bt_5").click(function(){
select_buffer_time("#btn_bt_5", 5);
});
$("#btn_bt_10").click(function(){
select_buffer_time("#btn_bt_10", 10);
});
$("#btn_bt_30").click(function(){
select_buffer_time("#btn_bt_30", 30);
});
}
var query = parse_query_string();
if (query.autostart == "true") {
url = $("#txt_url").val();
$("#main_modal").modal({show:true, keyboard:false});
}
});
</script>
</html>

View file

@ -38,3 +38,4 @@
<buildCSSFiles/>
<flashCatalyst validateFlashCatalystCompatibility="false"/>
</actionScriptProperties>

View file

@ -18,6 +18,7 @@ package
import flash.ui.ContextMenu;
import flash.ui.ContextMenuItem;
import flash.utils.Timer;
import flash.utils.getTimer;
import flash.utils.setTimeout;
import flashx.textLayout.formats.Float;
@ -30,7 +31,9 @@ package
private var js_on_player_ready:String = null;
private var js_on_player_metadata:String = null;
private var js_on_player_timer:String = null;
private var js_on_player_empty:String = null;
private var js_on_player_full:String = null;
// play param url.
private var user_url:String = null;
// play param, user set width and height
@ -93,6 +96,8 @@ package
this.js_on_player_ready = flashvars.on_player_ready;
this.js_on_player_metadata = flashvars.on_player_metadata;
this.js_on_player_timer = flashvars.on_player_timer;
this.js_on_player_empty = flashvars.on_player_empty;
this.js_on_player_full = flashvars.on_player_full;
this.media_timer.addEventListener(TimerEvent.TIMER, this.system_on_timer);
this.media_timer.start();
@ -106,7 +111,7 @@ package
*/
private function system_on_js_ready():void {
if (!flash.external.ExternalInterface.available) {
trace("js not ready, try later.");
log("js not ready, try later.");
flash.utils.setTimeout(this.system_on_js_ready, 100);
return;
}
@ -114,7 +119,7 @@ package
flash.external.ExternalInterface.addCallback("__play", this.js_call_play);
flash.external.ExternalInterface.addCallback("__stop", this.js_call_stop);
flash.external.ExternalInterface.addCallback("__pause", this.js_call_pause);
flash.external.ExternalInterface.addCallback("__resume", this.js_call_resume);
flash.external.ExternalInterface.addCallback("__resume", this.js_call_resume);
flash.external.ExternalInterface.addCallback("__set_dar", this.js_call_set_dar);
flash.external.ExternalInterface.addCallback("__set_fs", this.js_call_set_fs_size);
flash.external.ExternalInterface.addCallback("__set_bt", this.js_call_set_bt);
@ -126,15 +131,39 @@ package
* system callack event, timer to do some regular tasks.
*/
private function system_on_timer(evt:TimerEvent):void {
if (!this.media_stream) {
trace("stream is null, ignore timer event.");
var ms:NetStream = this.media_stream;
if (!ms) {
log("stream is null, ignore timer event.");
return;
}
trace("notify js the timer event.");
var rtime:Number = flash.utils.getTimer();
var bitrate:Number = Number((ms.info.videoBytesPerSecond + ms.info.audioBytesPerSecond) * 8 / 1000);
log("on timer, time=" + ms.time.toFixed(2) + "s, buffer=" + ms.bufferLength.toFixed(2) + "s"
+ ", bitrate=" + bitrate.toFixed(1) + "kbps"
+ ", fps=" + ms.currentFPS.toFixed(1)
+ ", rtime=" + rtime.toFixed(0)
);
flash.external.ExternalInterface.call(
this.js_on_player_timer, this.js_id, this.media_stream.time, this.media_stream.bufferLength);
this.js_on_player_timer, this.js_id, ms.time, ms.bufferLength,
bitrate, ms.currentFPS, rtime
);
}
/**
* system callback event, when stream is empty.
*/
private function system_on_buffer_empty():void {
var time:Number = flash.utils.getTimer();
log("stream is empty at " + time + "ms");
flash.external.ExternalInterface.call(this.js_on_player_empty, this.js_id, time);
}
private function system_on_buffer_full():void {
var time:Number = flash.utils.getTimer();
log("stream is full at " + time + "ms");
flash.external.ExternalInterface.call(this.js_on_player_full, this.js_id, time);
}
/**
* system callack event, when got metadata from stream.
@ -181,7 +210,7 @@ package
*/
private function user_on_click_video(evt:MouseEvent):void {
if (!this.stage.allowsFullScreen) {
trace("donot allow fullscreen.");
log("donot allow fullscreen.");
return;
}
@ -266,6 +295,7 @@ package
this.media_conn.close();
this.media_conn = null;
}
log("player stopped");
}
// srs infos
@ -311,7 +341,7 @@ package
this.user_url = url;
this.user_w = _width;
this.user_h = _height;
trace("start to play url: " + this.user_url + ", w=" + this.user_w + ", h=" + this.user_h);
log("start to play url: " + this.user_url + ", w=" + this.user_w + ", h=" + this.user_h);
js_call_stop();
@ -358,7 +388,11 @@ package
if (evt.info.code == "NetStream.Video.DimensionChange") {
system_on_metadata(media_metadata);
}
} else if (evt.info.code == "NetStream.Buffer.Empty") {
system_on_buffer_empty();
} else if (evt.info.code == "NetStream.Buffer.Full") {
system_on_buffer_full();
}
// TODO: FIXME: failed event.
});
@ -460,7 +494,11 @@ package
}
// rescale to fs
__update_video_size(num, den, obj.width * user_fs_percent / 100, obj.height * user_fs_percent / 100, this.stage.fullScreenWidth, this.stage.fullScreenHeight);
__update_video_size(num, den,
obj.width * user_fs_percent / 100,
obj.height * user_fs_percent / 100,
this.stage.fullScreenWidth, this.stage.fullScreenHeight
);
}
/**
@ -539,5 +577,18 @@ package
this.control_fs_mask.graphics.drawRect(0, 0, _width, _height);
this.control_fs_mask.graphics.endFill();
}
private function log(msg:String):void {
msg = "[" + new Date() +"][srs-player][" + js_id + "] " + msg;
trace(msg);
if (!flash.external.ExternalInterface.available) {
flash.utils.setTimeout(log, 300, msg);
return;
}
ExternalInterface.call("console.log", msg);
}
}
}

View file

@ -4,213 +4,11 @@
<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 remote_player = null;
var realtime_player = null;
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("#txt_url", null, null);
if (query.agent == "true") {
document.write(navigator.userAgent);
return;
}
$("#btn_video_settings").click(function(){
$("#video_modal").modal({show:true});
});
$("#btn_audio_settings").click(function(){
$("#audio_modal").modal({show:true});
});
$("#remote_tips").tooltip({
title: "为了支持HLS输出FLASH编码器输出的流需要经过转码(VP6=>H264,MP3=>aac),所以会黑屏较长时间,请耐心等待"
});
$("#low_latecy_tips").tooltip({
title: "服务器不转码直接转发FLASH编码器的流所以延迟比支持HLS的流要低很多"
});
$("#realtime_player_url").tooltip({
title: "右键复制RTMP地址"
});
$("#remote_player_url").tooltip({
title: "右键复制RTMP地址"
});
$("#btn_publish").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_publisher_initialize_page(
cameras, microphones,
"#sl_cameras", "#sl_microphones",
"#sl_vcodec", "#sl_profile", "#sl_level", "#sl_gop", "#sl_size",
"#sl_fps", "#sl_bitrate",
"#sl_acodec"
);
};
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 specified, donot show the player, for debug the publisher.
if (query.no_play != "true") {
// start the normal player with HLS supported.
remote_player = new SrsPlayer("remote_player", 430, 185);
remote_player.on_player_ready = function() {
this.set_bt(0.8);
};
remote_player.on_player_metadata = function(metadata) {
this.set_dar(0, 0);
this.set_fs("screen", 100);
}
remote_player.start();
// start the realtime player.
realtime_player = new SrsPlayer("realtime_player", 430, 185);
realtime_player.on_player_ready = function() {
this.set_bt(0.8);
};
realtime_player.on_player_metadata = function(metadata) {
this.set_dar(0, 0);
this.set_fs("screen", 100);
}
realtime_player.start();
}
});
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;
}
/**
* we generate the transcoded stream url for flash publish donot support HLS
* which requires aac, so the publish vhost maybe players for example, we
* use players_pub vhost(transcoded stream to which) for all clients,
* both players and players_pub are write HLS to the sample dir,
* it's ok for the players vhost disabled the HLS, only the
* players_pub enalbed HLS.
*/
function update_play_url() {
var url = $("#txt_url").val();
var ret = srs_parse_rtmp_url(url);
var remote_url = "rtmp://" + ret.server + ":" + ret.port + "/" + ret.app + "...vhost..." + srs_get_player_publish_vhost(ret.vhost) + "/" + ret.stream;
$("#realtime_player_url").attr("href", url).attr("target", "_blank");
$("#remote_player_url").attr("href", remote_url).attr("target", "_blank");
var srs_player_url = "http://" + query.host + query.dir + "/srs_player.html?";
srs_player_url += "vhost=" + srs_get_player_publish_vhost(ret.vhost) + "&port=" + ret.port + "&app=" + ret.app + "&stream=" + ret.stream;
srs_player_url += "&autostart=true";
var srs_player_rt_url = "http://" + query.host + query.dir + "/srs_player.html?";
srs_player_rt_url += "vhost=" + ret.vhost + "&port=" + ret.port + "&app=" + ret.app + "&stream=" + ret.stream;
srs_player_rt_url += "&autostart=true";
var jwplayer_url = "http://" + query.host + query.dir + "/jwplayer6.html?";
jwplayer_url += "vhost=" + srs_get_player_publish_vhost(ret.vhost) + "&port=" + ret.port + "&app=" + ret.app + "&stream=" + ret.stream;
jwplayer_url += "&hls_autostart=true";
var hls_url = "http://" + ret.server + ":" + query.http_port + "/" + ret.app + "/" + ret.stream + ".m3u8";
$("#txt_play_realtime").text("RTMP低延时(点击打开)").attr("href", srs_player_rt_url).attr("target", "_blank");
$("#txt_play_url").text("RTMP已转码(点击打开)").attr("href", srs_player_url).attr("target", "_blank");
$("#txt_play_hls").text("HLS-m3u8(点击打开或右键复制)").attr("href", hls_url).attr("target", "_blank");
$("#txt_play_jwplayer").text("HLS-JWPlayer(点击打开)").attr("href", jwplayer_url).attr("target", "_blank");
}
function on_user_publish() {
if ($("#btn_publish").text() == "停止发布") {
srs_publisher.stop();
$("#btn_publish").text("发布视频");
//$("#txt_play_realtime").text("RTMP低延时(请发布视频)").attr("href", "#").attr("target", "_self");
//$("#txt_play_realtime").attr("href", "#").attr("target", "_self");
//$("#txt_play_url").text("RTMP已转码(请发布视频)").attr("href", "#").attr("target", "_self");
//$("#remote_player_url").attr("href", "#").attr("target", "_self");
//$("#txt_play_hls").text("HLS-m3u8(请发布视频)").attr("href", "#").attr("target", "_self");
//$("#txt_play_jwplayer").text("HLS-JWPlayer(请发布视频)").attr("href", "#").attr("target", "_self");
if (!on_publish_stop()) {
return;
}
return;
}
$("#btn_publish").text("停止发布");
update_play_url();
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",
"#sl_acodec"
);
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);
}
if (remote_player) {
// the normal player should play the transcoded stream in another vhost.
// for example, publish stream to vhost players,
// the realtime player play the vhost players, which may donot support HLS,
// the normal player play the vhost players_pub, which transcoded to h264/aac with HLS.
var ret = srs_parse_rtmp_url(url);
var pub_url = "rtmp://" + ret.server + ":" + ret.port + "/" + ret.app;
pub_url += "?vhost=" + srs_get_player_publish_vhost(ret.vhost) + "/" + ret.stream;
remote_player.stop();
remote_player.play(pub_url);
}
}
</script>
</head>
<body>
<div class="navbar navbar-fixed-top">
@ -464,4 +262,208 @@
</footer>
</div>
</body>
<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>
<script type="text/javascript" src="js/winlin.utility.js"></script>
<script type="text/javascript">
var srs_publisher = null;
var remote_player = null;
var realtime_player = null;
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_rtmp("#txt_url", null);
if (query.agent == "true") {
document.write(navigator.userAgent);
return;
}
$("#btn_video_settings").click(function(){
$("#video_modal").modal({show:true});
});
$("#btn_audio_settings").click(function(){
$("#audio_modal").modal({show:true});
});
$("#remote_tips").tooltip({
title: "为了支持HLS输出FLASH编码器输出的流需要经过转码(VP6=>H264,MP3=>aac),所以会黑屏较长时间,请耐心等待"
});
$("#low_latecy_tips").tooltip({
title: "服务器不转码直接转发FLASH编码器的流所以延迟比支持HLS的流要低很多"
});
$("#realtime_player_url").tooltip({
title: "右键复制RTMP地址"
});
$("#remote_player_url").tooltip({
title: "右键复制RTMP地址"
});
$("#btn_publish").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_publisher_initialize_page(
cameras, microphones,
"#sl_cameras", "#sl_microphones",
"#sl_vcodec", "#sl_profile", "#sl_level", "#sl_gop", "#sl_size",
"#sl_fps", "#sl_bitrate",
"#sl_acodec"
);
};
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 specified, donot show the player, for debug the publisher.
if (query.no_play != "true") {
// start the normal player with HLS supported.
remote_player = new SrsPlayer("remote_player", 430, 185);
remote_player.on_player_ready = function() {
this.set_bt(0.8);
};
remote_player.on_player_metadata = function(metadata) {
this.set_dar(0, 0);
this.set_fs("screen", 100);
}
remote_player.start();
// start the realtime player.
realtime_player = new SrsPlayer("realtime_player", 430, 185);
realtime_player.on_player_ready = function() {
this.set_bt(0.8);
};
realtime_player.on_player_metadata = function(metadata) {
this.set_dar(0, 0);
this.set_fs("screen", 100);
}
realtime_player.start();
}
});
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;
}
/**
* we generate the transcoded stream url for flash publish donot support HLS
* which requires aac, so the publish vhost maybe players for example, we
* use players_pub vhost(transcoded stream to which) for all clients,
* both players and players_pub are write HLS to the sample dir,
* it's ok for the players vhost disabled the HLS, only the
* players_pub enalbed HLS.
*/
function update_play_url() {
var url = $("#txt_url").val();
var ret = srs_parse_rtmp_url(url);
var remote_url = "rtmp://" + ret.server + ":" + ret.port + "/" + ret.app + "...vhost..." + srs_get_player_publish_vhost(ret.vhost) + "/" + ret.stream;
$("#realtime_player_url").attr("href", url).attr("target", "_blank");
$("#remote_player_url").attr("href", remote_url).attr("target", "_blank");
var srs_player_url = "http://" + query.host + query.dir + "/srs_player.html?";
srs_player_url += "vhost=" + srs_get_player_publish_vhost(ret.vhost) + "&port=" + ret.port + "&app=" + ret.app + "&stream=" + ret.stream;
srs_player_url += "&autostart=true";
var srs_player_rt_url = "http://" + query.host + query.dir + "/srs_player.html?";
srs_player_rt_url += "vhost=" + ret.vhost + "&port=" + ret.port + "&app=" + ret.app + "&stream=" + ret.stream;
srs_player_rt_url += "&autostart=true";
var jwplayer_url = "http://" + query.host + query.dir + "/jwplayer6.html?";
jwplayer_url += "vhost=" + srs_get_player_publish_vhost(ret.vhost) + "&port=" + ret.port + "&app=" + ret.app + "&stream=" + ret.stream;
jwplayer_url += "&hls_autostart=true";
var hls_url = "http://" + ret.server + ":" + query.http_port + "/" + ret.app + "/" + ret.stream + ".m3u8";
$("#txt_play_realtime").text("RTMP低延时(点击打开)").attr("href", srs_player_rt_url).attr("target", "_blank");
$("#txt_play_url").text("RTMP已转码(点击打开)").attr("href", srs_player_url).attr("target", "_blank");
$("#txt_play_hls").text("HLS-m3u8(点击打开或右键复制)").attr("href", hls_url).attr("target", "_blank");
$("#txt_play_jwplayer").text("HLS-JWPlayer(点击打开)").attr("href", jwplayer_url).attr("target", "_blank");
}
function on_user_publish() {
if ($("#btn_publish").text() == "停止发布") {
srs_publisher.stop();
$("#btn_publish").text("发布视频");
//$("#txt_play_realtime").text("RTMP低延时(请发布视频)").attr("href", "#").attr("target", "_self");
//$("#txt_play_realtime").attr("href", "#").attr("target", "_self");
//$("#txt_play_url").text("RTMP已转码(请发布视频)").attr("href", "#").attr("target", "_self");
//$("#remote_player_url").attr("href", "#").attr("target", "_self");
//$("#txt_play_hls").text("HLS-m3u8(请发布视频)").attr("href", "#").attr("target", "_self");
//$("#txt_play_jwplayer").text("HLS-JWPlayer(请发布视频)").attr("href", "#").attr("target", "_self");
if (!on_publish_stop()) {
return;
}
return;
}
$("#btn_publish").text("停止发布");
update_play_url();
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",
"#sl_acodec"
);
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);
}
if (remote_player) {
// the normal player should play the transcoded stream in another vhost.
// for example, publish stream to vhost players,
// the realtime player play the vhost players, which may donot support HLS,
// the normal player play the vhost players_pub, which transcoded to h264/aac with HLS.
var ret = srs_parse_rtmp_url(url);
var pub_url = "rtmp://" + ret.server + ":" + ret.port + "/" + ret.app;
pub_url += "?vhost=" + srs_get_player_publish_vhost(ret.vhost) + "/" + ret.stream;
remote_player.stop();
remote_player.play(pub_url);
}
}
</script>
</html>

View file

@ -4,21 +4,11 @@
<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/srs.page.js"></script>
<style>
body{
padding-top: 55px;
}
</style>
<script type="text/javascript">
$(function(){
update_nav();
$("#main_frame").attr("src", "http://www.videolan.org/vlc/");
});
</script>
</head>
<body>
<div class="navbar navbar-fixed-top">
@ -49,4 +39,15 @@
</footer>
</div>
</body>
<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/srs.page.js"></script>
<script type="text/javascript">
$(function(){
update_nav();
$("#main_frame").attr("src", "http://www.videolan.org/vlc/");
});
</script>
</html>