首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PTS必须从0开始吗?

PTS必须从0开始吗?
EN

Stack Overflow用户
提问于 2018-06-28 14:14:00
回答 1查看 10.2K关注 0票数 6

我见过很多关于视频PTS值的问题,它们不是从零开始,或者是询问如何使它们从零开始。我知道使用ffmpeg我可以做一些像ffmpeg -i <video> -vf="setpts=PTS-STARTPTS" <output>这样的事情来修复这类事情

然而,我的理解是,PTS值不从零开始。例如,如果您加入了一个实时流,那么它可能已经进行了一个小时,并且PTS已经在3600000+的某个地方,但是您的视频播放器忠实地显示一切都很好。因此,如果我故意创建一个具有PTS值的视频,比如从当前的挂钟时间开始,那么我就不会有问题了。

我想使用ffmpeg发送一个实时流,但是将当前时间嵌入到流中。这既可用于在流处于活动状态时的延迟计算,也可用于稍后确定流最初播放的时间。根据我对PTS的理解,像这样简单的东西可能会起作用:

代码语言:javascript
复制
ffmpeg -i video.flv -vf="setpts=RTCTIME" rtmp://<output>

然而,当我尝试这样做时,ffmpeg输出如下:

代码语言:javascript
复制
frame=   93 fps= 20 q=-1.0 Lsize=    9434kB time=535020:39:58.70 bitrate=   0.0kbits/s speed=1.35e+11x

请注意"time“的非常大的值、比特率(0.0kbit)和速度(135000000000x!!!)

起初,我认为这个问题可能是我的时间基础,所以我尝试了以下几点:

代码语言:javascript
复制
ffmpeg -i video.flv -vf="settb=1/1K,setpts=RTCTIME/1K" rtmp://<output>

这意味着一切都是毫秒(1 PTS =1ms),但我也有同样的问题(大量的时间、零比特率和巨大的速度)。

我对PTS有什么误解吗?不允许从非零值开始吗?还是我只是做错了什么?

更新

在查看了@Gyan的答案之后,我将命令格式化如下:

代码语言:javascript
复制
ffmpeg -re -i video.flv -vf="settb=1/1K, setpts=(RTCTIME-RTCSTART)/1K" -output_ts_offset $(date +%s.%N) rtmp://<output>

这样,PTS值将匹配“自流启动以来的毫秒”,并将被流的启动时间所抵消(理论上使PTS =时间戳在服务器上)。

看起来它的编码更好:

代码语言:javascript
复制
frame=  590 fps=7.2 q=22.0 size=   25330kB time=00:01:21.71 bitrate=2539.5kbits/s dup=0 drop=1350 speed=   1x 

现在的比特率是正确的,时间是准确的,速度也不是惊人的。但是每秒的帧仍然有点差(源视频是24 fps,但是它报告了每秒7.2帧)

当我试图从另一端观看流时,视频与音频不同步,并以大约双倍的正常速度播放了一段时间,然后视频冻结了,音频继续播放。

此外,当我将流转储到一个文件(ffmpeg -i rtmp://<output> dump.mp4)并使用ff探针(ffprobe -show_entries packet=codec_type,pts dump.mp4 | grep "video" -B 1 -A 2)查看PTS时间戳时,时间戳似乎根本没有显示服务器时间:

代码语言:javascript
复制
...
--
[PACKET]
codec_type=video
pts=131072
[/PACKET]
[PACKET]
codec_type=video
pts=130048
[/PACKET]
--
[PACKET]
codec_type=video
pts=129536
[/PACKET]
[PACKET]
codec_type=video
pts=130560
[/PACKET]
--
[PACKET]
codec_type=video
pts=131584
[/PACKET]

这个问题只是与RTMP不兼容吗?

更新2

我删除了视频过滤器,现在编码如下:

代码语言:javascript
复制
ffmpeg -re -i video.flv -output_ts_offset $(date +%s.%N) rtmp://<output>

这是正确的编码:

代码语言:javascript
复制
frame=  910 fps= 23 q=25.0 size=   12027kB time=00:00:38.97 bitrate=2528.2kbits/s speed=0.981x 

为了验证PTS值是否正确,我将输出转储到如下文件:

代码语言:javascript
复制
ffmpeg -i rtmp://<output> -copyts -write_tmcd 0 dump.mp4

我尝试将它保存为dump.flv (因为它是RTMP),但是这引发了错误:

代码语言:javascript
复制
[flv @ 0x5600f24b4620] Audio codec mp3 not compatible with flv

这有点奇怪,因为视频不是mp3编码的(它是speex),但无论如何。

在转储此文件时,重复弹出下列错误:

代码语言:javascript
复制
frame=    1 fps=0.0 q=0.0 size=       0kB time=00:00:09.21 bitrate=   0.0kbits/s dup=0 dr
43090023 frame duplication too large, skipping
43090027 frame duplication too large, skipping
    Last message repeated 3 times
43090031 frame duplication too large, skipping
    Last message repeated 3 times
43090035 frame duplication too large, skipping

在VLC中播放生成的视频,播放音频流,但不显示视频。然后,我尝试用ffprobe探测这个视频,查看视频PTS值:

代码语言:javascript
复制
ffprobe -show_entries packet=codec_type,pts dump.mp4 | grep "video" -B 1 -A 2

这只返回PTS不像我预期的那么大的单个视频帧:

代码语言:javascript
复制
[PACKET]
codec_type=video
pts=1020
[/PACKET]

这是一项令人惊讶的艰巨任务。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-28 14:58:16

这意味着一切都是毫秒(1 PTS =1ms),但我也有同样的问题(大量的时间、零比特率和巨大的速度)。

这只是统计计算的一个副作用,它没有参照观察到的启动PTS来测量时间。比特率(位/秒)和速度(输出持续时间/实时)计算只是这个设计的牺牲品。

如果容器允许,您可以从非零PTS开始。最好的方法是使用选项-output_ts_offset N,其中N是以秒为单位的。

在编码之前更改时间戳是有风险的,因为ffmpeg的框架转换方法使用时间戳来检查同步漂移,并做出删除或复制帧的决定。对CFR输出特别重要。编码器的速率控制流也可能会失控。

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51085133

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档