mirror of
https://github.com/ossrs/srs.git
synced 2025-02-13 03:41:55 +00:00
add buffer time and play time display
This commit is contained in:
parent
065cbbe4aa
commit
21c6001210
4 changed files with 204 additions and 43 deletions
|
@ -1,3 +1,16 @@
|
|||
/**
|
||||
* 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* update the navigator, add same query string.
|
||||
*/
|
||||
|
@ -88,7 +101,7 @@ function srs_init(rtmp_url, hls_url) {
|
|||
/**
|
||||
* the SrsPlayer object.
|
||||
*/
|
||||
function SrsPlayer(container, stream_url, width, height, buffer_time) {
|
||||
function SrsPlayer(container, stream_url, width, height) {
|
||||
if (!SrsPlayer.__id) {
|
||||
SrsPlayer.__id = 100;
|
||||
}
|
||||
|
@ -102,12 +115,14 @@ function SrsPlayer(container, stream_url, width, height, buffer_time) {
|
|||
this.stream_url = stream_url;
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.buffer_time = buffer_time;
|
||||
this.id = SrsPlayer.__id++;
|
||||
this.callbackObj = null;
|
||||
this.buffer_time = 0.8; // default to 0.8
|
||||
|
||||
// callback set the following values.
|
||||
this.meatadata = {}; // for on_player_metadata
|
||||
this.time = 0; // current stream time.
|
||||
this.buffer_length = 0; // current stream buffer length.
|
||||
}
|
||||
/**
|
||||
* user can set some callback, then start the player.
|
||||
|
@ -121,6 +136,7 @@ SrsPlayer.prototype.start = function() {
|
|||
flashvars.id = this.id;
|
||||
flashvars.on_player_ready = "__srs_on_player_ready";
|
||||
flashvars.on_player_metadata = "__srs_on_player_metadata";
|
||||
flashvars.on_player_timer = "__srs_on_player_timer";
|
||||
|
||||
var params = {};
|
||||
params.wmode = "opaque";
|
||||
|
@ -144,7 +160,7 @@ SrsPlayer.prototype.start = function() {
|
|||
return this;
|
||||
}
|
||||
SrsPlayer.prototype.play = function() {
|
||||
return this.callbackObj.ref.__play(this.stream_url, this.width, this.height, this.buffer_time);
|
||||
this.callbackObj.ref.__play(this.stream_url, this.width, this.height, this.buffer_time);
|
||||
}
|
||||
SrsPlayer.prototype.stop = function() {
|
||||
for (var i = 0; i < SrsPlayer.__players.length; i++) {
|
||||
|
@ -157,13 +173,14 @@ SrsPlayer.prototype.stop = function() {
|
|||
SrsPlayer.__players.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
return this.callbackObj.ref.__stop();
|
||||
|
||||
this.callbackObj.ref.__stop();
|
||||
}
|
||||
SrsPlayer.prototype.pause = function() {
|
||||
return this.callbackObj.ref.__pause();
|
||||
this.callbackObj.ref.__pause();
|
||||
}
|
||||
SrsPlayer.prototype.resume = function() {
|
||||
return this.callbackObj.ref.__resume();
|
||||
this.callbackObj.ref.__resume();
|
||||
}
|
||||
/**
|
||||
* to set the DAR, for example, DAR=16:9
|
||||
|
@ -175,7 +192,7 @@ SrsPlayer.prototype.resume = function() {
|
|||
* use user specified width if -1.
|
||||
*/
|
||||
SrsPlayer.prototype.dar = function(num, den) {
|
||||
return this.callbackObj.ref.__dar(num, den);
|
||||
this.callbackObj.ref.__dar(num, den);
|
||||
}
|
||||
/**
|
||||
* set the fullscreen size data.
|
||||
|
@ -186,13 +203,24 @@ SrsPlayer.prototype.dar = function(num, den) {
|
|||
* 100 means 100%.
|
||||
*/
|
||||
SrsPlayer.prototype.set_fs = function(refer, percent) {
|
||||
return this.callbackObj.ref.__set_fs(refer, percent);
|
||||
this.callbackObj.ref.__set_fs(refer, percent);
|
||||
}
|
||||
/**
|
||||
* set the stream buffer time in seconds.
|
||||
* @buffer_time the buffer time in seconds.
|
||||
*/
|
||||
SrsPlayer.prototype.set_bt = function(buffer_time) {
|
||||
this.buffer_time = buffer_time;
|
||||
this.callbackObj.ref.__set_bt(buffer_time);
|
||||
}
|
||||
SrsPlayer.prototype.on_player_ready = function() {
|
||||
return this.play();
|
||||
this.play();
|
||||
}
|
||||
SrsPlayer.prototype.on_player_metadata = function(metadata) {
|
||||
return 0;
|
||||
// ignore.
|
||||
}
|
||||
SrsPlayer.prototype.on_player_timer = function(time, buffer_length) {
|
||||
// ignore.
|
||||
}
|
||||
function __srs_on_player_ready(id) {
|
||||
for (var i = 0; i < SrsPlayer.__players.length; i++) {
|
||||
|
@ -202,7 +230,8 @@ function __srs_on_player_ready(id) {
|
|||
continue;
|
||||
}
|
||||
|
||||
return player.on_player_ready();
|
||||
player.on_player_ready();
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error("player not found. id=" + id);
|
||||
|
@ -219,7 +248,30 @@ function __srs_on_player_metadata(id, metadata) {
|
|||
// so set the data before invoke it.
|
||||
player.metadata = metadata;
|
||||
|
||||
return player.on_player_metadata(metadata);
|
||||
player.on_player_metadata(metadata);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error("player not found. id=" + id);
|
||||
}
|
||||
function __srs_on_player_timer(id, time, buffer_length) {
|
||||
for (var i = 0; i < SrsPlayer.__players.length; i++) {
|
||||
var player = SrsPlayer.__players[i];
|
||||
|
||||
if (player.id != id) {
|
||||
continue;
|
||||
}
|
||||
|
||||
buffer_length = Math.max(0, buffer_length);
|
||||
buffer_length = Math.min(player.buffer_time, buffer_length);
|
||||
|
||||
// user may override the on_player_timer,
|
||||
// so set the data before invoke it.
|
||||
player.time = time;
|
||||
player.buffer_length = buffer_length;
|
||||
|
||||
player.on_player_timer(time, buffer_length);
|
||||
return;
|
||||
}
|
||||
|
||||
throw new Error("player not found. id=" + id);
|
||||
|
|
|
@ -40,6 +40,18 @@
|
|||
__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
|
||||
|
@ -68,15 +80,38 @@
|
|||
|
||||
var url = $("#txt_url").val();
|
||||
|
||||
srs_player = new SrsPlayer("player_id", url, 530, 300, 0.8);
|
||||
srs_player = new SrsPlayer("player_id", url, 530, 300);
|
||||
srs_player.on_player_ready = function() {
|
||||
return srs_player.play();
|
||||
srs_player.play();
|
||||
}
|
||||
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);
|
||||
return 0;
|
||||
select_buffer_time("#btn_bt_0_8", 0.8);
|
||||
}
|
||||
srs_player.on_player_timer = function(time, buffer_length) {
|
||||
var buffer = buffer_length / srs_player.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();
|
||||
});
|
||||
|
@ -97,11 +132,11 @@
|
|||
});
|
||||
|
||||
$("#btn_pause").click(function(){
|
||||
if ($("#btn_pause").text() == "暂停播放") {
|
||||
$("#btn_pause").text("继续播放");
|
||||
if ($("#btn_pause").text() == "暂停") {
|
||||
$("#btn_pause").text("继续");
|
||||
srs_player.pause();
|
||||
} else {
|
||||
$("#btn_pause").text("暂停播放");
|
||||
$("#btn_pause").text("暂停");
|
||||
srs_player.resume();
|
||||
}
|
||||
});
|
||||
|
@ -144,6 +179,33 @@
|
|||
select_fs_size("#btn_fs_size_screen_50", "screen", 50);
|
||||
});
|
||||
}
|
||||
|
||||
if (true) {
|
||||
$("#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);
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</head>
|
||||
|
@ -180,15 +242,23 @@
|
|||
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
|
||||
<h3>SrsPlayer</h3>
|
||||
</div>
|
||||
<div class="modal-body" id="player">
|
||||
<div class="modal-body">
|
||||
<div id="player"></div>
|
||||
<div class="progress progress-striped active" id="pb_buffer_bg">
|
||||
<div class="bar" style="width: 0%;" id="pb_buffer"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<div class="modal-footer" style="margin-top:-20px;">
|
||||
<div class="input-prepend" style="margin-top: 10px;">
|
||||
<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">
|
||||
<a id="fs_tips" href="#" data-toggle="tooltip" data-placement="top" title="">
|
||||
<img src="img/tooltip.png"/>
|
||||
</a>
|
||||
全屏大小<span class="caret"></span>
|
||||
大小<span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="btn_fs_size_screen_100" href="#">屏幕大小(100%)</a></li>
|
||||
|
@ -200,7 +270,7 @@
|
|||
</ul>
|
||||
</div>
|
||||
<div class="btn-group dropup">
|
||||
<button class="btn dropdown-toggle" data-toggle="dropdown">显示比例<span class="caret"></span></button>
|
||||
<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>
|
||||
|
@ -210,7 +280,20 @@
|
|||
</ul>
|
||||
</div>
|
||||
<div class="btn-group dropup">
|
||||
<button id="btn_pause" class="btn">暂停播放</button>
|
||||
<button class="btn dropdown-toggle" data-toggle="dropdown">缓冲区<span class="caret"></span></button>
|
||||
<ul class="dropdown-menu">
|
||||
<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>
|
||||
|
|
Binary file not shown.
|
@ -8,6 +8,7 @@ package
|
|||
import flash.events.FullScreenEvent;
|
||||
import flash.events.MouseEvent;
|
||||
import flash.events.NetStatusEvent;
|
||||
import flash.events.TimerEvent;
|
||||
import flash.external.ExternalInterface;
|
||||
import flash.media.Video;
|
||||
import flash.net.NetConnection;
|
||||
|
@ -15,6 +16,7 @@ package
|
|||
import flash.system.Security;
|
||||
import flash.ui.ContextMenu;
|
||||
import flash.ui.ContextMenuItem;
|
||||
import flash.utils.Timer;
|
||||
import flash.utils.setTimeout;
|
||||
|
||||
public class srs_player extends Sprite
|
||||
|
@ -24,6 +26,7 @@ package
|
|||
// user set callback
|
||||
private var on_player_ready:String = null;
|
||||
private var on_player_metadata:String = null;
|
||||
private var on_player_timer:String = null;
|
||||
|
||||
// play param url.
|
||||
private var url:String = null;
|
||||
|
@ -41,6 +44,7 @@ package
|
|||
private var stream:NetStream = null;
|
||||
private var video:Video = null;
|
||||
private var metadata:Object = {};
|
||||
private var timer:Timer = new Timer(300);
|
||||
|
||||
// flash donot allow js to set to fullscreen,
|
||||
// only allow user click to enter fullscreen.
|
||||
|
@ -82,10 +86,25 @@ package
|
|||
this.id = flashvars.id;
|
||||
this.on_player_ready = flashvars.on_player_ready;
|
||||
this.on_player_metadata = flashvars.on_player_metadata;
|
||||
this.on_player_timer = flashvars.on_player_timer;
|
||||
|
||||
this.timer.addEventListener(TimerEvent.TIMER, this.on_timer);
|
||||
this.timer.start();
|
||||
|
||||
flash.utils.setTimeout(this.on_js_ready, 0);
|
||||
}
|
||||
|
||||
private function on_timer(evt:TimerEvent):void {
|
||||
if (!this.stream) {
|
||||
trace("stream is null, ignore timer event.");
|
||||
return;
|
||||
}
|
||||
|
||||
trace("notify js the timer event.");
|
||||
flash.external.ExternalInterface.call(
|
||||
this.on_player_timer, this.id, this.stream.time, this.stream.bufferLength);
|
||||
}
|
||||
|
||||
private function on_stage_fullscreen(evt:FullScreenEvent):void {
|
||||
if (!evt.fullScreen) {
|
||||
execute_user_set_dar();
|
||||
|
@ -107,25 +126,21 @@ package
|
|||
flash.external.ExternalInterface.addCallback("__resume", this.js_call_resume);
|
||||
flash.external.ExternalInterface.addCallback("__dar", this.js_call_dar);
|
||||
flash.external.ExternalInterface.addCallback("__set_fs", this.js_call_set_fs_size);
|
||||
flash.external.ExternalInterface.addCallback("__set_bt", this.js_call_set_bt);
|
||||
|
||||
var code:int = flash.external.ExternalInterface.call(this.on_player_ready, this.id);
|
||||
if (code != 0) {
|
||||
throw new Error("callback on_player_ready failed. code=" + code);
|
||||
}
|
||||
flash.external.ExternalInterface.call(this.on_player_ready, this.id);
|
||||
}
|
||||
|
||||
private function js_call_pause():int {
|
||||
private function js_call_pause():void {
|
||||
if (this.stream) {
|
||||
this.stream.pause();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function js_call_resume():int {
|
||||
private function js_call_resume():void {
|
||||
if (this.stream) {
|
||||
this.stream.resume();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -137,12 +152,11 @@ package
|
|||
* use metadata width if 0.
|
||||
* use user specified width if -1.
|
||||
*/
|
||||
private function js_call_dar(num:int, den:int):int {
|
||||
private function js_call_dar(num:int, den:int):void {
|
||||
dar_num = num;
|
||||
dar_den = den;
|
||||
|
||||
flash.utils.setTimeout(execute_user_set_dar, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -153,11 +167,9 @@ package
|
|||
* @param percent, the rescale percent, where
|
||||
* 100 means 100%.
|
||||
*/
|
||||
private function js_call_set_fs_size(refer:String, percent:int):int {
|
||||
private function js_call_set_fs_size(refer:String, percent:int):void {
|
||||
fs_refer = refer;
|
||||
fs_percent = percent;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/**
|
||||
* js cannot enter the fullscreen mode, user must click to.
|
||||
|
@ -176,7 +188,17 @@ package
|
|||
}
|
||||
}
|
||||
|
||||
private function js_call_stop():int {
|
||||
/**
|
||||
* set the stream buffer time in seconds.
|
||||
* @buffer_time the buffer time in seconds.
|
||||
*/
|
||||
private function js_call_set_bt(buffer_time:Number):void {
|
||||
if (this.stream) {
|
||||
this.stream.bufferTime = buffer_time;
|
||||
}
|
||||
}
|
||||
|
||||
private function js_call_stop():void {
|
||||
if (this.stream) {
|
||||
this.stream.close();
|
||||
this.stream = null;
|
||||
|
@ -189,8 +211,6 @@ package
|
|||
this.removeChild(this.video);
|
||||
this.video = null;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function draw_black_background(_width:int, _height:int):void {
|
||||
|
@ -205,7 +225,7 @@ package
|
|||
this.fs_mask.graphics.endFill();
|
||||
}
|
||||
|
||||
private function js_call_play(url:String, _width:int, _height:int, _buffer_time:Number):int {
|
||||
private function js_call_play(url:String, _width:int, _height:int, _buffer_time:Number):void {
|
||||
this.url = url;
|
||||
this.w = _width;
|
||||
this.h = _height;
|
||||
|
@ -218,6 +238,8 @@ package
|
|||
this.conn.client.onBWDone = function():void {};
|
||||
this.conn.addEventListener(NetStatusEvent.NET_STATUS, function(evt:NetStatusEvent):void {
|
||||
trace ("NetConnection: code=" + evt.info.code);
|
||||
|
||||
// TODO: FIXME: failed event.
|
||||
if (evt.info.code != "NetConnection.Connect.Success") {
|
||||
return;
|
||||
}
|
||||
|
@ -232,8 +254,12 @@ package
|
|||
if (evt.info.code == "NetStream.Video.DimensionChange") {
|
||||
on_metadata(metadata);
|
||||
}
|
||||
|
||||
// TODO: FIXME: failed event.
|
||||
});
|
||||
stream.play(url.substr(url.lastIndexOf("/")));
|
||||
|
||||
var streamName:String = url.substr(url.lastIndexOf("/"));
|
||||
stream.play(streamName);
|
||||
|
||||
video = new Video();
|
||||
video.width = _width;
|
||||
|
@ -247,9 +273,9 @@ package
|
|||
// lowest layer, for mask to cover it.
|
||||
setChildIndex(video, 0);
|
||||
});
|
||||
this.conn.connect(this.url.substr(0, this.url.lastIndexOf("/")));
|
||||
|
||||
return 0;
|
||||
var tcUrl:String = this.url.substr(0, this.url.lastIndexOf("/"));
|
||||
this.conn.connect(tcUrl);
|
||||
}
|
||||
|
||||
private function on_metadata(metadata:Object):void {
|
||||
|
|
Loading…
Reference in a new issue