new2cpp
new2cpp

Reputation: 3667

ffmpeg generates random length video when using libx265

I am using ffmpeg to record my outdoor camera video stream. The below script works pretty well to split the stream to be 1 hour video.

ffmpeg -nostdin -loglevel error -rtsp_transport tcp -i rtsp://username:[email protected]/stream1 -vcodec copy -acodec copy -f segment -reset_timestamps 1 -segment_time 3600 -segment_format mkv -segment_atclocktime 1 -strftime 1 ~/onedrive/camera/%Y%m%dT%H-%M-%S.mkv 2> ~/projects/ip-camera/upload.log

The only issue is the video file is too big, around 1GB for 1hour video file.

So I am trying to use libx265 to compress the video

ffmpeg -nostdin -loglevel error -rtsp_transport tcp -i rtsp://username:[email protected]/stream1 -c:v libx265 -crf 28 -acodec copy -f segment -reset_timestamps 1 -segment_time 3600 -segment_format mkv -segment_atclocktime 1 -strftime 1 ~/onedrive/camera/%Y%m%dT%H-%M-%S.mkv 2> ~/projects/ip-camera/upload.log

The strange thing is now ffmpeg is generating random length video, between 5 minutes to 10 minutes for each video file.

What's wrong with my updated script? Couldn't ffmpeg generate 1-hour length video just as before by initial script?

Upvotes: -1

Views: 176

Answers (1)

user14816009
user14816009

Reputation:

The most common issue when dealing with segmentation and transcoding simultaneously is keyframes (or I-frames). When segmenting, ffmpeg will ideally split the video at keyframes to avoid corruption or unplayable segments.

In your initial command, you used -vcodec copy, which does a straight copy without transcoding. Therefore, the natural keyframe intervals from the source are retained, and ffmpeg was probably segmenting on those keyframes that conveniently existed around the 1-hour mark.

However, when you introduced libx265, the encoding process could introduce keyframes at different intervals than the source or your desired segmentation point.

To solve this:

  1. Force keyframes: You can force keyframes at specific intervals, which can help in determining when to split the video. For example, to set keyframes every 10 seconds (assuming 30 fps), you'd use -force_key_frames "expr:gte(t,n_forced*10)". Adjust the 10 as needed based on your video's framerate.

  2. Tune for zero-latency: Add -tune zerolatency for real-time applications.

  3. Preset: You might want to specify a preset. x265 has presets that determine the compression-speed trade-off. Slower presets will compress more (smaller output file) but will take longer. Common presets are ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow. The default is medium. For faster encoding (at the expense of a slightly larger file size), you can try -preset fast.

Combining these, your command would look something like:

ffmpeg -nostdin -loglevel error -rtsp_transport tcp -i rtsp://username:[email protected]/stream1 -c:v libx265 -crf 28 -preset fast -tune zerolatency -force_key_frames "expr:gte(t,n_forced*10)" -acodec copy -f segment -reset_timestamps 1 -segment_time 3600 -segment_format mkv -segment_atclocktime 1 -strftime 1 ~/onedrive/camera/%Y%m%dT%H-%M-%S.mkv 2> ~/projects/ip-camera/upload.log

Upvotes: 0

Related Questions