I was wondering if it is at all possible to change the metadata of video segments in ffmpeg as the segments are being created. I know that by using the "-metadata" tag, you can change the metadata of the -i input video, but if that -i input video is being split into different segments by the "-f segment" option, then how do you change the metadata of the resulting segments while the -i input video is being segmented? I know that it's possible to change the metadata after the segmenting has completed, but this isn't that useful since I'm looking to stream the segments live as the input video is being segmented. To give a little better description:
ffmpeg -f video4linux2 -s wvga -t ${CAPTURE_DURATION} -i "/dev/video0" -r 30 \
-vcodec ${VID_CODEC} -s:v 640x480 -b:v 80k -keyint_min 30 -g 30 \
-sc_threshold 0 -map 0 -flags -global_header -qcomp 0.8 \
-qmin 10 -qmax 51 -qdiff 4 -f segment -segment_time ${SEG_TIME} \
-segment_format ${SEG_FORMAT} -metadata START=0 -y "${LOCATE}${OUTPUT}%01d.${EXTENSION}"
Essentially what I'm doing is taking a video from the standard video input and segmenting it. Once the video segments are created, I can test videos by throwing them all into a VLC playlist, and when the segment format is "mp4", there is a notable delay between each video segment where VLC won't start the video segment until it has played back the time again where the segment was in the original video. So for example, if I have a 30 second video, and split it into 5 second segments, VLC will play the 1st segment immediately, but it will wait 5 seconds before playing the 2nd segment after the 1st segment has finished playing. It does this because the 2nd segment has a start time metadata of 5 seconds, so VLC thinks that it has to wait 5 seconds before playing the 2nd segment. What I'm wondering is if there's a way to tell ffmpeg to set the segment start time metadata to 0 seconds as the segments are being created. Any help would be greatly appreciated.
According to the source code, there is a flag that should do what you want:
{ "reset_timestamps", "reset timestamps at the begin of each segment",
OFFSET(reset_timestamps), AV_OPT_TYPE_INT, {.i64 = 0}, 0, 1, E }
instead of -metadata START=0 use -reset_timestamps 1 and all your segments will start playing immediately.
Related
I wanted to run ffmpeg to connect to an RTSP stream and create multiple mkv files every 10 seconds based on the device time (device time where ffmpeg is running), and not the runtime of ffmpeg.
So if ffmpeg was run on midnight, file splits would be on 00:00:00, 00:00:10, 00:00:20, 00:00:30, 00:00:40, 00:00:50, 00:01:00, 00:01:10, etc.
An example file output would be:
stream_2022MAR07_00.00.00.mkv
stream_2022MAR07_00.00.10.mkv
stream_2022MAR07_00.00.20.mkv
etc.
And if the run hasn't started on the 10th second, it should still split on the next 10th second.
Example, the ffmpeg ran on 09:24:43, it should split on 09:24:50 and the succeeding 10th second of the device time. Expected file output would be:
stream_2022MAR07_09.24.43.mkv
stream_2022MAR07_09.24.50.mkv
stream_2022MAR07_09.25.00.mkv
etc.
The code that I have seen splits on the 10th second of the runtime, and not based on the device time.
ffmpeg -rtsp_transport tcp -i <rtsp_url> -f segment -strftime 1 \
-segment_time 00:00:10 -segment_atclocktime 1 -segment_clocktime_offset 30 \
-segment_format mp4 -an -vcodec copy -reset_timestamps 1 \
stream_%Y-%m-%d-%H.%M.%S.mp4
And also, I haven't really got the explanation of the flags used. Can someone please help me here as I am new with ffmpeg.
I want to split a video into (mostly) equal parts of 120sec length. The code below works but only the first video output is of normal mp4 format. The others seem like they start at where the previous video ends but only like the video file was never cut
First video timeline image:
next video timeline, as you can see it starts at 2min mark rather than at 0 as a separate video. Even though the file stats still show the video as being 2 minutes in length:
ffmpeg -i 1146redmp4.mp4 -c:v libx264 -crf 22 -map 0 -segment_time 120 -g 120 -sc_threshold 0 -force_key_frames "expr:gte(t,n_forced*120)" -f segment 1146output%03d.mp4
If this is the correct output and not a bug. How do I have the video splits be output as their own video?
Looks like your player doesn't like starting timestamps to be non-zero.
ffmpeg -i 1146redmp4.mp4 -c:v libx264 -crf 22 -map 0 -segment_time 120 -g 120 -sc_threshold 0 -force_key_frames "expr:gte(t,n_forced*120)" -reset_timestamps 1 -f segment 1146output%03d.mp4
I want to use ffmpeg to convert a sequence of images to a video, the images are got in realtime, the interval of getting image is changeable, maybe i get next image in 1 second or even 1 millisecond.
I want the target video in a special fps(like 100), now my implement is creating a loop, which fade ffmpeg last image then sleep(like 10ms).
Do you guys know some options could let ffmpeg fill frames automatically?
If that option do exist, i wonder is that possible to make video real fps is half of it is claimed.
My ffmpeg command likes follow:
ffmpeg -f image2pipe -r 100 -i pipe:0 -f flv -r 100 pipe:1
You can use
ffmpeg -f image2pipe -use_wallclock_as_timestamps 1 -i pipe:0 -f flv -vsync cfr -r 100 pipe:1
FFmpeg will set each incoming frame's timestamp to the time it is received. SInce the output rate is set and mode is constant frame rate, ffmpeg will duplicate the last frame till next input frame is received, or drop if two frames are less than 10ms apart. Change -r to 1000 to keep frames only a millisecond apart.
I'm capturing video from 4 cameras connected with HDMI through a capture card. I'm using ffmpeg to save the video feed from the cameras to multiples jpeg files (30 jpeg per second per camera).
I want to be able to save the images with the capture time. Currently I'm using this command for one camera:
ffmpeg -f video4linux2 -pixel_format yuv420p -timestamps abs -I /dev/video0 -c:a jpeg -t 60 -ts_from_file 2 camera0-%5d.jpeg
It saves my file with the names camera0-00001.jpg, camera0-00002.jpg, etc.
Then I rename my file with camera0-HH-mm-ss-(1-30).jpeg based on the modified time of the file.
So in the end I have 4 files with the same time and same frame like this:
camera0-12-00-00-1.jpeg
camera1-12-00-00-1.jpeg
camera2-12-00-00-1.jpeg
camera3-12-00-00-1.jpeg
My issue is that the file may be offset from one to two frame. They may have the same name but sometime one or two camera may show different frame.
Is there a way to be sure that the capture frames has the actual time of the capture and not the time of the creation of the file?
You can use the mkvtimestamp_v2 muxer
ffmpeg -f video4linux2 -pixel_format yuv420p -timestamps abs -copyts -i /dev/video0 \
-vf setpts=PTS-STARTPTS -vsync 0 -vframes 1800 camera0-%5d.jpeg \
-c copy -vsync 0 -vframes 1800 -f mkvtimestamp_v2 timings.txt
timings.txt will have output like this
# timecode format v2
1521177189530
1521177189630
1521177189700
1521177189770
1521177189820
1521177189870
1521177189920
1521177189970
...
where each reading is the Unix epoch time in milliseconds.
I've switched to output frame count limit to stop the process instead of -t 60. You can use -t 60 for the first output since we are resetting timestamps there, but not for the second. If you do that, remember to only use the first N entries from the text file, where N is the number of images produced.
I've got a video file, video.mp4. It is 18 minutes 23 seconds in duration. I am looking to extract the audio only from this video, and create an MP3 of the highest possible quality from the audio in the video.
Some googlefu lead me to this command: ffmpeg -i video.mp4 audio.mp3
The problem is that, this command doubles the length of the audio that's outputted (duration is 36 minutes 46 seconds). It loops the audio track once, so the output contains the entire 18 minutes 23 seconds of audio, then immediately starts the 18 minutes and 23 seconds of audio over again.
Some more googlefu lead me to this flag: -write_xing 0 from this SO question, but even with that flag it still loops the audio.
EDIT: Additional googlefu and me seeming to think it has something to do with 2 audio channels (and perhaps looping channel 2 immediately after channel 1, rather than merging the two) lead me to this flag: -ac 1 to force it to merge stereo -> mono. This did not work also, and it still outputs a 38 minute 46 seconds MP3 file.
How can I extract (to MP3) the audio from a video file, without doubling the duration?
Your googlefu must be malfunctioning.
If you have a single audio track:
ffmpeg -i movie.mp4 -map 0:a -c:a mp3 audio.mp3
If you have multiple audio tracks:
Identify the track:
ffprobe -i movie.mp4 and look for an audio Stream #0:x where x is an integer
Use the above command using -map 0:x. Example for x = 2:
ffmpeg -i movie.mp4 -map 0:2 -c:a mp3 audio.mp3
How to use the -map option