What does `-map data-re` option in FFMPEG do? - ffmpeg

I am trying to extract and parse KLV data from a video stream. I found the following example in a Github repository. I am wondering what does the mapping option data-re do?
$ ffmpeg -i Day\ Flight.mpg -map data-re -codec copy -f data -
I understand the rest of the command, and know that -map is used to choose streams from inputs. But what does data-re mean. I couldn't find any explanation for it (or similar mapping option or stream identifier) in the documentation, e.g. here and here.

It's a typo and incorrect. The only time you use arbitrary label names is when using -filter_complex.
Use:
$ ffmpeg -i Day\ Flight.mpg -map 0:d -c copy -f data -
I could understand a user trying data, but data-re? Might be a double typo for -map data -re, where -re is intended to be the "Read input at native frame rate" input option (-map data is still invalid in this case).

It's not a valid value currently. It could possibly have been a value historically, but I doubt it. Most likely, it "worked" because the map arg parser would ignore additional letters if a lazy evaluation matched a stream and the d in data-re would match data streams. The parser is no longer that clumsy.

Related

Can I trigger a command after ffmpeg writes a segment?

I am reading from an RTSP (camera) stream and writing segments, using ffmpeg. My command to do so is:
ffmpeg -rtsp_transport tcp -i rtsp://$camera_creds#$camera_ip/video/1 -map 0 -c:v h264 -preset:v ultrafast -reset_timestamps 1 -f segment -segment_time 300 -strftime 1
-segment_list ${monitor_dir}/segments$camera.txt $monitor_dir/cam${camera}_out%Y%m%d_%H%M%S.mp4
It works fine to a point. My problem is that I want to do something with each segment once it has been written.
To accomplish this, I monitor the segmentsN.txt file for lines being added to it; I then read the contents, do stuff (process, upload), and then remove the lines that I've already processed (so that I don't reprocess them).
The problem with this is that periodically, ffmpeg will start writing to a new segment, but apparently won't update the segments list file. Initially I thought this was because my "remove the lines" operation was writing a brand new file and replacing it in place (which it was), while ffmpeg was probably continuing to append to the inode it started out with (which it maybe was). Having fixed that, I think I now just have a race condition.
What I'd really like is to have ffmpeg change the filename once it has completed a segment, and/or move the completed segment file into a different folder. However, this doesn't seem like an option. Is there a more robust way to accomplish what I'm doing here? I could just poll for multiple files with a given filename pattern, and process the earliest, circumventing the segments list file...but something more robust would be nice.
Thanks
At loglevel 40 / verbose or higher, you can grep ffmpeg's log for the word ended and see lines like these:
[segment # 000002d338781120] segment:'Mymon/Cam1_out20221228_093412.mp4' count:23 ended
Get the log by reading stderr or by adding -report to generate a logfile.

Segment video with FFMPEG using custom filenames for output

I'm trying to segment a video and name the cropped files in a specific way. Right now I'm using
ffmpeg -i input.mp3 -f segment -segment_time 59 output_%03d.wav
and looping over created files, parsing their filenames and renaming them accordingly.
I have an array which contains
array=[1650027545, 1650027300, 1650026502, ...]
and want the output files to be in;
output_1650027545.wav
output_1650027300.wav
output_1650026502.wav
format. Since there's no loop, I can't figure out how to implement such a naming scheme. Any help is appreciated!

Remove a section from the middle of a video without concat

How do I cut a section out of a video with ffmpeg?
Imagine I have a 60 second mp4 A.
I want to remove all the stuff from 0:15 to 0:45.
The result should be a 30-second mp4, which is composed of the first 15 seconds of A directly followed by the last 15 seconds of A.
How can I do this without using concat?
I know how I could do it by creating two intermediary files and then using ffmpeg to concat them. I don't want to have to perform so much manual work for this (simple?) operation.
I have also seen the trim filder used for removing multiple parts from a video. All the usages I've found show that it seems to be very verbose, and I haven't found an example for a case as simple as I would like (just a single section removed).
Do I have to use trim for this operation? Or are there other less verbose solutions?
The ideal would of course be something at least simple as -ss 0:15 -to 0:45 which removes the ends of a video (-cut 0:15-0:45 for example).
I started from
https://stackoverflow.com/a/54192662/3499840 (currently the only answer to "FFmpeg remove 2 sec from middle of video and concat the parts. Single line solution").
Working from that example, the following works for me:
# In order to keep <start-15s> and <45s-end>, you need to
# keep all the frames which are "not between 15s and 45s":
ffmpeg -i input.mp4 \
-vf "select='not(between(t,15,45))', setpts=N/FRAME_RATE/TB" \
-af "aselect='not(between(t,15,45))', asetpts=N/SR/TB" \
output.mp4
This is a one-line linux command, but I've used the bash line-continuation character ('\') so that I can vertically align the equals-signs as this helps me to understand what is going on.
I had never seen ffmpeg's not and between operators before, but I found their documentation here.
Regarding the usual ffmpeg "copy vs re-encode" dichotomy, I was hoping to be able to use ffmpeg's "copy" "codec" (yeah, I know that it's not really a codec) so that ffmpeg would not re-encode my video, but if I specify "copy", then ffmpeg starts and stops at the nearest keyframes which are not sufficiently close to my desired start and stop points. (I want to remove a piece of video that is approximately 20 seconds long, but my source video only has one keyframe every 45 seconds!). Hence I am obliged to re-encode. See https://trac.ffmpeg.org/wiki/Seeking#Seekingwhiledoingacodeccopy for more info.
The setpts/asetpts filters set the timestamps on each frame to the correct values so that your media player will play each frame at the correct time.
HTH.
If you want to use the copy "codec", consider the following approach:
ffmpeg -i input.mp4 -t "$start_cut_section" -c copy part1.mp4&
ffmpeg -i input.mp4 -ss "$end_cut_section" -c copy part2.mp4&
echo "file 'part1.mp4'" > filelist;
echo "file 'part2.mp4'" >> filelist;
wait;
ffmpeg -f concat -i filelist -c copy output.mp4;
rm filelist;
This creates two files from before and after the cut, then combines them into a new trimmed final video. Obviously, this can be used to create as many cuts as you like. It may seem like a longer approach than the accepted answer, but it likely will execute much faster because of the use of the copy codec.

