减少HLS延迟时间超过30秒

10

Ubuntu 12.04

nginx 1.2.4

avconv -version

avconv version 0.8.10-4:0.8.10-0ubuntu0.12.04.1, Copyright (c) 2000-2013 the Libav developers
  built on Feb  6 2014 20:56:59 with gcc 4.6.3
avconv 0.8.10-4:0.8.10-0ubuntu0.12.04.1
libavutil    51. 22. 2 / 51. 22. 2
libavcodec   53. 35. 0 / 53. 35. 0
libavformat  53. 21. 1 / 53. 21. 1
libavdevice  53.  2. 0 / 53.  2. 0
libavfilter   2. 15. 0 /  2. 15. 0
libswscale    2.  1. 0 /  2.  1. 0
libpostproc  52.  0. 0 / 52.  0. 0

我正在使用avconv和nginx创建HLS流,但现在我的延迟通常超过30秒。经过多方阅读,我知道HLS具有固有的延迟,预计甚至更倾向于10秒,但30秒似乎相当极端。

我在nginx-rtmp谷歌小组上看到了很多讨论,这个线程尤其提出了很多建议。我已经尝试通过减少hls_fragmenthls_playlist_length来解决我的问题,但它们并没有产生显着的影响。

nginx.conf:

#user  nobody;
worker_processes  1;

error_log  logs/error.log debug;

events {
    worker_connections  1024;
}

http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       8888;
        server_name  localhost;

        add_header 'Access-Control-Allow-Origin' "*";

        location /hls {
            types {
                application/vnd.apple.mpegurl m3u8;
                video/mp2t ts;
            }
            root /tmp;
        }

        # rtmp stat
        location /stat {
            rtmp_stat all;
            rtmp_stat_stylesheet stat.xsl;
        }
        location /stat.xsl {
            # you can move stat.xsl to a different location
            root /usr/build/nginx-rtmp-module;
        }

        # rtmp control
        location /control {
            rtmp_control all;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }
}

rtmp {
    server {
        listen 1935;
        ping 30s;
        notify_method get;

        application myapp {
            live on;

            hls on;
            hls_path /tmp/hls;
            hls_base_url http://x.x.x.x:8888/hls/;
            hls_sync 2ms;
            hls_fragment 2s;

            #hls_variant _low BANDWIDTH=160000;
            #hls_variant _mid BANDWIDTH=320000;
            #hls_variant _hi BANDWIDTH=640000;
        }
    }
}

avconv命令:

avconv -r 30 -y -f image2pipe -codec:v mjpeg -i - -f flv -codec:v libx264 -profile:v baseline -preset ultrafast -tune zerolatency -an -f flv rtmp://127.0.0.1:1935/myapp/mystream

编辑

我知道瓶颈不在avconv,因为我也在使用nginx生成RTMP流。这个RTMP流有非常小的延迟(几秒钟)。


正如你所看到的,HLS 的性质是高延迟。30 秒并不算极端...这很常见。当 YouTube 做直播事件时,几分钟的延迟是正常的(虽然他们有一个更大的网络来分发)。你找到的建议也是正确的。如果它们对你的延迟没有帮助,问题可能出在编码端。从方程式中取出 HLS 部分,尝试立即回放 avconv/FFmpeg 的数据。测量延迟。它应该是一秒钟或更短,但你永远不知道。 - Brad
我的当前设置产生了两个流,一个使用HLS,另一个使用RTMP,RTMP流中有很小的延迟(可能只有几秒钟)。 - Rick
@Rick,我看到你现在正在使用Node.js,这可能是一个有趣的选择,但不幸的是,我认为iOS要求您使用HLS进行流媒体传输,否则RTMP可能是我的首选。你现在的延迟如何? - Panama Jack
@PanamaJack -注意,我已经有几年没有参与这个项目了。我不认为IOS是一个问题,我们使用nodejs进行流媒体传输,然后使用JS解码库将帧写入HTML5画布。延迟很好(几秒钟)。我们无法使用RTMP,因为它需要浏览器中的Flash播放器,这不会给您访问单个帧(我们需要的)。请注意,这些内容在我上次参与此项目的几年中可能已经发生了变化。 - Rick
2个回答

8

关于减少hls_playlist到4秒,hls_fragment到1秒的答案是好的。然而,需要注意的是,如果源视频的关键帧间隔大于hls_fragment长度,则nginx通常必须创建更长的片段,从而增加延迟。

我们所能达到的最低延迟是hls_fragment设置为1秒,源视频关键帧间隔也设置为1秒。使用这些设置,我们实现了少于7秒的延迟。


2
我觉得这更像是一条评论而不是一个答案。 - Aziz
3
我之所以给出这个答案,是因为你一定要将源关键帧间隔设置为较低的值,否则你将无法获得原始问题所期望的低于10秒的延迟(而我不能添加评论,那么我怎么能让这个重要的区别变得清晰明了呢?)注意不要改变原本的意思。 - brod
@brod,你是如何更改源视频关键帧间隔的?我正在尝试使用hls.js在浏览器中进行流媒体传输,但还没有找到实现这一点的方法。 - hoodsy
1
@hoodsy 这需要设置在生成视频的任何设备上。为了测试,您可以尝试在平板电脑或手机上使用Larix Broadcaster应用程序。Larix广播允许您更改视频关键帧间隔:链接 - brod
当您使用OBS或vmix时,也是可能的。 - Hirbod

6

我曾经也遇到过同样的问题。在nginx.conf中添加了两个参数后,延迟时间缩短至10秒甚至更短。以下是我的配置:

    application hls {
        hls_playlist_length 4s; 
        hls_fragment 1s
    }

然而,我必须说10秒似乎是我们的限制。还有更好的解决方案吗?

3
最终,我们彻底放弃了HLS并改用使用Node.js服务器通过套接字传输框架的方案。[链接](http://phoboslab.org/log/2013/09/html5-live-video-streaming-via-websockets) - Rick

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接