Have FFMpeg output images more consistently when reading from a stream - ffmpeg

I am currently seeing an issue where FFMPEG seems to write my images in bursts. When I run the following command:
ffmpeg -i <URL> -vf fps=fps=1 -f image2 image-%d.png
I get progress updates every two seconds, at which point immediately image-(n).png and image-(n+1).png are written in quick succession.
Is it possible to have these images output more consistently? I would prefer to have the output speed be the same as the designated FPS (so one image per second).
I am using a Python script to do some processing on these images and I am able to better maximize my throughput if these images came more consistently.

You can add -re before -i to operate in real time. However I suspect the frames are being written regularly, just whatever method you are using to get fs updates is polled or coalesced

Related

How to remove a frame with ffmpeg without re-encoding?

I am making a datamoshing program in C++, and I need to find a way to remove one frame from a video (specifically, the p-frame right after a sequence jump) without re-encoding the video. I am currently using h.264 but would like to be able to do this with VP9 and AV1 as well.
I have one way of going about it, but it doesn't work for one frustrating reason (mentioned later). I can turn the original video into two intermediate videos - one with just the i-frame before the sequence jump, and one with the p-frame that was two frames later. I then create a concat.txt file with the following contents:
file video.mkv
file video1.mkv
And run ffmpeg -y -f concat -i concat.txt -c copy output.mp4. This produces the expected output, although is of course not as efficient as I would like since it requires creating intermediate files and reading the .txt file from disk (performance is very important in this project).
But worse yet, I couldn't generate the intermediate videos with ffmpeg, I had to use avidemux. I tried all sorts of variations on ffmpeg -y -ss 00:00:00 -i video.mp4 -t 0.04 -codec copy video.mkv, but that command seems to really bug out with videos of length 1-2 frames - while it works for longer videos no problem. My best guess is that there is some internal checker to ensure the output video is not corrupt (which, unfortunately, is exactly what I want it to be!).
Maybe there's a way to do it this way that gets around that problem, or better yet, a more elegant solution to the problem in the first place.
Thanks!
If you know the PTS or data offset or packet index of the target frame, then you can use the noise bitstream filter. This is codec-agnostic.
ffmpeg -copyts -i input -c copy -enc_time_base -1 -bsf:v:0 noise=drop=eq(pos\,11291) out
This will drop the packet from the first video stream stored at offset 11291 in the input file. See other available variables at http://www.ffmpeg.org/ffmpeg-bitstream-filters.html#noise

What does "Error in the pull function" mean while executing ffmpeg command?

