video-dev / hls.js

HLS.js is a JavaScript library that plays HLS in browsers with support for MSE.
https://hlsjs.video-dev.org/demo
Other
14.66k stars 2.56k forks source link

How to get low latency with lhls #2450

Closed sblandford closed 4 years ago

sblandford commented 4 years ago

What do you want to do with Hls.js? I want to receive live audio with a latency of 1 second or less.

Currently the audio latency increases with whatever time the HTML5 player is in Pause mode. I would expect the audio to jump to within <1 second of latency whenever the Play button is pressed. I assume most browsers will not allow automated play on page load any more so the time it takes for the user to press play will always be added to the total latency.

I have tried setting liveBackBufferLength: 1 in the new Hls(config) however this has no effect.

What have you tried so far? Tried on:

I have Apache2 set up on ubuntu with a directory /var/www/html/audio containing the following files. .htaccess

RewriteEngine On

RewriteCond %{REQUEST_METHOD} =DELETE [OR]
RewriteCond %{REQUEST_METHOD} =PUT
RewriteRule ^.*?(\?.*)?$ index.php$1

RewriteCond %{REQUEST_METHOD} =GET
RewriteCond %{ENV:REDIRECT_STATUS} ^$
RewriteRule (.*) data/$1 [L]

index.php

<?php
$filename = "data/" . basename($_SERVER['REQUEST_URI']);
switch ($_SERVER['REQUEST_METHOD']) {
    case "PUT":
        session_start();
        $putdata = fopen("php://input", "r");

        /* Open a file for writing */
        $fp = fopen($filename, "w");

        /* Read the data 1 KB at a time
        and write to the file */
        while ($data = fread($putdata, 1024)) {
            fwrite($fp, $data);
        }

        /* Close the streams */
        fclose($fp);
        fclose($putdata);
        break;
    case "DELETE":
        unlink($filename);
        break;  
}
?>

There is a directory /var/www/html/audio/data that contains the PUT files from the ffmpeg source.

I am using the following ffmpeg version:

ffmpeg-static -version
ffmpeg version N-95730-ga7245adee3 Copyright (c) 2000-2019 the FFmpeg developers
built with gcc 7 (Ubuntu 7.4.0-1ubuntu1~18.04.1)

...and the following ffmpeg command: ffmpeg-static -f alsa -ac 2 -ar 44100 -i hw:1,0 -fflags nobuffer -flags low_delay -vn -c:a libfdk_aac -profile:a aac_he -ar 44100 -ac 1 -b:a 16k -bsf:a aac_adtstoasc -window_size 2 -hls_playlist 1 -seg_duration 0.5 -streaming 1 -strict experimental -lhls 1 -remove_at_exit 0 -master_m3u8_publish_rate 1 -f dash -method PUT -http_persistent 0 "http://127.0.0.1/audio/manifest.mpd"

The following file is used to play the stream:

<!Doctype html>
<html>
<body>
<script src="https://cdn.jsdelivr.net/npm/hls.js@canary"></script>
<audio id="audio" controls></audio><br />
<script>
    var audio = document.getElementById('audio');
    if(Hls.isSupported()) {
        var config = {
        };
        var hls = new Hls(config);
        hls.loadSource('audio/media_0.m3u8');
        hls.attachMedia(audio);
    } else {
        console.log("hls.js not supported");
    }
</script>
</body>
</html>
sblandford commented 4 years ago

Update. I have found a work-around to get the playback time to jump forward when the play button is pressed.

The extra config may get the latency lower than the default settings.

The result seems to be that I have a latency of about 1 second.

<!Doctype html>
<html>
<body>
<script src="https://cdn.jsdelivr.net/npm/hls.js@canary"></script>
<audio id="audio" controls></audio><br />
<script>
    var audio = document.getElementById('audio');
    if(Hls.isSupported()) {
        var config = {
            maxMaxBufferLength: 1,
            liveSyncDuration: 0.5,
            liveMaxLatencyDuration: 1,
            liveBackBufferLength: 0,
            nudgeMaxRetry: 10
        };
        var hls = new Hls(config);
        hls.loadSource('audio/media_0.m3u8');
        hls.attachMedia(audio);
    } else {
        console.log("hls.js not supported");
    }
    audio.onplay = function() {
        audio.currentTime = hls.liveSyncPosition;
    };
</script>
</body>
</html>
robwalch commented 4 years ago

Wow! Are you experiencing many stalls or seeks with this configuration?

Which version or branch are you using?

sblandford commented 4 years ago

I am using the "Canary" version of hls.js, which, I assume at the time I raised the issue, would have been built at v0.13.0-beta.1.

I did get quite a lot of drop outs after tweaking the buffer lengths. I found if I left everything at default then the extra latency was only a couple 100ms and I got no more dropouts.

I have since made some progress on the application I am developing : https://github.com/sblandford/LHLSWifiTranslation

It would be nice if I could somehow get the latency down to a few 100ms. Currently it is still about 1.5 seconds.

sblandford commented 4 years ago

This is embarrassing. I just realised that the standard hls.js has no LHLS implementation at all. I was basically using standard HLS. I need to be using the LHLS branch of the jwplayer fork of hls.js to start with.

Since this is another project entirely. I will close this ticket.