Upgrade hls.js and set in low latency mode. v6.0.112 (#3924)

HLS typically has a delay of around 30 seconds, roughly comprising three
segments, each lasting 10 seconds. We can reduce the delay to about 5
seconds by lowering the segment duration to 2 seconds and starting
playback from the last segment, achieving a stable delay.

Of course, this requires setting the OBS's GOP to 1 second, and the
profile to baseline, preset to fast, and tune to zerolatency.
Additionally, updating a few configurations in the hls.js player is
necessary, such as setting it to start playback from the last segment,
setting the maximum buffer, and initiating accelerated playback to
reduce latency.

---------

Co-authored-by: chundonglinlin <chundonglinlin@163.com>
Co-authored-by: john <hondaxiao@tencent.com>
pull/3920/head
Winlin 1 year ago committed by GitHub
parent 4ca7684e36
commit 22c2469414
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -276,7 +276,9 @@ jobs:
echo "Release ossrs/srs:$SRS_TAG"
docker buildx build --platform linux/arm/v7,linux/arm64/v8,linux/amd64 \
--output "type=image,push=true" \
-t ossrs/srs:$SRS_TAG --build-arg SRS_AUTO_PACKAGER=$PACKAGER -f Dockerfile .
-t ossrs/srs:$SRS_TAG --build-arg SRS_AUTO_PACKAGER=$PACKAGER \
--build-arg CONFARGS='--sanitizer=off --gb28181=on' \
-f Dockerfile .
# Docker alias images
# TODO: FIXME: If stable, please set the latest from 5.0 to 6.0
- name: Docker alias images for ossrs/srs

@ -29,7 +29,7 @@ WORKDIR /srs/trunk
# Build and install SRS.
# Note that SRT is enabled by default, so we configure without --srt=on.
# Note that we have copied all files by make install.
RUN ./configure --sanitizer=off --gb28181=on --h265=on ${CONFARGS} && make ${MAKEARGS} && make install
RUN ./configure ${CONFARGS} && make ${MAKEARGS} && make install
############################################################
# dist

@ -6,7 +6,7 @@ help=no
SRS_HDS=NO
SRS_SRT=YES
SRS_RTC=YES
SRS_H265=NO
SRS_H265=YES
SRS_GB28181=NO
SRS_CXX11=YES
SRS_CXX14=NO

5
trunk/configure vendored

@ -648,9 +648,8 @@ install:
@mkdir -p \$(__REAL_INSTALL)
@echo "Now make the http root dir"
@mkdir -p \$(__REAL_INSTALL)/objs/nginx/html
@cp -f research/api-server/static-dir/index.html \$(__REAL_INSTALL)/objs/nginx/html
@cp -f research/players/crossdomain.xml \$(__REAL_INSTALL)/objs/nginx/html
@cp -f research/api-server/static-dir/favicon.ico \$(__REAL_INSTALL)/objs/nginx/html
@cp -f research/index.html \$(__REAL_INSTALL)/objs/nginx/html
@cp -f research/favicon.ico \$(__REAL_INSTALL)/objs/nginx/html
@cp -Rf research/players \$(__REAL_INSTALL)/objs/nginx/html/
@cp -Rf research/console \$(__REAL_INSTALL)/objs/nginx/html/
@cp -Rf 3rdparty/signaling/www/demos \$(__REAL_INSTALL)/objs/nginx/html/

@ -7,6 +7,7 @@ The changelog for SRS.
<a name="v6-changes"></a>
## SRS 6.0 Changelog
* v6.0, 2024-02-05, Merge [#3924](https://github.com/ossrs/srs/pull/3924): Upgrade hls.js and set in low latency mode. v6.0.112 (#3924)
* v6.0, 2024-02-05, Merge [#3925](https://github.com/ossrs/srs/pull/3925): RTC: Fix video and audio track pt_ is not change in player before publisher. v6.0.111 (#3925)
* v6.0, 2024-02-05, Merge [#3923](https://github.com/ossrs/srs/pull/3923): Configure: print enabled/disable sanitizer. v6.0.110 (#3923)
* v6.0, 2023-12-30, Merge [#3916](https://github.com/ossrs/srs/pull/3916): Enhancing the compatibility of options.sh. v6.0.108 (#3916)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 17 B

@ -0,0 +1 @@
../../favicon.ico

Before

Width:  |  Height:  |  Size: 4.2 KiB

After

Width:  |  Height:  |  Size: 17 B

@ -1,72 +0,0 @@
<html>
<head>
<title>SRS</title>
<meta charset="utf-8">
<style>
.span6 {
width: 480px;
}
.code {
background-color: rgb(246 248 250);
padding: 8px;
overflow: auto;
font-size: 85%;
line-height: 1.45;
border-radius: 6px;
word-break: normal;
word-wrap: normal;
box-sizing: border-box;
display: block;
white-space: pre;
}
</style>
</head>
<body>
<div>
<h3><a href="https://github.com/ossrs/srs">SRS</a> works!</h3>
<p>
Click <a id="enConsole" href="#">here</a> to enter SRS console.<br/>
点击进入<a id="cnConsole" href="#">SRS控制台</a>
</p>
<p>
Publish stream by <a href="https://ffmpeg.org/download.html">FFmpeg</a> or <a href="https://obsproject.com/download">OBS</a>:<br/>
请使用工具<a href="https://ffmpeg.org/download.html">FFmpeg</a>或者<a href="https://obsproject.com/download">OBS</a>推流到下面地址:
<pre id="url" class="code span6"></pre>
</p>
<p>
Click <a id="enPlayer" href="#">here</a> to start SRS player.<br/>
点击进入<a id="cnPlayer" href="#">SRS播放器</a>
</p>
<p><a href="https://github.com/ossrs/srs">SRS Team &copy; 2022</a></p>
</div>
<script type="text/javascript">
// Build RTMP url.
if (true) {
const rtmpUrl = `rtmp://${window.location.hostname}/live/livestream`;
document.getElementById('url').innerText = rtmpUrl;
}
// Build console url.
if (true) {
// The prefix for default website.
const prefix = `${window.location.protocol}//${window.location.host}`;
// If not 8080, user should proxy to the default port.
const query = parseInt(window.location.port) === 8080 ? `?port=1985` : '';
const enUrl = `${prefix}/console/en_index.html#/summaries${query}`;
const cnUrl = `${prefix}/console/ng_index.html#/summaries${query}`;
document.getElementById("enConsole").setAttribute('href', enUrl);
document.getElementById("cnConsole").setAttribute('href', cnUrl);
}
// The player url.
if (true) {
const prefix = `players/?schema=${window.location.protocol.replace(':', '')}`;
const httpPort = window.location.port || (window.location.protocol === 'http:' ? 80 : 443);
// If not 8080, user should proxy both stream and API to the default port.
const query = parseInt(window.location.port) === 8080 ? '' : `&port=${httpPort}&api=${httpPort}`;
document.getElementById("enPlayer").setAttribute('href', `${prefix}${query}`);
document.getElementById("cnPlayer").setAttribute('href', `${prefix}${query}`);
}
</script>
</body>

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

@ -0,0 +1,103 @@
<html>
<head>
<title>SRS</title>
<meta charset="utf-8">
<style>
.code {
background-color: rgb(217, 222, 227);
padding: 2px;
overflow: auto;
font-size: 85%;
line-height: 1.45;
border-radius: 6px;
word-break: normal;
word-wrap: normal;
box-sizing: border-box;
white-space: pre;
}
</style>
</head>
<body>
<div>
<h2>Status</h2>
<p>Congratulations! <a href="https://github.com/ossrs/srs">SRS</a> works!</p>
<hr/>
<h2>English</h2>
<p>
1. Please publish stream by:
<ul>
<li>
Recommend <a href="https://obsproject.com/download">OBS</a>, set Service to <span class="code">Custom</span>,
set Server to <span id="url3" class="code"></span>
and Stream Key to <span id="url4" class="code"></span>
</li>
<li>
You can also use <a href="https://ffmpeg.org/download.html">FFmpeg</a>:
<span id="url" class="code"></span>
</li>
<li>
Or use WHIP to publish stream, please click <span class="code">SRS Player</span> link below.
</li>
</ul>
</p>
<p>2. Choose <a id="enPlayer" href="#">SRS player</a> to play the stream in different protocols.</p>
<p>3. (Optional) Click <a id="enConsole" href="#">here</a> to enter SRS console.</p>
<hr/>
<h2>简体中文</h2>
<p>
1. 请选择推流方式:
<ul>
<li>
推荐<a href="https://obsproject.com/download">OBS</a>,设置服务为 <span class="code">自定义</span>
设置推流地址(服务器)为 <span id="url5" class="code"></span>
设置推流密钥(串流密钥)为 <span id="url6" class="code"></span>
</li>
<li>
或者用<a href="https://ffmpeg.org/download.html">FFmpeg</a>推流到地址:
<span id="url2" class="code"></span>
</li>
<li>
或者使用WHIP推流请点击下面的 <span class="code">SRS播放器</span> 链接。
</li>
</ul>
</p>
<p>2. 点击选择 <a id="cnPlayer" href="#">SRS播放器</a></p>
<p>3. 点击进入 <a id="cnConsole" href="#">SRS控制台</a> (可选) </p>
<hr/>
<p><a href="https://github.com/ossrs/srs">SRS Team &copy; 2013~2024</a></p>
</div>
<script type="text/javascript">
// Build RTMP url.
if (true) {
const server = `rtmp://${window.location.hostname}/live`;
const key = `livestream`;
const rtmpUrl = `${server}/${key}`;
document.getElementById('url2').innerText = document.getElementById('url').innerText = `ffmpeg -re -i ./doc/source.200kbps.768x320.flv -c copy -f flv ${rtmpUrl}`;
document.getElementById('url5').innerText = document.getElementById('url3').innerText = server;
document.getElementById('url6').innerText = document.getElementById('url4').innerText = key;
}
// Build console url.
if (true) {
// The prefix for default website.
const prefix = `${window.location.protocol}//${window.location.host}`;
// If not 8080, user should proxy to the default port.
const query = parseInt(window.location.port) === 8080 ? `?port=1985` : '';
const enUrl = `${prefix}/console/en_index.html#/summaries${query}`;
const cnUrl = `${prefix}/console/ng_index.html#/summaries${query}`;
document.getElementById("enConsole").setAttribute('href', enUrl);
document.getElementById("cnConsole").setAttribute('href', cnUrl);
}
// The player url.
if (true) {
const prefix = `players/?schema=${window.location.protocol.replace(':', '')}`;
const httpPort = window.location.port || (window.location.protocol === 'http:' ? 80 : 443);
// If not 8080, user should proxy both stream and API to the default port.
const query = parseInt(window.location.port) === 8080 ? '' : `&port=${httpPort}&api=${httpPort}`;
document.getElementById("enPlayer").setAttribute('href', `${prefix}${query}`);
document.getElementById("cnPlayer").setAttribute('href', `${prefix}${query}`);
}
</script>
</body>

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

@ -103,7 +103,7 @@
<script type="text/javascript" src="js/jquery-1.12.2.min.js"></script>
<script type="text/javascript" src="js/bootstrap.min.js"></script>
<script type="text/javascript" src="js/mpegts-1.7.3.min.js"></script>
<script type="text/javascript" src="js/hls-0.14.17.min.js"></script>
<script type="text/javascript" src="js/hls-1.4.14.min.js"></script>
<script type="text/javascript" src="js/dash-v4.5.1.all.min.js"></script>
<script type="text/javascript" src="js/json2.js"></script>
<script type="text/javascript" src="js/srs.page.js"></script>
@ -196,6 +196,8 @@
stopPlayers();
if (!r) return;
const video = document.getElementById('video_player');
// Use H5 native to play aac/mp3.
if (r.stream.indexOf('.mp3') > 0 || r.stream.indexOf('.aac') > 0) {
$('#audio_player').attr('src', r.url).show();
@ -220,7 +222,7 @@
show_for_video_ok();
tsPlayer = mpegts.createPlayer({type: 'mpegts', url: r.url, isLive: true, enableStashBuffer: false});
tsPlayer.attachMediaElement(document.getElementById('video_player'));
tsPlayer.attachMediaElement(video);
tsPlayer.load();
tsPlayer.play();
return;
@ -235,9 +237,21 @@
show_for_video_ok();
hlsPlayer = new Hls();
// See https://github.com/video-dev/hls.js/blob/master/docs/API.md#maxlivesyncplaybackrate
// See https://github.com/video-dev/hls.js/issues/3077#issuecomment-705152394
hlsPlayer = new Hls({
enableWorker: true, // Improve performance and avoid lag/frame drops.
lowLatencyMode: true, // Enable Low-Latency HLS part playlist and segment loading.
liveSyncDurationCount: 0, // Start from the last segment.
liveMaxLatencyDurationCount: 4, // Maximum delay allowed from edge of live.
maxBufferLength: 5, // Maximum buffer length in seconds.
maxMaxBufferLength: 8, // The max Maximum buffer length in seconds.
maxLiveSyncPlaybackRate: 2, // Catch up if the latency is large.
liveDurationInfinity: true // Override current Media Source duration to Infinity for a live broadcast.
});
hlsPlayer.loadSource(r.url);
hlsPlayer.attachMedia(document.getElementById('video_player'));
hlsPlayer.attachMedia(video);
video.play();
return;
}
@ -264,16 +278,23 @@
show_for_video_ok();
flvPlayer = mpegts.createPlayer({type: 'flv', url: r.url, isLive: true, enableStashBuffer: false});
flvPlayer.attachMediaElement(document.getElementById('video_player'));
// See https://github.com/xqq/mpegts.js/blob/master/src/config.js#L32
// See https://github.com/xqq/mpegts.js/blob/master/docs/api.md
flvPlayer = mpegts.createPlayer({
type: 'flv', url: r.url,
isLive: true, enableStashBuffer: false, liveSync: true
});
flvPlayer.attachMediaElement(video);
flvPlayer.load();
flvPlayer.play();
return;
}
console.error('不支持的URL', r.url, r);
$('#video_player').hide();
$('#audio_player').hide();
const msg = `Not supported URL ${r.url} ${JSON.stringify(r)}`;
console.error(msg);
alert(msg);
};
$("#txt_url").change(function(){

@ -111,13 +111,13 @@ private:
srs_error_t on_ts_video_avc(SrsTsMessage* msg, SrsBuffer* avs);
srs_error_t on_ts_audio(SrsTsMessage* msg, SrsBuffer* avs);
srs_error_t check_sps_pps_change(SrsTsMessage* msg);
srs_error_t on_h264_frame(SrsTsMessage* msg, std::vector<std::pair<char*, int> >& ipb_frames);
srs_error_t on_h264_frame(SrsTsMessage* msg, std::vector< std::pair<char*, int> >& ipb_frames);
srs_error_t check_audio_sh_change(SrsTsMessage* msg, uint32_t pts);
srs_error_t on_aac_frame(SrsTsMessage* msg, uint32_t pts, char* frame, int frame_size);
#ifdef SRS_H265
srs_error_t on_ts_video_hevc(SrsTsMessage *msg, SrsBuffer *avs);
srs_error_t check_vps_sps_pps_change(SrsTsMessage *msg);
srs_error_t on_hevc_frame(SrsTsMessage *msg, std::vector<std::pair<char *, int>> &ipb_frames);
srs_error_t on_hevc_frame(SrsTsMessage *msg, std::vector< std::pair<char *, int> > &ipb_frames);
#endif
private:
ISrsStreamBridge* bridge_;

@ -9,6 +9,6 @@
#define VERSION_MAJOR 6
#define VERSION_MINOR 0
#define VERSION_REVISION 111
#define VERSION_REVISION 112
#endif

@ -778,7 +778,7 @@ struct SrsHevcRbspVps
uint32_t vps_max_latency_increase_plus1[8];
uint8_t vps_max_layer_id;
uint32_t vps_num_layer_sets_minus1;
std::vector<std::vector<uint8_t>> layer_id_included_flag;
std::vector< std::vector<uint8_t> > layer_id_included_flag;
uint8_t vps_timing_info_present_flag;
uint32_t vps_num_units_in_tick;
uint32_t vps_time_scale;

Loading…
Cancel
Save