Difference between revisions of "ffmpeg"
(12 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
[[Category: Engineering]] | [[Category: Engineering]] | ||
− | == | + | == reduce video size and quality == |
− | You can | + | You can reduce the dimensions of the video frame, the video framerate, compression bitrate (quality). |
+ | |||
+ | Use '''ffmpeg -i video_input.mp4''' to determine the current video parameters. To determine bitrate look for a line in the output like '''Duration: 00:28:04.17, start: 0.000000, bitrate: 40705 kb/s'''. To determine framerate look for a line in the output like '''Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709), 2880x1800 [SAR 1:1 DAR 8:5], 40283 kb/s, 59.50 fps, 60 tbr, 6k tbn, 12k tbc (default)'''. | ||
+ | |||
+ | The following would reduce the bitrate by approximately 1/8. | ||
+ | <pre> | ||
+ | ffmpeg -i video_input.mp4 -b 5000k video_output.mp4 | ||
+ | </pre> | ||
+ | The following would reduce the framerate by approximately 1/4. We could use either the '''-r 15''' option or a '''-filter:v fps=fps=15'''. | ||
+ | <pre> | ||
+ | ffmpeg -i video_input.mp4 -filter:v fps=fps=15 video_output.mp4 | ||
+ | ffmpeg -i video_input.mp4 -r 15 video_output.mp4 | ||
+ | </pre> | ||
+ | Combined framerate and bitrate for even more reduction: | ||
+ | <pre> | ||
+ | ffmpeg -i video_input.mp4 -r 15 -b 5000k video_output.mp4 | ||
+ | </pre> | ||
+ | |||
+ | == Extract original JPEG images from MJPEG video == | ||
+ | |||
+ | You can check if your video is in '''MJPEG''' format using '''ffprobe'''. You should get the output '''codec_name=mjpeg'''. | ||
+ | <pre> | ||
+ | ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=nw=1 input.mov | ||
+ | </pre> | ||
+ | |||
+ | You can extract lossless individual JPEG images from an '''MJPEG''' file. Note the two form of syntax that may be required depending on the version of '''ffmpeg''' being used. | ||
+ | <pre> | ||
+ | ffmpeg -i input.mov -codec:v copy -bsf:v mjpeg2jpeg frame-%04d.jpg | ||
+ | </pre> | ||
+ | Alternate syntax: | ||
+ | <pre> | ||
+ | ffmpeg -i input.mov -vcodec copy frame-%04d.jpg | ||
+ | </pre> | ||
+ | |||
+ | == Extract the best quality of still images from a video == | ||
+ | |||
+ | '''Note''', if your video is in '''MJPEG''' format then see [[#MJPEG]] for even better best quality still image extraction. | ||
+ | |||
+ | See the options '''-qscale:v''' or the alias '''-q:v''' for '''ffmpeg'''. | ||
+ | <pre> | ||
+ | ffmpeg -i input.mp4 -qscale:v 1 frame-%04d.jpg | ||
+ | # or the alias: | ||
+ | ffmpeg -i input.mp4 -q:v 1 frame-%04d.jpg | ||
+ | </pre> | ||
+ | |||
+ | Note that some people say to use '''1''' for the quality value, but others say to use '''2'''. I found that '''1''' seemed to work. | ||
<pre> | <pre> | ||
− | ffmpeg -i | + | ffmpeg -i input.mp4 -qscale:v 1 frame-%04d.jpg |
</pre> | </pre> | ||
== Create video from a sequence of images == | == Create video from a sequence of images == | ||
− | + | This assumes the images have sequential naming. | |
+ | <pre> | ||
+ | ffmpeg -pattern_type glob -i "image-*.jpg" video_output.mov | ||
+ | </pre> | ||
+ | |||
+ | This sets the framerate and format options. | ||
+ | <pre> | ||
+ | ffmpeg -framerate 10 -pattern_type glob -i "*.jpg" -c:v libx264 -pix_fmt yuv420p -crf 23 video_output.mp4 | ||
+ | </pre> | ||
+ | |||
+ | == text file to scrolling video credits == | ||
+ | |||
+ | This will create a blank, black video with white text from a plain text file that scrolls up like the credits in a film. | ||
+ | |||
+ | Note that I have not figured out how to wrap text, so the text file must be formatted with line breaks at 70 columns. | ||
+ | |||
+ | You must also play around with the output timing to fit the text. For a 260 line text file I found that I needed about 5 minutes (300 seconds), '''-t 300'''. I have not figured out a way to make the video length fit the amount of time needed to scroll any given text file. | ||
+ | |||
+ | The '''y=h-30*t''' parameter sets the scroll speed. Between 20 and 40 is usually comfortable. 20 is fast. 40 is slow. You will need to adjust the length of the video if you modify the scroll speed. | ||
+ | |||
+ | <pre> | ||
+ | ffmpeg -f lavfi -i "color=color=black:s=1280x720, drawtext=fontsize=32:fontfile=FreeSerif.ttf:fontcolor=white:x=40:y=40:textfile=text.txt:y=h-30*t" -t 300 20200324-transcript.mp4 | ||
+ | </pre> | ||
+ | |||
+ | == video with timecode == | ||
+ | |||
+ | Playback with H:M:S time format starting at 0. | ||
+ | <pre> | ||
+ | ffplay -i video_input.mp4 -vf "drawtext='x=10:y=10:fontcolor=white:fontsize=32:text=%{pts\:gmtime\:0\:%T}'" | ||
+ | </pre> | ||
+ | |||
+ | Re-encode video with hard embedded time code showing seconds with decimals starting at 0. Notice that '''-vf''' becomes '''-filter_complex''' and '''[0:v] ''' (with a space) is prefixed to the expression. | ||
+ | <pre> | ||
+ | ffmpeg -i video_input.mp4 -filter_complex "[0:v] drawtext='x=20:y=40:fontcolor=white:fontsize=32:text=%{pts}'" video_output.mp4 | ||
+ | </pre> | ||
+ | |||
+ | Blank video with black screen (320x240 10 FPS), keep audio, embed time code. Notice that the '''-filter_complex''' uses '''[1:v]''', which is created by the '''lavfi''' filter that precedes it. | ||
+ | <pre> | ||
+ | ffmpeg -i video_input.mp4 -f lavfi -i color=c=black:s=320x240:r=10 -map 1 -map 0:a -shortest -filter_complex "[1:v] drawtext='x=20:y=40:fontcolor=white:fontsize=32:text=%{pts}'" video_output.mp4 | ||
+ | </pre> | ||
+ | |||
+ | Blank video with audio and multiple lines of text including multiple formats of timecode output. | ||
<pre> | <pre> | ||
− | ffmpeg - | + | ffmpeg -i video_input.mp4 -f lavfi -i color=c=black:s=320x240:r=10 -map 1 -map 0:a -shortest -filter_complex "[1:v] drawtext='x=10:y=40:fontcolor=white:fontsize=32:text=%{pts\:hms}', drawtext='x=134:y=80:fontcolor=white:fontsize=18:text=%{pts}', drawtext='x=22:y=110:fontcolor=white:fontsize=24:text=AUDIO 2020-03-25'" video_output.mp4 |
</pre> | </pre> | ||
+ | == Create slideshow video that is most compatible across many devices -- it will play back under QuickTime == | ||
+ | |||
+ | This will create a video that displays a slideshow of all the '''JPEG''' images in the current directory. | ||
+ | The specified framerate will show each slide for 4 seconds. | ||
<pre> | <pre> | ||
− | ffmpeg -framerate | + | ffmpeg -framerate 0.25 -pattern_type glob -i "*.jpg" video_output.mp4 |
</pre> | </pre> |
Latest revision as of 15:31, 27 December 2020
Contents
- 1 reduce video size and quality
- 2 Extract original JPEG images from MJPEG video
- 3 Extract the best quality of still images from a video
- 4 Create video from a sequence of images
- 5 text file to scrolling video credits
- 6 video with timecode
- 7 Create slideshow video that is most compatible across many devices -- it will play back under QuickTime
reduce video size and quality
You can reduce the dimensions of the video frame, the video framerate, compression bitrate (quality).
Use ffmpeg -i video_input.mp4 to determine the current video parameters. To determine bitrate look for a line in the output like Duration: 00:28:04.17, start: 0.000000, bitrate: 40705 kb/s. To determine framerate look for a line in the output like Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709), 2880x1800 [SAR 1:1 DAR 8:5], 40283 kb/s, 59.50 fps, 60 tbr, 6k tbn, 12k tbc (default).
The following would reduce the bitrate by approximately 1/8.
ffmpeg -i video_input.mp4 -b 5000k video_output.mp4
The following would reduce the framerate by approximately 1/4. We could use either the -r 15 option or a -filter:v fps=fps=15.
ffmpeg -i video_input.mp4 -filter:v fps=fps=15 video_output.mp4 ffmpeg -i video_input.mp4 -r 15 video_output.mp4
Combined framerate and bitrate for even more reduction:
ffmpeg -i video_input.mp4 -r 15 -b 5000k video_output.mp4
Extract original JPEG images from MJPEG video
You can check if your video is in MJPEG format using ffprobe. You should get the output codec_name=mjpeg.
ffprobe -v error -select_streams v:0 -show_entries stream=codec_name -of default=nw=1 input.mov
You can extract lossless individual JPEG images from an MJPEG file. Note the two form of syntax that may be required depending on the version of ffmpeg being used.
ffmpeg -i input.mov -codec:v copy -bsf:v mjpeg2jpeg frame-%04d.jpg
Alternate syntax:
ffmpeg -i input.mov -vcodec copy frame-%04d.jpg
Extract the best quality of still images from a video
Note, if your video is in MJPEG format then see #MJPEG for even better best quality still image extraction.
See the options -qscale:v or the alias -q:v for ffmpeg.
ffmpeg -i input.mp4 -qscale:v 1 frame-%04d.jpg # or the alias: ffmpeg -i input.mp4 -q:v 1 frame-%04d.jpg
Note that some people say to use 1 for the quality value, but others say to use 2. I found that 1 seemed to work.
ffmpeg -i input.mp4 -qscale:v 1 frame-%04d.jpg
Create video from a sequence of images
This assumes the images have sequential naming.
ffmpeg -pattern_type glob -i "image-*.jpg" video_output.mov
This sets the framerate and format options.
ffmpeg -framerate 10 -pattern_type glob -i "*.jpg" -c:v libx264 -pix_fmt yuv420p -crf 23 video_output.mp4
text file to scrolling video credits
This will create a blank, black video with white text from a plain text file that scrolls up like the credits in a film.
Note that I have not figured out how to wrap text, so the text file must be formatted with line breaks at 70 columns.
You must also play around with the output timing to fit the text. For a 260 line text file I found that I needed about 5 minutes (300 seconds), -t 300. I have not figured out a way to make the video length fit the amount of time needed to scroll any given text file.
The y=h-30*t parameter sets the scroll speed. Between 20 and 40 is usually comfortable. 20 is fast. 40 is slow. You will need to adjust the length of the video if you modify the scroll speed.
ffmpeg -f lavfi -i "color=color=black:s=1280x720, drawtext=fontsize=32:fontfile=FreeSerif.ttf:fontcolor=white:x=40:y=40:textfile=text.txt:y=h-30*t" -t 300 20200324-transcript.mp4
video with timecode
Playback with H:M:S time format starting at 0.
ffplay -i video_input.mp4 -vf "drawtext='x=10:y=10:fontcolor=white:fontsize=32:text=%{pts\:gmtime\:0\:%T}'"
Re-encode video with hard embedded time code showing seconds with decimals starting at 0. Notice that -vf becomes -filter_complex and [0:v] (with a space) is prefixed to the expression.
ffmpeg -i video_input.mp4 -filter_complex "[0:v] drawtext='x=20:y=40:fontcolor=white:fontsize=32:text=%{pts}'" video_output.mp4
Blank video with black screen (320x240 10 FPS), keep audio, embed time code. Notice that the -filter_complex uses [1:v], which is created by the lavfi filter that precedes it.
ffmpeg -i video_input.mp4 -f lavfi -i color=c=black:s=320x240:r=10 -map 1 -map 0:a -shortest -filter_complex "[1:v] drawtext='x=20:y=40:fontcolor=white:fontsize=32:text=%{pts}'" video_output.mp4
Blank video with audio and multiple lines of text including multiple formats of timecode output.
ffmpeg -i video_input.mp4 -f lavfi -i color=c=black:s=320x240:r=10 -map 1 -map 0:a -shortest -filter_complex "[1:v] drawtext='x=10:y=40:fontcolor=white:fontsize=32:text=%{pts\:hms}', drawtext='x=134:y=80:fontcolor=white:fontsize=18:text=%{pts}', drawtext='x=22:y=110:fontcolor=white:fontsize=24:text=AUDIO 2020-03-25'" video_output.mp4
Create slideshow video that is most compatible across many devices -- it will play back under QuickTime
This will create a video that displays a slideshow of all the JPEG images in the current directory. The specified framerate will show each slide for 4 seconds.
ffmpeg -framerate 0.25 -pattern_type glob -i "*.jpg" video_output.mp4