I'm trying to generate a video from multiple video sources (https urls).
If I use say 8 video sources it works as expected. But if I need say 30 sources, it starts to work as expected, but at some moment a lot of errors appear.
I believe the main one is Error in the pull function..
Such a video-source appears in the output file but not a full requested part (e.g., I set trim=0:5, but ffmpeg generates only 3 seconds).
I tried different videos, different cropped parts, loaded sources to aws s3, but can't identify a "bad case", it's reproduced with different options.
My command looks like this:
ffmpeg -y
-i "https://player.vimeo.com/external/399541658.hd.mp4?s=5432956383527af00bb74b41c120bbb84ff3ac5e&profile_id=175&oauth2_token_id=57447761"
...
-i "https://player.vimeo.com/external/464966383.hd.mp4?s=648aa8277259c499f1d05d6330f9922932c080a6&profile_id=175&oauth2_token_id=57447761"
-i "https://test.com/development/videos/dc3c32cf9a194db1bb52/sources/5q5e3j2h57.mp3"
-filter_complex "[0:v]trim=0:5.64,setpts=PTS-STARTPTS,scale=1920x1080,setdar=16/9[v0];[1:v]trim=0:8,setpts=PTS-STARTPTS,scale=1920x1080,setdar=16/9,loop=0:32767[v1]; ... [10:v]trim=0:13,setpts=PTS-STARTPTS,scale=1920x1080,setdar=16/9[v10];[v0] ... [v10] concat=n=11:v=1 [video];[11:a] atrim=0:99.29 [audio]"
-vsync 2 -map [video] -map [audio] output.mp4
When I downloaded all sources to my local machine and tried to use them in the ffmpeg command it worked fine without errors.
Also, I figured out that it depends on the CPU. When I restricted my CPU the errors appeared earlier. And some commands might produce errors with a restricted CPU but finished successfully with no CPU restriction.
As I understand, for some reason, ffmpeg fails to receive a particular part of a file data, but I believe it should retry to receive lost packages (it's https).
And I don't understand, how it could be related to CPU or sources quantity.
By not understanding the core of evil, I can think about 2 ways (both ugly):
to download all sources and generate the final video from local files;
to chunk sources, generate intermediate outputs for each chunk (and save locally), and concatenate them into the final one.
Any better suggestions or at least where to seek?

ffmpeg timing individual frames of an image sequence

I am having an image sequence input of webp-s concatenated (for various reasons) in a single file. I have a full control over the single file format and can potentially reformat it as a container (IVF etc.) if a proper exists.
I would like ffmpeg to consume this input and time properly each individual frame (consider first displayed for 5 seconds, next 3 seconds, 7, 12 etc.) and output a video (mp4).
My current approach is using image2pipe or webp_pipe followed by a list of loop filters, but I am curious if there are any solid alternatives potentially a simple format/container I could use in order to reduce or completely avoid ffmpeg filter instructions as there might be hundreds or more in total.
ffmpeg -filter_complex "...movie=input.webps:f=webp_pipe,loop=10:1:20,loop=10:1:10..." -y out.mp4
I am aware of concat demuxer but having a separate file for each input image is not an option in my case.
I have tried IVF format which works ok for vp8 frames, but doesnt seem to accept webp. An alternative would be welcomed, but way too many exists for me to study each single one and help would be appreciated.

Keep FFMPEG processing if input fails

I'm trying to save a stream to a video file. If the input stream goes down, FFMPEG automatically stops encoding, but I want to somehow still display those seconds in which the input is down (as a black frame or freezing the last frame).
What I have tried:
ffmpeg -i udp://x.x.x.x:y -c:v copy output.mp4
I wonder if it is possible to keep writing the mp4 file even if the input goes down.
You need to code a special application for this.
It will take the input (will re-encode it if necessary) and will output to ffmpeg.
In the special app, you can check whether is the source is offline or not and act accordingly.
Crucial thing here is PCR values must be continuous, this is why this kind of thing is hard to do or code in general. But it can be done.

is this ffmpeg command optimized?

I have a requirement to take a video, add some plain text, and then add some rotated text at different times, locations, and durations. I want to use processor power in the most efficient way this will run 20,000 times (yes, really, we're personalizing a video for students at a U.)This is what I finally came up with:
ffmpeg -y -i INPUT.mp4 -filter_complex
"drawtext=enable='between(t,14,16)':fontfile=tahoma.ttf:fontsize=54:fontcolor=green:x=10:y=text_h + 10:text='Dana Scully',
drawtext=enable='between(t,19,23)':fontfile=tahoma.ttf:fontsize=16:fontcolor=red:x=150:y=220:text='Dana Scully \<Dana.Scully\#fbi.gov\>',
drawtext=enable='between(t,99,104)':fontfile=tahoma.ttf:fontsize=28:fontcolor=green:x=480:y=text_h + 160:text='Dana Scully',
drawtext=enable='between(t,14,16)':fontfile=tahoma.ttf:fontsize=16:fontcolor=yellow:x=40:y=25:text='Dana Scully \<Dana.Scully\#fbi.gov\>',
drawtext=enable='between(t,180,186)':fontfile=tahoma.ttf:fontsize=88:fontcolor=green:x=20:y=430:text='Dana Scully'[text];
color=c=#111111:s=1280x720:d=1,format=yuv444p[colorbk];
[colorbk]drawtext=fontfile=tahoma.ttf:fontsize=16:fontcolor=purple:x=(w-text_w)/2:y=(h-text_h)/2:text='by',drawtext=fontfile=tahoma.ttf:fontsize=32:fontcolor=green:x=(w-text_w)/2:y=((h-text_h)/2)+50:text='Dana Scully',rotate=(-.5):ow=1280:oh=720:c=#111111,chromakey=#111111:similarity=0.01,format=yuva444p,colorkey=#111111:0.1[rotated];
[text][rotated]overlay=eval=frame:x='if(gte(t,134),(if(lte(t,137),20,NAN)), NAN)':y=100[out];[out]scale=iw*.25:-1"
-crf 20 test.mp4
Is that about as optimized as it is going to get? I thought ffmpeg would already handle the threads based on the computer's processor, so no real need to mess with it. The processing will all be done on AWS VMs.
Rotating the text is what really slows it down.
Any ideas?

Resources