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?
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, andffmpeg
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:
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 the10
as needed based on your video's framerate.Tune for zero-latency: Add
-tune zerolatency
for real-time applications.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 ismedium
. 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: