You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何降低CMAF直播延迟?3秒延迟优化及分块传输问题求助

自建Nginx+FFmpeg实现CMAF直播:延迟优化至1秒+修复分块传输

问题背景

使用OBS推流至自建Nginx服务器,转码后通过CDN分发实现CMAF直播,当前存在两个问题:

  • 延迟稳定在3秒,无法降至目标的1秒
  • 分块传输未成功实现

当前配置代码

FFmpeg 转码命令

sudo ffmpeg -i rtmp://127.0.0.1:1935/live/stream -loglevel 40 -c copy -sc_threshold 0 -g 60 -bf 0 -map 0 -f dash -strict experimental -use_timeline 1 -use_template 1 -seg_duration 1 -window_size 5 -adaptation_sets "id=0,streams=v id=1,streams=a" -streaming 1 -dash_segment_type mp4 -utc_timing_url "http://time.akamai.com/?iso" -movflags frag_keyframe+empty_moov+default_base_moof -ldash 1 -hls_playlist 1 -master_m3u8_publish_rate 1 -remove_at_exit 1 /var/www/html/live/manifest.mpd

Nginx 配置

server_name myserver.com;
    add_header Access-Control-Allow-Origin *;
    add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
    add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
    add_header Access-Control-Expose-Headers 'Content-Length,Content-Range';
    root /var/www/html;
    index index.html index.nginx-debian.html;
        location / {
            chunked_transfer_encoding on;
        }

HTML 播放器代码

<!DOCTYPE html>
<html lang="zh-tw">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>streaming test</title>
    <script src="https://cdn.jsdelivr.net/npm/hls.js@latest"></script>
    <script src="https://cdn.dashjs.org/latest/dash.all.min.js"></script>
    <style>
        body {
            margin: 0;
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            min-height: 100vh;
            background-color: #000;
        }

        #video {
            max-width: 100%;
            max-height: 100vh;
        }
    </style>
</head>
<body>
    <video id="video" controls></video>

    <script>
        const video = document.getElementById('video');
        const hlsSrc = '/live/master.m3u8';
        const dashSrc = '/live/stream.mpd';

        function isHlsSupported() {
            return Hls.isSupported() || video.canPlayType('application/vnd.apple.mpegurl');
        }

        function isDashSupported() {
            return !!window.MediaSource && !!MediaSource.isTypeSupported('video/mp4; codecs="avc1.4d401e,mp4a.40.2"');
        }

        if (isHlsSupported()) {
            const hls = new Hls({
                lowLatencyMode: true,
                liveSyncDurationCount: 1,
                liveMaxLatencyDurationCount: 2,
                maxBufferLength: 2,
                maxBufferSize: 1000 * 1000 * 100,
                liveBackBufferLength: 0
            });
            hls.loadSource(hlsSrc);
            hls.attachMedia(video);
            hls.on(Hls.Events.MANIFEST_PARSED, () => {
                video.play();
            });
        } else if (isDashSupported()) {
            const player = dashjs.MediaPlayer().create();
            player.initialize(video, dashSrc, true);
            player.updateSettings({
                streaming: {
                    lowLatencyEnabled: true,
                    liveDelay: 1,
                    liveCatchUpPlaybackRate: 1.2,
                    liveCatchUpMinDrift: 0.5,
                    bufferTimeAtTopQuality: 3,
                    bufferToKeep: 0,
                }
            });
        } else {
            console.error('Neither HLS nor DASH playback is supported in this browser.');
        }
    </script>
</body>
</html>

解决方案:延迟降至1秒+修复分块传输

1. 调整FFmpeg参数(核心优化)

修改后的命令:

sudo ffmpeg -i rtmp://127.0.0.1:1935/live/stream -loglevel 40 -c copy -sc_threshold 0 -g 30 -bf 0 -map 0 -f dash -strict experimental -use_timeline 0 -use_template 1 -seg_duration 1 -frag_duration 200 -window_size 3 -adaptation_sets "id=0,streams=v id=1,streams=a" -streaming 1 -dash_segment_type mp4 -utc_timing_url "http://time.akamai.com/?iso" -movflags frag_keyframe+empty_moov+default_base_moof+faststart -ldash 1 -hls_playlist 1 -master_m3u8_publish_rate 1 -remove_at_exit 1 /var/www/html/live/manifest.mpd

关键修改点:

  • -g 30:若使用30fps推流,设置关键帧间隔为1秒(与seg_duration匹配),避免等待关键帧产生延迟
  • -use_timeline 0:禁用时间线模式,低延迟CMAF不需要全局时间线,减少manifest更新延迟
  • -frag_duration 200:将1秒的segment拆分为5个200ms的分片,支持分块传输,让播放器提前加载部分内容
  • -window_size 3:减少历史segment保留数量,降低播放器缓冲压力

2. 修复Nginx分块传输配置

修改Nginx的location块,确保支持字节范围请求并禁用缓存:

server_name myserver.com;
add_header Access-Control-Allow-Origin *;
add_header Access-Control-Allow-Methods 'GET, POST, OPTIONS';
add_header Access-Control-Allow-Headers 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';
add_header Access-Control-Expose-Headers 'Content-Length,Content-Range';
root /var/www/html;
index index.html index.nginx-debian.html;

location /live {
    chunked_transfer_encoding on;
    # 禁用缓存,确保播放器获取最新直播内容
    add_header Cache-Control "no-cache, no-store, must-revalidate";
    add_header Pragma "no-cache";
    add_header Expires "0";
    # 开启字节范围请求,支持分块传输
    add_header Accept-Ranges bytes;
    autoindex off;
}

关键修改点:

  • 单独为/live路径配置,避免全局影响
  • 新增Accept-Ranges bytes:这是分块传输成功的核心,让播放器可以请求文件的部分内容
  • 完全禁用缓存:直播内容实时更新,缓存会导致延迟增加

3. 优化播放器参数

Hls.js配置调整

const hls = new Hls({
    lowLatencyMode: true,
    liveSyncDurationCount: 1, // 仅同步最新的1个segment
    liveMaxLatencyDurationCount: 1, // 最大延迟限制为1秒
    maxBufferLength: 1, // 播放器缓冲区最多保留1秒内容
    maxBufferSize: 1000 * 1000 * 50, // 缩小缓冲区大小
    liveBackBufferLength: 0,
    enableWorker: true, // 启用Worker提升加载效率
    manifestLoadingRetryDelay: 100, // 缩短manifest重试间隔
    levelLoadingRetryDelay: 100
});

Dash.js配置调整

player.updateSettings({
    streaming: {
        lowLatencyEnabled: true,
        liveDelay: 1, // 目标延迟设为1秒
        liveCatchUpPlaybackRate: 1.5, // 加快追帧速度
        liveCatchUpMinDrift: 0.2, // 只要延迟超过0.2秒就启动追帧
        bufferTimeAtTopQuality: 1, // 缓冲区上限设为1秒
        bufferToKeep: 0,
        fastSwitchEnabled: true
    }
});

4. 额外配置检查

  • OBS推流设置:将关键帧间隔设为1秒(与FFmpeg的-g参数匹配),关闭OBS内置的推流延迟优化
  • CDN配置:确保CDN支持字节范围请求(byte-range),并设置缓存时间为1秒或禁用缓存,避免CDN缓存旧内容导致延迟

内容的提问来源于stack exchange,提问作者dannyomni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.18 19:25:02