FFmpeg how to extract time fragments of exact duration at set intervals? - ffmpeg

I have a video file, I know how to extract segments with ffmpeg and setting the keyframes to do so exact.
However, I would like to extract a segment of a certain duration, say 1 minute, then wait 50 seconds, again segment 1 minute, wait 50 seconds, again segment 1 minute, etc. until the end of the video file.
How can I accomplish this?
Is it possible to use a list.txt as cut input?

Let's call your segment duration X and interval between end of one segment and start of another Y. Both in seconds. Use
ffmpeg -i in.mp4 -vf select='lt(mod(t,X+Y),X)',setpts=N/FRAME_RATE/TB -force_key_frames expr:gte(t,n_forced*X) -f segment -segment_time X out%d.ts
You may want to add -reset_timestamps 1 for zero-start timestamps for each segment. Audio is ignored and will be out of sync if present. Add a corresponding audio filter with aselect/asetpts to cut audio in sync.

Related

Segmenting a video live stream into videos of a fixed length using ffmpeg

I want to use an ffmpeg command to save segments of length 10 seconds from a video being streamed via HTTP using VLC.
The command I used to carry out the task is:
ffmpeg -i http://[Local IPv4 address]:8080 -f segment -segment_time 10 -vcodec copy -acodec copy -reset_timestamps 1 video%03d.mp4
However, the lengths of the output videos I'm receiving are around 8.333 or 16.666 seconds in duration. (The videos video000.mp4, video005.mp4, video010.mp4, video015.mp4... have duration of around 16.666 seconds and the remaining videos have duration of around 8.333 seconds).
I'm aware that the segmentation of input video happens based on the occurrences of keyframes in the video. It appears that the key frames in the video being streamed occur with an interval of around 8 seconds.
Is there a way to obtain video segments that are closer to 10 seconds in duration from the live stream of such a video?
Also, I occasionally get the "Non-monotonous DTS in output stream 0:0" warning while executing the above command. I tried using different flags (+genpts, +igndts, +ignidx) hoping that the warning message would not be displayed, but no luck. Is it possible that there is any correlation between this warning and the issue with lengths of the segments?

Is there a way to cut first 1 second of video from .webm without keyframe present using Ffmpeg?

Recently I had a task to process several thousand videos, both .mp4 and .webm. The goal was to cut 1 second off from the front of the video. As a constraint, I wanted to avoid re-encoding the videos, as the number of jobs would take far too much time. The .mp4 files went smoothly, each job taking only a few seconds.
However, when trying to accomplish the same thing for the .webm files, I've hit a block. This is command I am running:
ffmpeg -i downloaded_raw_vids/{{vid_hash}}.webm -ss 00:00:01 -map 0 -c copy trimmed_videos/{video_url}.webm
What seems to happen is that no cut or edit happens whatsoever on the .webm files. Now if I change the timestamp to something like
ffmpeg -i downloaded_raw_vids/{{vid_hash}}.webm -ss 00:00:15 -map 0 -c copy trimmed_videos/{video_url}.webm
I end up with a file that has roughly the first 10 seconds cut out, but not the 15 seconds specified.
My understanding is that .webm files can only be cut on keyframes, and the keyframes are too sparse to actually cut around the 1 second mark as desired originally. It does seem like the first keyframe is present around the 10 second mark, which is why the 15 second argument cuts at that point.
Ultimately I am wondering if there is a way to accomplish the 1 second cut, without having to re-encode every .webm file I am working with.
Ultimately I am wondering if there is a way to accomplish the 1 second cut, without having to re-encode every .webm file I am working with.
No. you can only cut on keyframes otherwise it requires re-encoding. There are no tricks or magic, it is a property of how temporal video compression works.

Why are screenshots taken with ffmpeg uneven in time?

I'm using the following ffmpeg command to take screenshots every 5 seconds of a video file that is 85 seconds long:
ffmpeg -i out2.mp4 -vf fps=1/05 img%03d.jpg
I get 18 files When I look at the resulting screenshots, they are 5 seconds apart, but the first frame starts around 3 seconds, the second is then 8 seconds, and so on. How do I get it to start with the very first frame, and then go 5 seconds apart on subsequent frames?
You're the using the fps function, whose primary use is to change the framerate, not select specific frames. When using it to reduce framerate, it uses a regular cadence to retain frames. For 1/5, that's the middle frame in a 5-second segment.
Use the select filter.
ffmpeg -i out2.mp4 -vf select='lte(mod(t,5),0.01)' -vsync 0 img%03d.jpg

ffmpeg - make a seamless loop with a crossfade

I want to apply a crossfade to the last x frames of a video with the first x frames in order to obtain a seamless loop.
How can I do that?
Let's say your video is 30 seconds long and your fade is 1 second long. Your command would be
ffmpeg -i video.mp4 -filter_complex
"[0]split[body][pre];
[pre]trim=duration=1,format=yuva420p,fade=d=1:alpha=1,setpts=PTS+(28/TB)[jt];
[body]trim=1,setpts=PTS-STARTPTS[main];
[main][jt]overlay" output.mp4
The video is split into two identical streams. The first is trimmed to just the first second, has an alpha channel added, and then faded. The last filter on the first stream delays it by 28 seconds since the final output will have trimmed off the first second of the original clip and overlap with the last second. The 2nd stream is trimmed to start at t=1 and the processed first stream is overlaid on the 2nd. Since the alpha channel is faded in the first stream, it crossfades in.

Create thumbnails tile for time range of video

I need to create, let's say, 12 thumbnails from video, but skip 10 percent in the beginning and in the ending. I found this thing, but it just takes every 1000th frame. In my case this range will be variable and it will be better if it will be in seconds. Can't figure out how to do this with ffmpeg, don't work with it much.
ffmpeg -ss $skip_time -i $input_path -vframes 1 -vf select=isnan(prev_selected_t)+gte(t-prev_selected_t\,$screenshot_time), scale=iw*min($width/iw\,$height/ih):ih*min($width/iw\,$height/ih),pad=($width):($height):($width-iw)/2):($height-ih)/2),tile=3x4 -vcodec mjpeg $output_filename
$skip_time - time to skip from the beginning
$screenshot_time - time interval for screenshots to be taken
These values should be precalculated, I used ffprobe to get video duration.

Resources