Support HTTP-FLV and HLS for srs-player by H5. 4.0.63

pull/2075/head
winlin 4 years ago
parent e2bdacb337
commit 618333cdd1

@ -155,6 +155,7 @@ For previous versions, please read:
## V4 changes
* v4.0, 2021-01-20, Support HTTP-FLV and HLS for srs-player by H5. 4.0.63
* v4.0, 2021-01-08, HTML5 video tag resolution adaptive. 4.0.59
* v4.0, 2021-01-08, Fix memory leak and bugs for RTC. 4.0.58
* v4.0, 2021-01-06, Merge #2109, Refine srs_string_split.

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -52,229 +52,54 @@
</div>
</div>
<div class="container">
<div name="detect_flash">
<div id="main_flash_alert" class="alert alert-danger fade in hide">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong><p>Usage:</p></strong>
<p>
请点击下面的图标启用Flash
</p>
<p>
若没有见到这个图标Chrome浏览器请打开
<span class="text-info">chrome://settings/content/flash</span> 并修改为"Ask first"。
</p>
</div>
<div id="main_flash_hdr" class="hide">
</div>
</div>
<div id="main_content" class="hide">
<div class="alert alert-info fade in">
<div id="main_content">
<div id="main_info" class="alert alert-info fade in">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong><span>Usage:</span></strong> <span>输入RTMP/HTTP-FLV/HLS地址后点击“播放视频”即可播放视频</span>
<strong><span>Usage:</span></strong> <span>输入HTTP-FLV/HLS地址后点击“播放视频”即可播放视频</span>
</div>
<div class="form-inline">
URL:
<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>
URL:
<input type="text" id="txt_url" class="input-xxlarge" value="">
<button class="btn btn-primary" id="btn_play">播放视频</button>
</div>
<p></p>
<div>
<video id="video_player" width="100%" autoplay controls></video>
</div>
<p>
推荐的其他播放器:
<ul>
<li><a href="http://bilibili.github.io/flv.js/demo">flv.js</a>H5/MSE播放HTTP-FLV</li>
<li><a href="https://hls-js.netlify.com/demo">hls.js</a>H5/MSE播放HLS</li>
<li><a href="http://reference.dashif.org/dash.js/nightly/samples/dash-if-reference-player/index.html">dash.js</a>H5/MSE播放MPEG-DASH</li>
</ul>
分享:<a href="#" id="link_url" target="_blank">请右键拷贝此链接</a>
</p>
</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/ossrs/srs">SRS Link Generator</a></h3>
<div id="main_tips">
<p></p>
<p>
推荐的其他播放器:
<ul>
<li><a href="http://bilibili.github.io/flv.js/demo">flv.js</a>H5/MSE播放HTTP-FLV</li>
<li><a href="https://hls-js.netlify.com/demo">hls.js</a>H5/MSE播放HLS</li>
<li><a href="http://reference.dashif.org/dash.js/nightly/samples/dash-if-reference-player/index.html">dash.js</a>H5/MSE播放MPEG-DASH</li>
</ul>
</p>
</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 id="main_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/ossrs/srs">SrsPlayer</a></h3>
</div>
<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" id="my_modal_footer">
<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_0" href="#">1秒(低延迟)</a></li>
<li><a id="btn_bt_2_0" href="#">2秒(较低延时)</a></li>
<li><a id="btn_bt_3_0" href="#">3秒(流畅播放)</a></li>
<li><a id="btn_bt_4_0" href="#">4秒(流畅播放)</a></li>
<li><a id="btn_bt_5_0" href="#">5秒(网速较低)</a></li>
<li><a id="btn_bt_6_0" href="#">6秒(网速较低)</a></li>
<li><a id="btn_bt_8_0" href="#">8秒(网速较低)</a></li>
<li><a id="btn_bt_10_0" href="#">10秒(无所谓延迟)</a></li>
<li><a id="btn_bt_15_0" href="#">15秒(无所谓延迟)</a></li>
<li><a id="btn_bt_20_0" href="#">20秒(无所谓延迟)</a></li>
<li><a id="btn_bt_30_0" href="#">30秒(流畅第一)</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_mbt_0_6" href="#">0.6秒(实时)</a></li>
<li><a id="btn_mbt_0_9" href="#">0.9秒(实时)</a></li>
<li><a id="btn_mbt_1_2" href="#">1.2秒(实时)</a></li>
<li><a id="btn_mbt_1_5" href="#">1.5秒(实时)</a></li>
<li><a id="btn_mbt_2_4" href="#">2.4秒(会议)</a></li>
<li><a id="btn_mbt_3_0" href="#">3秒(低延迟)</a></li>
<li><a id="btn_mbt_6_0" href="#">6秒(较低延时)</a></li>
<li><a id="btn_mbt_9_0" href="#">9秒(流畅播放)</a></li>
<li><a id="btn_mbt_12_0" href="#">12秒(流畅播放)</a></li>
<li><a id="btn_mbt_15_0" href="#">15秒(网速较低)</a></li>
<li><a id="btn_mbt_18_0" href="#">18秒(网速较低)</a></li>
<li><a id="btn_mbt_24_0" href="#">24秒(网速较低)</a></li>
<li><a id="btn_mbt_30_0" href="#">30秒(无所谓延迟)</a></li>
<li><a id="btn_mbt_45_0" href="#">45秒(无所谓延迟)</a></li>
<li><a id="btn_mbt_60_0" href="#">60秒(无所谓延迟)</a></li>
<li><a id="btn_mbt_90_0" href="#">90秒(流畅第一)</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="hide" id="fullscreen_tips">
<font color="red">点击视频</font>进入全屏模式~<br/>
由于安全原因Flash全屏无法使用JS触发
</div>
<div>
<div class="input-prepend div_play_time" title="BufferLength/BufferTime/MaxBufferTime">
<span class="add-on">@B</span>
<input class="span2" style="width:80px" id="txt_buffer" type="text" placeholder="0/0/0s">
</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:45px" 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:55px" 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:55px" 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 style="margin-top:-12px;">
<span id="debug_info"></span>
URL: <a href="#" id="player_url"></a>
<div class="input-prepend div_play_time" title="当前时间:年-月-日 时:分:秒">
<span class="add-on">@N</span>
<input class="span2" style="width:135px" id="player_clock" type="text" placeholder="年-月-日 时:分:秒">
</div>
</div>
<div>
<div class="input-prepend" title="首播时间,点播放到开始播放的时间,秒">
<span class="add-on">@PST</span>
<input class="span1" style="width:60px" id="txt_pst" type="text" placeholder="N秒">
</div>
</div>
</div>
</div>
<div name="detect_flash">
<div id="main_flash_alert" class="alert alert-danger fade in hide">
<button type="button" class="close" data-dismiss="alert">×</button>
<p>
<a href="https://www.adobe.com/products/flashplayer/end-of-life.html" target="_blank">Flash已死</a>
无法播放RTMP流可用VLC播放器播放。
</p>
<ul>
<li>若希望做低延迟直播3-5秒可用HTTP-FLV播放器用<a href="http://bilibili.github.io/flv.js/demo">flv.js</a>H5/MSE播放HTTP-FLV</li>
<li>若对延迟不敏感5-10秒跨平台比较好可用HLS播放器用<a href="https://hls-js.netlify.com/demo">hls.js</a>H5/MSE播放HLS</li>
<li>若希望超低延迟1秒内只需要支持主流的浏览器可用WebRTC播放器用<a href="rtc_player.html">RTC播放器</a></li>
</ul>
<p>
更多信息,参考<a href="https://mp.weixin.qq.com/s/oYn5q4fF9afaged23Ueudg" target="_blank">没有Flash如何做直播</a>
</p>
</div>
</div>
@ -286,436 +111,134 @@
</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/flv-1.5.0.min.js"></script>
<script type="text/javascript" src="js/hls-0.14.17.min.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 __on_flash_ready = null;
$(function(){
// 探测Flash是否正常启用。
$('#main_flash_hdr').html(
'\
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="100%" height="100%"> \
<param name="movie" value="srs_player/release/srs_player.swf"> \
<param name="quality" value="autohigh"> \
<param name="swliveconnect" value="true"> \
<param name="allowScriptAccess" value="always"> \
<param name="bgcolor" value="#0"> \
<param name="allowFullScreen" value="true"> \
<param name="wmode" value="opaque"> \
<param name="FlashVars" value="log=1"> \
<param name="flashvars" value="id=1&on_player_ready=__on_flash_ready"> \
<embed src="srs_player/release/srs_player.swf" width="100%" height="100%" \
quality="autohigh" bgcolor="#0" align="middle" allowfullscreen="true" allowscriptaccess="always" \
type="application/x-shockwave-flash" swliveconnect="true" wmode="opaque" \
flashvars="id=1&on_player_ready=__on_flash_ready" \
pluginspage="http://www.macromedia.com/go/getflashplayer"> \
</object> \
'
);
$('#main_flash_hdr').show();
var showFlashHdr = setTimeout(function(){
$('#main_flash_alert').show();
}, 300);
__on_flash_ready = function (id) {
clearTimeout(showFlashHdr);
$('#main_flash_alert').hide();
$('#main_flash_hdr').hide();
$('#main_content').show();
autoLoadPage();
};
});
</script>
<script type="text/javascript">
var srs_player = null;
var url = null;
var flvPlayer = null;
var hlsPlayer = null;
var hide_for_error = function () {
$('#main_flash_alert').show();
$('#main_info').hide();
$('#main_tips').hide();
$('#video_player').hide();
//$('#btn_play').hide();
};
var __active_dar = null;
function select_dar(dar_id, num, den) {
srs_player.set_dar(num, den);
var show_for_ok = function () {
$('#main_flash_alert').hide();
$('#main_info').show();
$('#main_tips').show();
$('#video_player').show();
//$('#btn_play').show();
};
if (__active_dar) {
__active_dar.removeClass("active");
var apply_url_change = function() {
var r = parse_rtmp_url($("#txt_url").val());
var url = window.location.protocol + "//" + query.host + query.pathname + "?autostart=true"
+ "&app=" + r.app + "&stream=" + r.stream + "&server=" + r.server + "&port=" + r.port;
url += (query.shp_identify)? "&shp_identify=" + query.shp_identify : '';
url += (r.vhost === "__defaultVhost__")? "&vhost=" + r.server : "&vhost=" + r.vhost;
url += (r.schema !== "rtmp")? "&schema=" + r.schema : '';
url += (query.buffer)? "&buffer=" + query.buffer : '';
url += (query.api_port)? "&api_port=" + query.api_port : '';
var queries = user_extra_params(query);
queries = user_extra_params(r, queries);
if (queries && queries.length) {
url += '&' + queries.join('&');
}
$("#player_url").text($("#txt_url").val()).attr("href", url);
$("#link_url").attr("href", url);
__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");
// Stop players.
if (flvPlayer) {
flvPlayer.destroy();
}
__active_size = $(size_id).parent();
__active_size.addClass("active");
}
function select_buffer(buffer_time) {
var bt = buffer_time;
var bt_id = "#btn_bt_" + bt.toFixed(1).replace(".", "_");
select_buffer_time(bt_id, bt);
}
function select_max_buffer(max_buffer_time) {
var mbt = max_buffer_time;
var mbt_id = "#btn_mbt_" + mbt.toFixed(1).replace(".", "_");
select_max_buffer_time(mbt_id, mbt);
}
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");
if (hlsPlayer) {
hlsPlayer.destroy();
}
__active_bt = $(bt_id).parent();
__active_bt.addClass("active");
select_max_buffer(srs_player.max_buffer_time);
}
var __active_mbt = null;
function select_max_buffer_time(mbt_id, max_buffer_time) {
srs_player.set_mbt(max_buffer_time);
if (__active_mbt) {
__active_mbt.removeClass("active");
// For RTMP, not support.
if (r.schema === 'rtmp') {
hide_for_error();
return;
}
__active_mbt = $(mbt_id).parent();
__active_mbt.addClass("active");
}
/****
* The parameters for this page:
* schema, the protocol schema, rtmp or http.
* server, the ip of the url.
* port, the rtmp port of url.
* vhost, the vhost of url, can equals to server.
* app, the app of url.
* stream, the stream of url, can endwith .flv or .mp4 or nothing for RTMP.
* autostart, whether auto play the stream.
* buffer, the buffer time in seconds.
* extra params:
* shp_identify, hls+ param.
* for example:
* http://localhost:8088/players/srs_player.html?vhost=ossrs.net&app=live&stream=livestream&server=ossrs.net&port=1935&autostart=true&schema=rtmp
* http://localhost:8088/players/srs_player.html?vhost=ossrs.net&app=live&stream=livestream.flv&server=ossrs.net&port=8080&autostart=true&schema=http
*/
var autoLoadPage = function() {
var query = parse_query_string();
// get the vhost and port to set the default url.
// for example: http://192.168.1.213/players/srs_player.html?port=1935&vhost=demo
// url set to: rtmp://demo:1935/live/livestream
srs_init_rtmp("#txt_url", "#main_modal");
// consts for buffer and max buffer.
var bts = [0.1, 0.2, 0.3, 0.5, 0.8, 1, 2, 3, 4, 5, 6, 8, 10, 15, 20, 30];
var mbts = [0.6, 0.9, 1.2, 1.5, 2.4, 3, 6, 9, 12, 15, 18, 24, 30, 45, 60, 90];
// the play startup time.
var pst = new Date();
$("#main_modal").on("show", function(){
if (srs_player) {
// Start play HTTP-FLV.
if (r.stream.indexOf('.flv') > 0) {
if (!flvjs.isSupported()) {
hide_for_error();
return;
}
$("#div_container").remove();
$("#debug_info").text("");
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);
apply_url_change();
srs_player = new SrsPlayer("player_id", srs_get_player_width(), srs_get_player_height());
srs_player.on_player_ready = function() {
var buffer_time = 0.5;
if (url.indexOf('.m3u8') > 0) {
buffer_time = 2;
}
if (query.buffer) {
for (var i = 0; i < bts.length - 1; i++) {
var cur = bts[i];
var next = bts[i+1];
if (Number(query.buffer) >= cur && Number(query.buffer) < next) {
buffer_time = cur;
break;
}
}
}
select_buffer(buffer_time);
this.play(url);
pst = new Date();
};
srs_player.on_player_status = function(code, desc) {
//console.log("[播放器状态] code=" + code + ", desc=" + desc);
};
srs_player.on_player_metadata = function(metadata) {
$("#btn_dar_original").text("视频原始比例" + "(" + metadata.width + ":" + metadata.height + ")");
if (metadata.ip && metadata.pid && metadata.cid) {
$("#debug_info").text("ID:" + metadata.ip + '/' + metadata.pid + '/' + metadata.cid + '');
}
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) {
if (time > 0 && pst) {
var diff = (new Date().getTime() - pst.getTime()) / 1000.0;
$("#txt_pst").val(Number(diff).toFixed(2) + "秒");
pst = null;
}
var buffer = buffer_length / this.max_buffer_time * 100;
$("#pb_buffer").width(Number(buffer).toFixed(1) + "%");
$("#pb_buffer_bg").attr("title",
"缓冲区:" + buffer_length.toFixed(1) + "秒, 最大缓冲区:"
+ this.max_buffer_time.toFixed(1) + "秒, 当前:"
+ buffer.toFixed(1) + "%");
show_for_ok();
var bts = this.buffer_time >= 1? this.buffer_time.toFixed(0) : this.buffer_time.toFixed(1);
var mbts = this.buffer_time >= 1? this.max_buffer_time.toFixed(0) : this.max_buffer_time.toFixed(1);
$("#txt_buffer").val(buffer_length.toFixed(1) + "/" + bts + "/" + mbts + "s");
$("#txt_bitrate").val(kbps.toFixed(0) + "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);
var clock = new Date().getTime() / 1000;
$("#player_clock").val(absolute_seconds_to_YYYYmmdd(clock) + " " + absolute_seconds_to_HHMMSS(clock));
};
srs_player.start();
});
$("#main_modal").on("hide", function(){
if (srs_player) {
// report the log to backend.
//console.log(srs_player.dump_log());
srs_player.stop();
srs_player = null;
}
});
var apply_url_change = function() {
var rtmp = parse_rtmp_url($("#txt_url").val());
var schema = window.location.protocol;
var url = schema + "//" + query.host + query.pathname + "?"
+ "app=" + rtmp.app + "&stream=" + rtmp.stream
+ "&server=" + rtmp.server + "&port=" + rtmp.port
+ "&autostart=true";
if (query.shp_identify) {
url += "&shp_identify=" + query.shp_identify;
}
if (rtmp.vhost === "__defaultVhost__") {
url += "&vhost=" + rtmp.server;
} else {
url += "&vhost=" + rtmp.vhost;
}
if (rtmp.schema !== "rtmp") {
url += "&schema=" + rtmp.schema;
}
if (query.buffer) {
url += "&buffer=" + query.buffer;
}
if (query.api_port) {
url += "&api_port=" + query.api_port;
}
flvPlayer = flvjs.createPlayer({type: 'flv', url: r.url});
flvPlayer.attachMediaElement(document.getElementById('video_player'));
flvPlayer.load();
flvPlayer.play();
return;
}
var queries = user_extra_params(query);
queries = user_extra_params(rtmp, queries);
if (queries && queries.length) {
url += '&' + queries.join('&');
// Start play HLS.
if (r.stream.indexOf('.m3u8') > 0) {
if (!Hls.isSupported()) {
hide_for_error();
return;
}
$("#player_url").text($("#txt_url").val()).attr("href", url);
$("#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);
};
$("#txt_url").change(function(){
apply_url_change();
});
$("#btn_generate_link").click(function(){
$("#link_modal").modal({show:true, keyboard:true});
});
$("#btn_play").click(function(){
url = $("#txt_url").val();
$("#main_modal").modal({show:true, keyboard:true});
});
show_for_ok();
$("#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});
});
hlsPlayer = new Hls();
hlsPlayer.loadSource(r.url);
hlsPlayer.attachMedia(document.getElementById('video_player'));
return;
}
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) {
for (var i = 0; i < bts.length; i++) {
var bt = bts[i];
var bt_id = "#btn_bt_" + bt.toFixed(1).replace(".", "_");
var bt_fun = function(id, v){
$(bt_id).click(function(){
select_buffer_time(id, v);
// remember the chagned buffer.
if (Number(query.buffer) != srs_player.buffer_time) {
query.buffer = srs_player.buffer_time;
apply_url_change();
}
});
};
bt_fun(bt_id, bt);
}
}
if (true) {
for (var i = 0; i < mbts.length; i++) {
var mbt = mbts[i];
var mbt_id = "#btn_mbt_" + mbt.toFixed(1).replace(".", "_");
console.error('不支持的URL', r.url, r);
$('#video_player').hide();
};
var mbt_fun = function(id, v){
$(mbt_id).click(function(){
select_max_buffer_time(id, v);
});
};
mbt_fun(mbt_id, mbt);
}
}
$("#txt_url").change(function(){
apply_url_change();
});
var query = parse_query_string();
if (query.autostart == "true") {
url = $("#txt_url").val();
$("#main_modal").modal({show:true, keyboard:false});
}
$("#btn_play").click(function(){
apply_url_change();
});
/****
* The parameters for this page:
* schema, the protocol schema, rtmp or http.
* server, the ip of the url.
* port, the rtmp port of url.
* vhost, the vhost of url, can equals to server.
* app, the app of url.
* stream, the stream of url, can endwith .flv or .mp4 or nothing for RTMP.
* autostart, whether auto play the stream.
* buffer, the buffer time in seconds.
* extra params:
* shp_identify, hls+ param.
* for example:
* http://localhost:8088/players/srs_player.html?vhost=ossrs.net&app=live&stream=livestream&server=ossrs.net&port=1935&autostart=true&schema=rtmp
* http://localhost:8088/players/srs_player.html?vhost=ossrs.net&app=live&stream=livestream.flv&server=ossrs.net&port=8080&autostart=true&schema=http
*/
var query = parse_query_string();
// get the vhost and port to set the default url.
// for example: http://192.168.1.213/players/srs_player.html?port=1935&vhost=demo
// url set to: rtmp://demo:1935/live/livestream
srs_init_rtmp("#txt_url");
if (query.autostart === "true") {
apply_url_change();
};
}
</script>
</html>

@ -0,0 +1,721 @@
<!DOCTYPE html>
<html>
<head>
<title>SRS</title>
<meta charset="utf-8">
<link rel="stylesheet" type="text/css" href="css/bootstrap.min.css"/>
<style>
body{
padding-top: 55px;
}
#my_modal_footer {
margin-top: -20px;
padding-top: 3px;
}
#main_modal {
margin-top: -60px;
}
.div_play_time {
margin-top: 10px;
}
#pb_buffer_bg {
margin-top: -4px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<img src='https://ossrs.net/gif/v1/sls.gif?site=ossrs.net&path=/player/srsplayer'/>
<div class="navbar navbar-fixed-top">
<div class="navbar-inner">
<div class="container">
<a id="srs_index" class="brand" href="#">SRS</a>
<div class="nav-collapse collapse">
<ul class="nav">
<li class="active"><a id="nav_srs_player" href="srs_player.html">SRS播放器</a></li>
<li><a id="nav_rtc_player" href="rtc_player.html">RTC播放器</a></li>
<li><a id="nav_rtc_publisher" href="rtc_publisher.html">RTC推流</a></li>
<li><a href="http://ossrs.net/srs.release/releases/app.html">iOS/Andriod</a></li>
<!--<li><a id="nav_srs_publisher" href="srs_publisher.html">SRS编码器</a></li>-->
<!--<li><a id="nav_srs_chat" href="srs_chat.html">SRS会议</a></li>-->
<!--<li><a id="nav_srs_bwt" href="srs_bwt.html">SRS测网速</a></li>-->
<!--li><a id="nav_vlc" href="vlc.html">VLC播放器</a></li>-->
<li><a id="nav_gb28181" href="srs_gb28181.html">GB28181</a></li>
<li>
<a href="https://github.com/ossrs/srs">
<img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/ossrs/srs?style=social">
</a>
</li>
</ul>
</div>
</div>
</div>
</div>
<div class="container">
<div name="detect_flash">
<div id="main_flash_alert" class="alert alert-danger fade in hide">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong><p>Usage:</p></strong>
<p>
请点击下面的图标启用Flash
</p>
<p>
若没有见到这个图标Chrome浏览器请打开
<span class="text-info">chrome://settings/content/flash</span> 并修改为"Ask first"。
</p>
</div>
<div id="main_flash_hdr" class="hide">
</div>
</div>
<div id="main_content" class="hide">
<div class="alert alert-info fade in">
<button type="button" class="close" data-dismiss="alert">×</button>
<strong><span>Usage:</span></strong> <span>输入RTMP/HTTP-FLV/HLS地址后点击“播放视频”即可播放视频</span>
</div>
<div class="form-inline">
URL:
<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>
<p></p>
<p>
推荐的其他播放器:
<ul>
<li><a href="http://bilibili.github.io/flv.js/demo">flv.js</a>H5/MSE播放HTTP-FLV</li>
<li><a href="https://hls-js.netlify.com/demo">hls.js</a>H5/MSE播放HLS</li>
<li><a href="http://reference.dashif.org/dash.js/nightly/samples/dash-if-reference-player/index.html">dash.js</a>H5/MSE播放MPEG-DASH</li>
</ul>
</p>
</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/ossrs/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 id="main_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/ossrs/srs">SrsPlayer</a></h3>
</div>
<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" id="my_modal_footer">
<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_0" href="#">1秒(低延迟)</a></li>
<li><a id="btn_bt_2_0" href="#">2秒(较低延时)</a></li>
<li><a id="btn_bt_3_0" href="#">3秒(流畅播放)</a></li>
<li><a id="btn_bt_4_0" href="#">4秒(流畅播放)</a></li>
<li><a id="btn_bt_5_0" href="#">5秒(网速较低)</a></li>
<li><a id="btn_bt_6_0" href="#">6秒(网速较低)</a></li>
<li><a id="btn_bt_8_0" href="#">8秒(网速较低)</a></li>
<li><a id="btn_bt_10_0" href="#">10秒(无所谓延迟)</a></li>
<li><a id="btn_bt_15_0" href="#">15秒(无所谓延迟)</a></li>
<li><a id="btn_bt_20_0" href="#">20秒(无所谓延迟)</a></li>
<li><a id="btn_bt_30_0" href="#">30秒(流畅第一)</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_mbt_0_6" href="#">0.6秒(实时)</a></li>
<li><a id="btn_mbt_0_9" href="#">0.9秒(实时)</a></li>
<li><a id="btn_mbt_1_2" href="#">1.2秒(实时)</a></li>
<li><a id="btn_mbt_1_5" href="#">1.5秒(实时)</a></li>
<li><a id="btn_mbt_2_4" href="#">2.4秒(会议)</a></li>
<li><a id="btn_mbt_3_0" href="#">3秒(低延迟)</a></li>
<li><a id="btn_mbt_6_0" href="#">6秒(较低延时)</a></li>
<li><a id="btn_mbt_9_0" href="#">9秒(流畅播放)</a></li>
<li><a id="btn_mbt_12_0" href="#">12秒(流畅播放)</a></li>
<li><a id="btn_mbt_15_0" href="#">15秒(网速较低)</a></li>
<li><a id="btn_mbt_18_0" href="#">18秒(网速较低)</a></li>
<li><a id="btn_mbt_24_0" href="#">24秒(网速较低)</a></li>
<li><a id="btn_mbt_30_0" href="#">30秒(无所谓延迟)</a></li>
<li><a id="btn_mbt_45_0" href="#">45秒(无所谓延迟)</a></li>
<li><a id="btn_mbt_60_0" href="#">60秒(无所谓延迟)</a></li>
<li><a id="btn_mbt_90_0" href="#">90秒(流畅第一)</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="hide" id="fullscreen_tips">
<font color="red">点击视频</font>进入全屏模式~<br/>
由于安全原因Flash全屏无法使用JS触发
</div>
<div>
<div class="input-prepend div_play_time" title="BufferLength/BufferTime/MaxBufferTime">
<span class="add-on">@B</span>
<input class="span2" style="width:80px" id="txt_buffer" type="text" placeholder="0/0/0s">
</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:45px" 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:55px" 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:55px" 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 style="margin-top:-12px;">
<span id="debug_info"></span>
URL: <a href="#" id="player_url"></a>
<div class="input-prepend div_play_time" title="当前时间:年-月-日 时:分:秒">
<span class="add-on">@N</span>
<input class="span2" style="width:135px" id="player_clock" type="text" placeholder="年-月-日 时:分:秒">
</div>
</div>
<div>
<div class="input-prepend" title="首播时间,点播放到开始播放的时间,秒">
<span class="add-on">@PST</span>
<input class="span1" style="width:60px" id="txt_pst" type="text" placeholder="N秒">
</div>
</div>
</div>
</div>
</div>
<footer>
<p></p>
<p><a href="https://github.com/ossrs/srs">SRS Team &copy; 2013</a></p>
</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 __on_flash_ready = null;
$(function(){
// 探测Flash是否正常启用。
$('#main_flash_hdr').html(
'\
<object classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="100%" height="100%"> \
<param name="movie" value="srs_player/release/srs_player.swf"> \
<param name="quality" value="autohigh"> \
<param name="swliveconnect" value="true"> \
<param name="allowScriptAccess" value="always"> \
<param name="bgcolor" value="#0"> \
<param name="allowFullScreen" value="true"> \
<param name="wmode" value="opaque"> \
<param name="FlashVars" value="log=1"> \
<param name="flashvars" value="id=1&on_player_ready=__on_flash_ready"> \
<embed src="srs_player/release/srs_player.swf" width="100%" height="100%" \
quality="autohigh" bgcolor="#0" align="middle" allowfullscreen="true" allowscriptaccess="always" \
type="application/x-shockwave-flash" swliveconnect="true" wmode="opaque" \
flashvars="id=1&on_player_ready=__on_flash_ready" \
pluginspage="http://www.macromedia.com/go/getflashplayer"> \
</object> \
'
);
$('#main_flash_hdr').show();
var showFlashHdr = setTimeout(function(){
$('#main_flash_alert').show();
}, 300);
__on_flash_ready = function (id) {
clearTimeout(showFlashHdr);
$('#main_flash_alert').hide();
$('#main_flash_hdr').hide();
$('#main_content').show();
autoLoadPage();
};
});
</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");
}
function select_buffer(buffer_time) {
var bt = buffer_time;
var bt_id = "#btn_bt_" + bt.toFixed(1).replace(".", "_");
select_buffer_time(bt_id, bt);
}
function select_max_buffer(max_buffer_time) {
var mbt = max_buffer_time;
var mbt_id = "#btn_mbt_" + mbt.toFixed(1).replace(".", "_");
select_max_buffer_time(mbt_id, mbt);
}
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");
select_max_buffer(srs_player.max_buffer_time);
}
var __active_mbt = null;
function select_max_buffer_time(mbt_id, max_buffer_time) {
srs_player.set_mbt(max_buffer_time);
if (__active_mbt) {
__active_mbt.removeClass("active");
}
__active_mbt = $(mbt_id).parent();
__active_mbt.addClass("active");
}
/****
* The parameters for this page:
* schema, the protocol schema, rtmp or http.
* server, the ip of the url.
* port, the rtmp port of url.
* vhost, the vhost of url, can equals to server.
* app, the app of url.
* stream, the stream of url, can endwith .flv or .mp4 or nothing for RTMP.
* autostart, whether auto play the stream.
* buffer, the buffer time in seconds.
* extra params:
* shp_identify, hls+ param.
* for example:
* http://localhost:8088/players/srs_player.html?vhost=ossrs.net&app=live&stream=livestream&server=ossrs.net&port=1935&autostart=true&schema=rtmp
* http://localhost:8088/players/srs_player.html?vhost=ossrs.net&app=live&stream=livestream.flv&server=ossrs.net&port=8080&autostart=true&schema=http
*/
var autoLoadPage = function() {
var query = parse_query_string();
// get the vhost and port to set the default url.
// for example: http://192.168.1.213/players/srs_player.html?port=1935&vhost=demo
// url set to: rtmp://demo:1935/live/livestream
srs_init_rtmp("#txt_url", "#main_modal");
// consts for buffer and max buffer.
var bts = [0.1, 0.2, 0.3, 0.5, 0.8, 1, 2, 3, 4, 5, 6, 8, 10, 15, 20, 30];
var mbts = [0.6, 0.9, 1.2, 1.5, 2.4, 3, 6, 9, 12, 15, 18, 24, 30, 45, 60, 90];
// the play startup time.
var pst = new Date();
$("#main_modal").on("show", function(){
if (srs_player) {
return;
}
$("#div_container").remove();
$("#debug_info").text("");
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);
apply_url_change();
srs_player = new SrsPlayer("player_id", srs_get_player_width(), srs_get_player_height());
srs_player.on_player_ready = function() {
var buffer_time = 0.5;
if (url.indexOf('.m3u8') > 0) {
buffer_time = 2;
}
if (query.buffer) {
for (var i = 0; i < bts.length - 1; i++) {
var cur = bts[i];
var next = bts[i+1];
if (Number(query.buffer) >= cur && Number(query.buffer) < next) {
buffer_time = cur;
break;
}
}
}
select_buffer(buffer_time);
this.play(url);
pst = new Date();
};
srs_player.on_player_status = function(code, desc) {
//console.log("[播放器状态] code=" + code + ", desc=" + desc);
};
srs_player.on_player_metadata = function(metadata) {
$("#btn_dar_original").text("视频原始比例" + "(" + metadata.width + ":" + metadata.height + ")");
if (metadata.ip && metadata.pid && metadata.cid) {
$("#debug_info").text("ID:" + metadata.ip + '/' + metadata.pid + '/' + metadata.cid + '');
}
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) {
if (time > 0 && pst) {
var diff = (new Date().getTime() - pst.getTime()) / 1000.0;
$("#txt_pst").val(Number(diff).toFixed(2) + "秒");
pst = null;
}
var buffer = buffer_length / this.max_buffer_time * 100;
$("#pb_buffer").width(Number(buffer).toFixed(1) + "%");
$("#pb_buffer_bg").attr("title",
"缓冲区:" + buffer_length.toFixed(1) + "秒, 最大缓冲区:"
+ this.max_buffer_time.toFixed(1) + "秒, 当前:"
+ buffer.toFixed(1) + "%");
var bts = this.buffer_time >= 1? this.buffer_time.toFixed(0) : this.buffer_time.toFixed(1);
var mbts = this.buffer_time >= 1? this.max_buffer_time.toFixed(0) : this.max_buffer_time.toFixed(1);
$("#txt_buffer").val(buffer_length.toFixed(1) + "/" + bts + "/" + mbts + "s");
$("#txt_bitrate").val(kbps.toFixed(0) + "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);
var clock = new Date().getTime() / 1000;
$("#player_clock").val(absolute_seconds_to_YYYYmmdd(clock) + " " + absolute_seconds_to_HHMMSS(clock));
};
srs_player.start();
});
$("#main_modal").on("hide", function(){
if (srs_player) {
// report the log to backend.
//console.log(srs_player.dump_log());
srs_player.stop();
srs_player = null;
}
});
var apply_url_change = function() {
var rtmp = parse_rtmp_url($("#txt_url").val());
var schema = window.location.protocol;
var url = schema + "//" + query.host + query.pathname + "?"
+ "app=" + rtmp.app + "&stream=" + rtmp.stream
+ "&server=" + rtmp.server + "&port=" + rtmp.port
+ "&autostart=true";
if (query.shp_identify) {
url += "&shp_identify=" + query.shp_identify;
}
if (rtmp.vhost === "__defaultVhost__") {
url += "&vhost=" + rtmp.server;
} else {
url += "&vhost=" + rtmp.vhost;
}
if (rtmp.schema !== "rtmp") {
url += "&schema=" + rtmp.schema;
}
if (query.buffer) {
url += "&buffer=" + query.buffer;
}
if (query.api_port) {
url += "&api_port=" + query.api_port;
}
var queries = user_extra_params(query);
queries = user_extra_params(rtmp, queries);
if (queries && queries.length) {
url += '&' + queries.join('&');
}
$("#player_url").text($("#txt_url").val()).attr("href", url);
$("#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);
};
$("#txt_url").change(function(){
apply_url_change();
});
$("#btn_generate_link").click(function(){
$("#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});
});
}
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) {
for (var i = 0; i < bts.length; i++) {
var bt = bts[i];
var bt_id = "#btn_bt_" + bt.toFixed(1).replace(".", "_");
var bt_fun = function(id, v){
$(bt_id).click(function(){
select_buffer_time(id, v);
// remember the chagned buffer.
if (Number(query.buffer) != srs_player.buffer_time) {
query.buffer = srs_player.buffer_time;
apply_url_change();
}
});
};
bt_fun(bt_id, bt);
}
}
if (true) {
for (var i = 0; i < mbts.length; i++) {
var mbt = mbts[i];
var mbt_id = "#btn_mbt_" + mbt.toFixed(1).replace(".", "_");
var mbt_fun = function(id, v){
$(mbt_id).click(function(){
select_max_buffer_time(id, v);
});
};
mbt_fun(mbt_id, mbt);
}
}
var query = parse_query_string();
if (query.autostart == "true") {
url = $("#txt_url").val();
$("#main_modal").modal({show:true, keyboard:false});
}
apply_url_change();
};
</script>
</html>

@ -24,6 +24,6 @@
#ifndef SRS_CORE_VERSION4_HPP
#define SRS_CORE_VERSION4_HPP
#define SRS_VERSION4_REVISION 62
#define SRS_VERSION4_REVISION 63
#endif

Loading…
Cancel
Save