The native video format Kinovea uses is a format (codec) that contains a full image for every frame. This can be mjpeg or rawvideo, whereby all compressed formats are using the mjpeg codec.
The compressed format can be stored as mp4, mkv or avi container.
The uncompressed format can be stored as mkv or avi container (the mp4 container always uses compressed images)
All these formats have a full image stored in each single video frame that is perfect in doing video observation and editing frame by frame. Cutting the video is simple due to the existence of a full images in every frames.
However, some video programs (like windows media player) cannot replay these formats (codecs), if not an appropriate codec is installed separately.
In your case, the video format (or better named codec) is H.264 in a mp4 container. This common codec can be replayed by most of all video players. However, it contains K-frames, having a full image and B-frames in between, not containing a full image.
Therefore, a video with a H.264 codec cannot be cut at any position without having black frames. It has to be re-encoded to get a clean output video.
The quality of the output video depends on the parameters you are using during re-encoding. If they are not specified, ffmpeg uses default values (about medium quality).
Every frame in a video (full frame like mjpeg, K-frame or B-frame) contains a PTS (presentation time stamp) that determines the position of this specific frame in the video line. The first frame contains the value 0 (under standard conditions).
If you cut or trim a video starting after the first frame, the first frame in the output video contains a value of non 0. Therefore, you have to correct the PTS during the trimming procedure. If you omit this step, the video program often does not know when to start the video. Kinovea expects the first frame to have a PTS as 0. VLC may recognize the non 0 value and corrects it.
To control the quality of the output, parameters may be used depending on the type of codec.
If the target should be H.264 codec (mp4 container), the -crf (value) and -preset (value) parameters are appropriate
-crf 0-51: 0 is the best, 51 is the lowest quality
-preset (value) has a literal parameter like fast, slow,…
a list can be found at https://trac.ffmpeg.org/wiki/Encode/H.264
I’ve never used the -g (value) parameters. You might use -g 0 to prevent any B-frames between K-frames. But I think it is more consistent to either use the H.264 or the mjpeg codec.
In the following examples, a segment of a video is cut from position 0.5 to 0.8 second
Example of creating a "good“ quality output video with the H.264 codec might be:
FFmpeg -i Infile.mp4 -ss 0.5 -to 0.8 -c:v libx264 -crf 5 -preset slow outfile.mp4
If the target should be a mjpeg codec (mp4 container), the -crf and -preset may not be used. Instead use
-q:v (value), value ranging from 2-32, 2: highest quality, 32: lowest quality
Example of creating a "good“ quality output video with the mjpeg codec might be:
FFmpeg -i infile.mp4 -ss 0.5 -to 0.8 -c:v mjpeg -q:v 5 outfile.mp4
Cutting a video at an exact position:
If the source video contains the mjpeg codec, the start/end/duration time position can be used without re-encoding:
FFmpeg -i Infile.mp4 -ss 0.5 -to 0.8 outfile.mp4
or better
FFmpeg -i infile.mp4 -ss 0.5 -to 0.8 -c:v copy outfile.mp4
(the "copy" parameters prevents re-encoding)
Influence of time position on the exactness:
If the start position is used before the infile, ffmpeg uses an approximation to find the start position, but it is faster:
FFmpeg -ss 0.5 -i infile.mp4 -to 0.8 …
If the start position is used after the infile, ffmpeg uses a more exact frame position to find the start position, but is somehow slower:
FFmpeg -i infile.mp4 -ss 0.5 -to 0.8 …
To create a video having a correct PTS-value of 0 for the first frame, a video-filter has to be inserted (re-encoding is mandatory)
FFmpeg -infile.mp4 -ss 0.5 -to 0.8 -vf "setpts=PTS-STARTPTS“ -c:v mjpeg -q:v 5 outfile.mp4
To tell ffmpeg the frame rate of the invideo, -r (frame rate) may be used before the infile, specifying the frame rate of the infile
FFmpeg -r 100 -i infile.mp4 …
However, you should be sure that this value is correct.
You might determine it using the ffprobe- program that comes with ffmpeg, creating a batch-file (i.e. ffprobe2.bat)
@echo off
<path to ffprobe>\ffprobe.exe -v error -show_format -show_streams %1
pause
Then call it at the command line:
ffprobe2 infile.mp4
and it displays the metadata of the infile.mp4
My recommendation in your cases could be the following:
high quality (not highest) H.264 target video:
ffmpeg -i unCut.MP4 -ss 18.440 -to 20.440 -vf "setpts=PTS-STARTPTS" -c:v libx264 -crf 3 -preset slow cut.MP4
high quality mjpeg target video:
ffmpeg -i unCut.MP4 -ss 18.440 -to 20.440 -vf "setpts=PTS-STARTPTS" -c:v mjpeg -q:v 5 cut.MP4
REMARK:
Only use Quote ABOVE for the Videofilter.
Hope that helps