FFMPEG/DASH-LL 以不同的速率创建音频和视频块;玩家感到困惑(404 错误)
FFMPEG/DASH-LL creates audio and video chunks at different rates; player is confused (404 errors)
我正在尝试从静态文件创建 MPEG-DASH“实时”流以测试各种低延迟模式。 FFmpeg 中的 DASH muxer 创建了两个 AdaptationSets,一个用于视频块,一个用于音频块。
但是,音频和视频块文件的创建速度不同(应该是这样吗?)。即,这里 stream0
是视频块,stream1
是音频块。 运行ning几秒后,webroot目录包含:
chunk-stream0-00001.m4s chunk-stream1-00001.m4s
chunk-stream0-00002.m4s chunk-stream1-00002.m4s
chunk-stream0-00003.m4s chunk-stream1-00003.m4s
chunk-stream0-00004.m4s chunk-stream1-00004.m4s
chunk-stream1-00005.m4s
chunk-stream1-00006.m4s
chunk-stream1-00007.m4s
chunk-stream1-00008.m4s
chunk-stream1-00009.m4s
master.mpd
init-stream0.m4s
init-stream1.m4s
流无法在 dash.js
或 shaka-player 上加载(或播放),视频块有很多 404 (Not Found)
错误。播放器按顺序从 stream0 和 stream1 请求块,即 stream0-001 + stream1-001,然后是 stream0-002 + stream1-002 等等。
但是由于 stream0 仅从 001 到 004,因此在它尝试加载 stream0-005 到 009 时会出现很多 404 错误。
让FFmpeg运行一段时间后,差距越来越大。例如,stream0 是 62 到 75,但 stream1 是 174 到 187。此时重新加载播放器页面失败并显示 dash.all.debug.js:15615 [2055][FragmentController] No video bytes to push or stream is inactive.
并显示 404 错误 stream0 chunk 188(不还存在!)
FFmpeg 命令采用自DASH streaming from the top-down:
ffmpeg -re -i /mnt/swdevel/TestStreams/H264/ThreeHourMovie.mp4 \
-c:v libx264 -x264-params keyint=120:scenecut=0 -b:v 1M -c:a copy \
-f dash -dash_segment_type mp4 \
-seg_duration 2 \
-target_latency 3 \
-frag_type duration \
-frag_duration 0.2 \
-window_size 10 \
-extra_window_size 3 \
-streaming 1 \
-ldash 1 \
-use_template 1 \
-use_timeline 0 \
-write_prft 1 \
-fflags +nobuffer+flush_packets \
-format_options "movflags=+cmaf" \
-utc_timing_url "/pelican/testPlayers/time.php" \
master.mpd
而dash.js
播放器代码非常简单:
const srcUrl = "../ottWebRoot/playerTest/master.mpd";
var player = dashjs.MediaPlayer().create();
let autoPlay = false;
player.initialize(document.querySelector("#videoTagId"), srcUrl, autoPlay);
player.updateSettings(
{
streaming :
{
lowLatencyEnabled : true,
liveDelay : 2,
jumpGaps : true,
jumpLargeGaps : true,
smallGapLimit : 1.5,
}
});
要在清单中提供 UTCTiming
元素,小 time.php
URL returns 来自 Web 服务器的 UTC 时间:
<?php
print gmdate("Y-m-d\TH:i:s\Z");
?>
(它还显示最新 stream1/audio 块的 404 错误,这可能是另一个问题)
我不确定接下来要尝试什么。非常感谢任何建议。
编辑我
@Anonymous Coward 提出的更改键间隔的建议使事情有了很大改善。 stream0 和 stream1 的块处于锁步状态并且具有相同的序列号。
但是,在初始页面加载(未按播放)和播放过程中仍然存在许多 404 错误。
I 运行 watch -n 1 ls -lt <webRootFolder
并与浏览器控制台中的错误并排比较。很难比较,但它 看起来 就像浏览器正在尝试“在播放边缘”获取 FFmpeg 尚未创建的文件。见下图。
如何指示浏览器在获取边缘块之前稍等片刻?
编辑二
使用 shaka-player
而不是 dash.js
可以正常播放,没有 404 错误。配置为:
player.configure(
{
streaming:
{
lowLatencyMode: true,
inaccurateManifestTolerance: 0,
rebufferingGoal: 0.1,
}
});
客户端
- MacOS 10.12
- dash.js最新3.2.2
- Chrome79、Safari 12、FireFox v?
服务器
- 阿帕奇 2.4.37
- PHP 7.2.4(仅限时间函数)
- 森托斯 8
(供参考,这里是FFmpeg生成的mpd文件)
<?xml version="1.0" encoding="utf-8"?>
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mpeg:dash:schema:mpd:2011"
xmlns:xlink="http://www.w3.org/1999/xlink"
xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
profiles="urn:mpeg:dash:profile:isoff-live:2011"
type="dynamic"
minimumUpdatePeriod="PT500S"
availabilityStartTime="2021-05-24T14:50:00.263Z"
publishTime="2021-05-24T15:22:45.335Z"
timeShiftBufferDepth="PT50.0S"
maxSegmentDuration="PT2.0S"
minBufferTime="PT5.0S">
<ProgramInformation>
</ProgramInformation>
<ServiceDescription id="0">
<Latency target="3000" referenceId="0"/>
</ServiceDescription>
<Period id="0" start="PT0.0S">
<AdaptationSet id="0" contentType="video" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" frameRate="24/1" maxWidth="1280" maxHeight="682" par="15:8" lang="und">
<Resync dT="200000" type="0"/>
<Representation id="0" mimeType="video/mp4" codecs="avc1.64081f" bandwidth="1000000" width="1280" height="682" sar="1023:1024">
<ProducerReferenceTime id="0" inband="true" type="captured" wallClockTime="2021-05-24T14:50:00.263Z" presentationTime="0">
<UTCTiming schemeIdUri="urn:mpeg:dash:utc:http-xsdate:2014" value="/pelican/testPlayers/time.php"/>
</ProducerReferenceTime>
<Resync dT="5000000" type="1"/>
<SegmentTemplate timescale="1000000" duration="2000000" availabilityTimeOffset="1.800" availabilityTimeComplete="false" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
</SegmentTemplate>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="audio" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" lang="und">
<Resync dT="200000" type="0"/>
<Representation id="1" mimeType="audio/mp4" codecs="mp4a.40.2" bandwidth="116317" audioSamplingRate="48000">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
<ProducerReferenceTime id="1" inband="true" type="captured" wallClockTime="2021-05-24T14:50:00.306Z" presentationTime="0">
<UTCTiming schemeIdUri="urn:mpeg:dash:utc:http-xsdate:2014" value="/pelican/testPlayers/time.php"/>
</ProducerReferenceTime>
<Resync dT="21333" type="1"/>
<SegmentTemplate timescale="1000000" duration="2000000" availabilityTimeOffset="1.800" availabilityTimeComplete="false" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
</SegmentTemplate>
</Representation>
</AdaptationSet>
</Period>
<UTCTiming schemeIdUri="urn:mpeg:dash:utc:http-xsdate:2014" value="/pelican/testPlayers/time.php"/>
</MPD>
输入 ThreeHourMovie.mp4
的帧率为 24Hz(参见 AdaptationSet@frameRate
),因此将 keyint
设置为 120
将每五秒给出一个 IDR x264 的输出。
您正在指示 DASH 多路复用器(通过 seg_duration
)输出 2s 段并发出信号,但这是不可能的,因为段必须以 IDR 开头(如您链接的指南中所述)。所以 muxer 输出 5s 段,但在清单中发出 2s 信号,这显然是不正确的。
将 keyint
更改为 seg_duration
的正确倍数(即本例中的 keyint=48
),它可能会开始工作。
我在 Exoplayer 上也观察到了同样的情况。但是,如果我设置值
"-use_timeline 1" 问题不存在了。但是,将 use_timeline 设置为 1,您将不会在模板上有部分段。我不确定这是 ffmpeg 的错误。
我正在尝试从静态文件创建 MPEG-DASH“实时”流以测试各种低延迟模式。 FFmpeg 中的 DASH muxer 创建了两个 AdaptationSets,一个用于视频块,一个用于音频块。
但是,音频和视频块文件的创建速度不同(应该是这样吗?)。即,这里 stream0
是视频块,stream1
是音频块。 运行ning几秒后,webroot目录包含:
chunk-stream0-00001.m4s chunk-stream1-00001.m4s
chunk-stream0-00002.m4s chunk-stream1-00002.m4s
chunk-stream0-00003.m4s chunk-stream1-00003.m4s
chunk-stream0-00004.m4s chunk-stream1-00004.m4s
chunk-stream1-00005.m4s
chunk-stream1-00006.m4s
chunk-stream1-00007.m4s
chunk-stream1-00008.m4s
chunk-stream1-00009.m4s
master.mpd
init-stream0.m4s
init-stream1.m4s
流无法在 dash.js
或 shaka-player 上加载(或播放),视频块有很多 404 (Not Found)
错误。播放器按顺序从 stream0 和 stream1 请求块,即 stream0-001 + stream1-001,然后是 stream0-002 + stream1-002 等等。
但是由于 stream0 仅从 001 到 004,因此在它尝试加载 stream0-005 到 009 时会出现很多 404 错误。
让FFmpeg运行一段时间后,差距越来越大。例如,stream0 是 62 到 75,但 stream1 是 174 到 187。此时重新加载播放器页面失败并显示 dash.all.debug.js:15615 [2055][FragmentController] No video bytes to push or stream is inactive.
并显示 404 错误 stream0 chunk 188(不还存在!)
FFmpeg 命令采用自DASH streaming from the top-down:
ffmpeg -re -i /mnt/swdevel/TestStreams/H264/ThreeHourMovie.mp4 \
-c:v libx264 -x264-params keyint=120:scenecut=0 -b:v 1M -c:a copy \
-f dash -dash_segment_type mp4 \
-seg_duration 2 \
-target_latency 3 \
-frag_type duration \
-frag_duration 0.2 \
-window_size 10 \
-extra_window_size 3 \
-streaming 1 \
-ldash 1 \
-use_template 1 \
-use_timeline 0 \
-write_prft 1 \
-fflags +nobuffer+flush_packets \
-format_options "movflags=+cmaf" \
-utc_timing_url "/pelican/testPlayers/time.php" \
master.mpd
而dash.js
播放器代码非常简单:
const srcUrl = "../ottWebRoot/playerTest/master.mpd";
var player = dashjs.MediaPlayer().create();
let autoPlay = false;
player.initialize(document.querySelector("#videoTagId"), srcUrl, autoPlay);
player.updateSettings(
{
streaming :
{
lowLatencyEnabled : true,
liveDelay : 2,
jumpGaps : true,
jumpLargeGaps : true,
smallGapLimit : 1.5,
}
});
要在清单中提供 UTCTiming
元素,小 time.php
URL returns 来自 Web 服务器的 UTC 时间:
<?php
print gmdate("Y-m-d\TH:i:s\Z");
?>
(它还显示最新 stream1/audio 块的 404 错误,这可能是另一个问题)
我不确定接下来要尝试什么。非常感谢任何建议。
编辑我
@Anonymous Coward 提出的更改键间隔的建议使事情有了很大改善。 stream0 和 stream1 的块处于锁步状态并且具有相同的序列号。
但是,在初始页面加载(未按播放)和播放过程中仍然存在许多 404 错误。
I 运行 watch -n 1 ls -lt <webRootFolder
并与浏览器控制台中的错误并排比较。很难比较,但它 看起来 就像浏览器正在尝试“在播放边缘”获取 FFmpeg 尚未创建的文件。见下图。
如何指示浏览器在获取边缘块之前稍等片刻?
编辑二
使用 shaka-player
而不是 dash.js
可以正常播放,没有 404 错误。配置为:
player.configure(
{
streaming:
{
lowLatencyMode: true,
inaccurateManifestTolerance: 0,
rebufferingGoal: 0.1,
}
});
客户端
- MacOS 10.12
- dash.js最新3.2.2
- Chrome79、Safari 12、FireFox v?
服务器
- 阿帕奇 2.4.37
- PHP 7.2.4(仅限时间函数)
- 森托斯 8
(供参考,这里是FFmpeg生成的mpd文件)
<?xml version="1.0" encoding="utf-8"?>
<MPD xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="urn:mpeg:dash:schema:mpd:2011"
xmlns:xlink="http://www.w3.org/1999/xlink"
xsi:schemaLocation="urn:mpeg:DASH:schema:MPD:2011 http://standards.iso.org/ittf/PubliclyAvailableStandards/MPEG-DASH_schema_files/DASH-MPD.xsd"
profiles="urn:mpeg:dash:profile:isoff-live:2011"
type="dynamic"
minimumUpdatePeriod="PT500S"
availabilityStartTime="2021-05-24T14:50:00.263Z"
publishTime="2021-05-24T15:22:45.335Z"
timeShiftBufferDepth="PT50.0S"
maxSegmentDuration="PT2.0S"
minBufferTime="PT5.0S">
<ProgramInformation>
</ProgramInformation>
<ServiceDescription id="0">
<Latency target="3000" referenceId="0"/>
</ServiceDescription>
<Period id="0" start="PT0.0S">
<AdaptationSet id="0" contentType="video" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" frameRate="24/1" maxWidth="1280" maxHeight="682" par="15:8" lang="und">
<Resync dT="200000" type="0"/>
<Representation id="0" mimeType="video/mp4" codecs="avc1.64081f" bandwidth="1000000" width="1280" height="682" sar="1023:1024">
<ProducerReferenceTime id="0" inband="true" type="captured" wallClockTime="2021-05-24T14:50:00.263Z" presentationTime="0">
<UTCTiming schemeIdUri="urn:mpeg:dash:utc:http-xsdate:2014" value="/pelican/testPlayers/time.php"/>
</ProducerReferenceTime>
<Resync dT="5000000" type="1"/>
<SegmentTemplate timescale="1000000" duration="2000000" availabilityTimeOffset="1.800" availabilityTimeComplete="false" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
</SegmentTemplate>
</Representation>
</AdaptationSet>
<AdaptationSet id="1" contentType="audio" startWithSAP="1" segmentAlignment="true" bitstreamSwitching="true" lang="und">
<Resync dT="200000" type="0"/>
<Representation id="1" mimeType="audio/mp4" codecs="mp4a.40.2" bandwidth="116317" audioSamplingRate="48000">
<AudioChannelConfiguration schemeIdUri="urn:mpeg:dash:23003:3:audio_channel_configuration:2011" value="2" />
<ProducerReferenceTime id="1" inband="true" type="captured" wallClockTime="2021-05-24T14:50:00.306Z" presentationTime="0">
<UTCTiming schemeIdUri="urn:mpeg:dash:utc:http-xsdate:2014" value="/pelican/testPlayers/time.php"/>
</ProducerReferenceTime>
<Resync dT="21333" type="1"/>
<SegmentTemplate timescale="1000000" duration="2000000" availabilityTimeOffset="1.800" availabilityTimeComplete="false" initialization="init-stream$RepresentationID$.m4s" media="chunk-stream$RepresentationID$-$Number%05d$.m4s" startNumber="1">
</SegmentTemplate>
</Representation>
</AdaptationSet>
</Period>
<UTCTiming schemeIdUri="urn:mpeg:dash:utc:http-xsdate:2014" value="/pelican/testPlayers/time.php"/>
</MPD>
输入 ThreeHourMovie.mp4
的帧率为 24Hz(参见 AdaptationSet@frameRate
),因此将 keyint
设置为 120
将每五秒给出一个 IDR x264 的输出。
您正在指示 DASH 多路复用器(通过 seg_duration
)输出 2s 段并发出信号,但这是不可能的,因为段必须以 IDR 开头(如您链接的指南中所述)。所以 muxer 输出 5s 段,但在清单中发出 2s 信号,这显然是不正确的。
将 keyint
更改为 seg_duration
的正确倍数(即本例中的 keyint=48
),它可能会开始工作。
我在 Exoplayer 上也观察到了同样的情况。但是,如果我设置值 "-use_timeline 1" 问题不存在了。但是,将 use_timeline 设置为 1,您将不会在模板上有部分段。我不确定这是 ffmpeg 的错误。