Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does PTS have to start at 0?

I've seen a number of questions regarding video PTS values not starting at zero, or asking how to make them start at zero. I'm aware that using ffmpeg I can do something like ffmpeg -i <video> -vf="setpts=PTS-STARTPTS" <output> to fix this kind of thing

However it's my understanding that PTS values don't have to start at zero. For instance, if you join a live stream then odds are it has been going on for an hour and the PTS is already somewhere around 3600000+ but your video player faithfully displays everything just fine. Therefore I would expect there to be no problem if I intentionally created a video with a PTS value starting at, say, the current wall clock time.

I want to send a live stream using ffmpeg, but embed the current time into the stream. This can be used both for latency calculation while the stream is live, and later to determine when the stream was originally aired. From my understanding of PTS, something as simple as this should probably work:

ffmpeg -i video.flv -vf="setpts=RTCTIME" rtmp://<output>

When I try this, however, ffmpeg outputs the following:

frame=   93 fps= 20 q=-1.0 Lsize=    9434kB time=535020:39:58.70 bitrate=   0.0kbits/s speed=1.35e+11x

Note the extremely large value for "time", the bitrate (0.0kbits), and the speed (135000000000x!!!)

At first I thought the issue might be my timebase, so I tried the following:

ffmpeg -i video.flv -vf="settb=1/1K,setpts=RTCTIME/1K" rtmp://<output>

This puts everything in terms of milliseconds (1 PTS = 1 ms) but I had the same issue (massive time, zero bitrate, and massive speed)

Am I misunderstanding something about PTS? Is it not allowed to start at non-zero values? Or am I just doing something wrong?

Update

After reviewing @Gyan's answer, I formatted my command like so:

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

This way the PTS values would match up to "milliseconds since the stream started" and would be offset by the start time of the stream (theoretically making PTS = timestamp on the server)

This looked like it was encoding better:

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 

Bitrate was now correct, time was accurate, and speed was not outrageous. The frames per second was still a bit off, though (the source video is 24 fps but it's reporting 7.2 frames per second)

When I tried watching the stream from the other end, the video was out of sync with the audio and played at about double normal speed for a while, then the video froze and the audio continued without it

Furthermore, when I dumped the stream to a file (ffmpeg -i rtmp://<output> dump.mp4) and look at the PTS timestamps with ffprobe (ffprobe -show_entries packet=codec_type,pts dump.mp4 | grep "video" -B 1 -A 2) the timestamps didn't seem to show server time at all:

...
--
[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]

Is the problem just an incompatibility with RTMP?

Update 2

I've removed the video filter and I'm now encoding like so:

ffmpeg -re -i video.flv -output_ts_offset $(date +%s.%N) rtmp://<output>

This is encoding correctly:

frame=  910 fps= 23 q=25.0 size=   12027kB time=00:00:38.97 bitrate=2528.2kbits/s speed=0.981x 

In order to verify that the PTS values are correct, I'm dumping the output to a file like so:

ffmpeg -i rtmp://<output> -copyts -write_tmcd 0 dump.mp4

I tried saving it as dump.flv (since it's RTMP) however this threw the error:

[flv @ 0x5600f24b4620] Audio codec mp3 not compatible with flv

This is a bit weird since the video isn't mp3-encoded (it's speex) - but whatever.

While dumping this file the following error pops up repeatedly:

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

Playing the resulting video in VLC plays an audio stream but displays no video. I then attempt to probe this video with ffprobe to look at the video PTS values:

ffprobe -show_entries packet=codec_type,pts dump.mp4 | grep "video" -B 1 -A 2

This returns only a single video frame whose PTS is not large like I would expect:

[PACKET]
codec_type=video
pts=1020
[/PACKET]

This has been a surprisingly difficult task

like image 746
stevendesu Avatar asked Jun 28 '18 14:06

stevendesu


1 Answers

This puts everything in terms of milliseconds (1 PTS = 1 ms) but I had the same issue (massive time, zero bitrate, and massive speed)

This is just a side-effect of the stats calculation which doesn't measure time with reference to the observed starting PTS. The bitrate (bits/second) and speed (output duration / real time) calculations are simply casualties of this design.


If the container allows it, you can start at non-zero PTS. The advisable way to do this is using the option -output_ts_offset N where N is in seconds.

Changing the timestamps prior to encoding is risky since ffmpeg's framerate conversion method uses timestamps to check sync drift and make decisions about dropping or duplicating frames. Especially important for CFR output. Encoders' rate-control flow may also go haywire.

like image 187
Gyan Avatar answered Nov 11 '22 17:11

Gyan