Remove all non key frames from video without re-encoding - ffmpeg

I have a HEVC mkv video from which I need to remove all but key frames without re-encoding whole thing.
I found out that I can extra key frames using this
ffmpeg -i full.mkv -c:v copy -vf "select=eq(pict_type\,PICT_TYPE_I)" key.mkv
but I get:
Filtergraph 'select=eq(pict_type\,PICT_TYPE_I)' was defined for video output stream 0:0 but codec copy was selected.
Filtering and streamcopy cannot be used together.
What do I do?

You'll have to use the bitstream filter filter_units for this:
ffmpeg -i test.mkv -c copy -map v -bsf:v "filter_units=pass_types=16-23|32-34" key.mkv
This will only pass through random access pictures from the HEVC stream. This should cover most of them but HEVC has more keyframes types than H.264 so I'll update the types above if there are some I've missed.

Related

How to combine a video with audio from another video using FFMPEG?

I have two videos of the same length that I'd like to combine. Video A has audio, video B does not. I'd like to take the audio from video A and put it onto Video B. I'd like to do this with FFMPEG, but I can't figure out the arguments I need? Should I use map?
There's a lot of questions about combining a video with audio, but not two videos.
Do I maybe need an intermediate step of converting my original video to audio?
I have tried using this FFMPEG command, and a couple of variations. All of the resulted in just Video A (the one with audio) being the output.
ffmpeg -i videoB.mp4 -i video A.mp4 -c:v copy -c:a aac output.mp4
Try this as a starter
ffmpeg -i videoB.mp4 -i video A.mp4
-filter_complex [0:v][1:a][1:v][1:a]concat=n=2:v=1:a=1[vout][aout]
-map [vout] -map [aout] -c:v h264 -c:a aac output.mp4
You must reencode though.

FFMPEG overlay video over image using movie filter resulting video with no sound

I want to overlay srinked video on the top of single image.
I use movie filter to do that. like this
ffmpeg.exe -loop 1 -i Coronavirus00000000.jpg -vf "movie=C\\:/\Users/\Toshiba/\Pictures/\test vcp/\shopi pro.mp4,scale=1180:-1[inner];[in][inner]overlay=70:70:shortest=1[out]" -y out.mp4
It's work. but the problem, the audio from video is removed. The final video out.mp4 has no sound, even though the original video has.
I have read answer on this threat FFMPEG overlaying video with image removes audio
That recommend to Change into ...[padded]overlay=0:0" -y ... Or add -map 0:a
But I don't understand how to implement that answer into movie filter
Please notice inputs/sources you have:
an input image ("Coronavirus00000000.jpg")
a movie source which by default selects a video stream
so you don't have any audio input stream selected/opened. To do so I'd recommend open every file as a standard ffmpeg input (-i <file>) and then configure a complex filtering graph that utilizes them.
In your example that would be:
ffmpeg -loop 1 -i Coronavirus00000000.jpg -i C\\:/\Users/\Toshiba/\Pictures/\test vcp/\shopi pro.mp4 -filter_complex "[1:v]scale=1180:-1[inner];[0:v][inner]overlay=70:70:shortest=1[out]" -map '[out]' -map 1:a -y out.mp4
where:
-i Coronavirus00000000.jpg opens your image file as input #0
-i C\\:/\Users/\Toshiba/\Pictures/\test vcp/\shopi pro.mp4 opens your video file with video and audio streams as input #1
[1:v]scale=1180:-1[inner] scales the input's #1 video stream
[0:v][inner]overlay=70:70:shortest=1[out] overlays the scaled video onto input's #0 video stream
-map '[out]' selects overlayed video stream (tagged as [out]) for output video stream
-map 1:a selects input's #1 audio stream for output audio stream

FFMPEG reduce fps for live h264 stream with direct copy

I found different articles on changing the fps with ffmpeg but none of them is matching for my exact purposes.
There is an ffmpeg command like below:
ffmpeg -i RTSPCAMERAPRODUCEH264 -c:v copy -an -movflags +frag_keyframe+empty_moov -f mp4
This will remux my camerastream to fragmented mp4 perfectly.
Is there a way to force ffmpeg to lower the FPS to save bandwidth?
I.e. camera streams 30fps, it needs 1Mbps for fmp4 (sample numbers!):
I'd like to know if it's possible to lower the FPS and get an output stream for which 500kbps (50% of original is enough) without re-encoding.
ffmpeg -r 1 -i RTSPCAMERAPRODUCEH264 -c:v copy -an -movflags +frag_keyframe+empty_moov -f mp4
and
ffmpeg -i RTSPCAMERAPRODUCEH264 -c:v copy -an -movflags +frag_keyframe+empty_moov -r 1 -f mp4
do not seem to work.
A temporally coded video stream (like one with H264 codec) cannot arbitrarily drop intermediate packets, so this is not possible. Only whole or trailing part of GOPs may be dropped.

Extract first frame of multi video streams video

I am curious about how to use FFmpeg in order to extract the first frame of the first video stream from a multi-video stream file.
What I have so far is:
ffmpeg -i {mediaFile} -ss 0 -map 0:v -vframes 1 -f image2 firstFrame.jpeg.
I am not sure about the -map part. How can be certain that I work on the first video stream? Is there a way to first filter streams by codec type, then select the first and then extract the frame?
Thanks.
ffmpeg -i {mediaFile} -map 0:v:0 -frames:v 1 firstFrame.jpeg
Add an input stream index to your -map as shown in the example above. 0:v:0 is input #0:video:stream #0. Note that ffmpeg starts counting from 0. If you wanted video stream #3, it would be 0:v:2.
I removed the superfluous options from your command.
Also see
-map option documentation
How can I extract a good quality JPEG image from a video with ffmpeg?

ffmpeg convert TS video file to raw rgb32 video file

I have a transport steam file containing H.264 video and would like to extract the video stream to a file containing raw uncompressed RGB32 video frames. So the H.264 video would need to be decoded and converted to RGB32 frames that would be dumped into a file.
Is there a ffmpeg command that would do this, or any other method?
Using FFmpeg command line,
ffmpeg -i in.ts -pix_fmt rgba -c:v rawvideo -map 0:v -f rawvideo in-rgba.raw

Resources