How to convert MP4 frame rate like 14.939948fps to 15fps

851 Views Asked by At

Description

I pushed a USB camera stream by ffmpeg to a RTMP stream server which is called SRS.

The SRS had saved a MP4 file for me. The frame rate is not a common value in VLC - it's 14.939948. I've checked it out - It seems to be the 'ntsc' format.

Meanwhile, I had received the stream by OpenCV and saved it as another MP4 file.They're not synchronized.

I have tried to convert the frame rate by ffmpeg but was still not synchronized. The only way to make it is to put it in Adobe Premiere and modify the frame rate. Here is the ffmpeg commands I executed:

ffmpeg -i 1639444871684_copy.mp4 -filter:v fps=15 out.mp4

Aside from the stream server, how can I convert the frame rate to normal and keep synchronized at the same time?

3

There are 3 best solutions below

0
On

Answer myself. Here is my method: Read by OpenCV and write frames to a new file at 15FPS. They're going to be synchronized.

1
On

with -r

ffmpeg -i 1639444871684_copy.mp4 -r 15 out.mp4
1
On

Note: Relying on FPS for live streaming is not recommended, as RTMP/FLV always uses a fixed TBN of 1k, which can introduce deviations when publishing streams via RTMP or recording to formats like TS/MP4.

Note: For WebRTC, the FPS varies. Please refer to Would WebRTC use a constant frame rate to capture video frame or Variable Frame Rate (VFR) for more information.

The issue is not related to SRS or FPS, and can be replicated using FFmpeg.

  1. Use FFmpeg to transcode doc/source.flv from 25fps to 15fps, then publish to SRS via RTMP (15fps).
  2. Use FFmpeg to record the RTMP (15fps) stream as output.mp4 (15fps).
  3. Use VLC to play the output.mp4 (15fps), and you'll notice that the FPS is not exactly 15fps.

First, start SRS with the following configuration, ensuring DVR is disabled:

# ./objs/srs -c test.conf
listen              1935;
daemon              off;
srs_log_tank        console;

vhost __defaultVhost__ {
}

Run FFmpeg to transcode and publish to SRS, changing the FPS to 15:

cd srs/trunk
ffmpeg -re -i doc/source.flv -c:v libx264 -r 15 -c:a copy \
  -f flv rtmp://localhost/live/livestream

Record the RTMP stream (at 15fps) to output.mp4. In FFmpeg logs, you'll see that the FPS is 15:

ffmpeg -f flv -i rtmp://localhost/live/livestream -c copy -y output.mp4

Use VLC to play the output.mp4 (15fps) and open Window -> Media Information. You'll find that the FPS fluctuates around 14.8fps, not exactly 15fps.

This deviation occurs because the TBN of RTMP/FLV is fixed at 1000 (1k tbn, with each frame being approximately 66.67ms). The deviation is introduced when publishing MP4 to RTMP streams. It's not caused by DVR, but rather by the RTMP/FLV TBN.

Note: For SRS, using a fixed TBN of 1k may not be the best choice, as it's not ideal for MP4 duration. The issue srs#2790 has been reopened.

In conclusion, the framerate/FPS is not a fixed value; it's merely an indicator for the stream. Players rely on DTS/PTS to determine when and how to render images.