What is the correct command line format for ffmpeg in this case

I apologise if this is a duplicate. I have used ffmpeg in the past to convert .pngs to .mp4 but now I am using it on my own files and I am not sure of the format it should have.
I have some files with the following naming convention:
./profiles_0.png
./profiles_40.png
...
./profiles_400.png
The number of files I have varies, i.e. it isn't always 400 and the interval isn't always going to be 40. I have tried the following:
ffmpeg -framerate 1 -i profiles_%d0.png -r 6 -pix_fmt yuv420p out.mp4
but that only captures one of the images. Is there a flexible format in the 'profiles_%d0.png" argument that captures all of the files in that directory regardless of the number of characters following the underscore or does it require that I change my naming convention?
Cheers for any help,
A
If you only have the images of interest in your folder it's easy. You can use a command similar to yours, examples are given in this other question. Basically you can match the files with a wildcard operator and their extension, *.png in that case.
It could look like this:
ffmpeg -f image2 -pattern_type glob -i '*.png' out.avi
This is only selectable if libavformat was compiled with globbing
support.
According to FFmpeg's documentation on the image2 demuxer.
If you have other files with other numbering or if you have a sequence of files and want to select a subsequence, I see no way to do it automatically but you can specify such sequence. You'll still need to use glob, you can get help on the use of globs in FFmpeg there and more information on glob programming here.

ffmpeg - Converting series of images to video (Ubuntu)

I got pictures named as
pic_0_new.jpg
pic_10_new.jpg
pic_20_new.jpg
...
pic_1050_new.jpg
which I want to turn into a video (Ubuntu ffmpeg). I tried the following
ffmpeg -start_number 0 -i pic_%d_new.jpg -vcodec mpeg4 test.avi
but I don't know how to set the step size and the end number. How to do this?
Thanks for help :)
If your files are named with leading zeroes then you can use the built-in globbing functionality. If not (like your's), you can create a file list and supply that as the input, just like explained here.
The other thing you need to set is the input framerate that tells FFmpeg what framerate should assume for the images (note that the option is ahead of the -i input option).
So the command should look like this:
ffmpeg -framerate 25 -i pic_%04d_new.jpg <encoding_settings> test.avi
Also note that you can use the filename expansion on files with or without leading zeroes (Thanks for #Gyan to pointing it out):
match regularly numbered files: %d (this is what you're using)
img_%d.png // This will match files with any number as a postfix starting from img_0.png
match leading zeroes: %0<number_of_digits>d
img_%03d.png // This will match files ranging from img_000.png to img_999.png
In addition, mpeg4/avi is not the most convenient encoder/container to use...

Resources