Skip to content
Search

FFmpeg:CLI

lastmod 2026-06-01created 2015-08-27146 edits

ffmpeg is a very fast video and audio converter that can also grab from a live audio/video source. It can also convert between arbitrary sample rates and resize video on the fly with a high quality polyphase filter.

Synopsis

ffmpeg [global_options] {[input_file_options] -i input_file} ... {[output_file_options] output_file} ...

Categories

Example

  • Organized on the FFmpeg page. <- Pulled out as a link to avoid duplicate notes

python

Docker Images

Commandline arguments

  • -acodec {codec}: (input/output) Set the audio codec. This is an alias for -codec:a.
  • -vf {filtergraph}: (output) Creates a filtergraph. This is an alias for -filter:v
    • -vf scale=320:-1: Converts the width to 320 and the height proportionally. That is, keeps the aspect ratio (Aspect Ratio) based on the "width".
    • -vf scale=-1:240: Converts the height to 240 and the width proportionally. That is, keeps the aspect ratio (Aspect Ratio) based on the "height".
    • -vf scale=iw*2:ih: Doubles the width of the input source.
    • -vf "scale=iw/2:ih/2": Halves the width and height of the input source.
    • -vf "scale='min(320,iw)':'min(240,ih)'": In the command line above, the minimum width/height for scaling are set to 320 and 240 pixels respectively. That is, it prevents video upscaling based on the size of the input video. This is a very simple way to prevent poor-quality scaling.
  • -ss {position}: (input/output) Start time. Can be specified as HH:MM:SS. When applied to the input, it must come before the -i option.
  • -t {duration}: (input/output) Duration time. Can be specified in seconds. When applied to the input, it must come before the -i option.
  • -to {position}: (output) Time value at which to end the cut. Can be specified as HH:MM:SS[.xxx].
  • -y: Overwrite the output file without confirmation, even if a file with the same name exists.
  • -i {입력파일이름}: Specifies the name of the source video file to convert.
  • -ab {num}: Specifies the audio bitrate.
  • -ar {num}: Specifies the audio sampling rate.
  • -fs {num}: File size limit
  • -f {format}: format (Force format)
  • -formats: Check supported formats
  • -ac {num}: Specifies the audio channels. 1 is mono, 2 is stereo
  • -b:a {num}: Specifies the audio bitrate.
  • -vcodec {codec}: Specifies the video codec.
  • -level {num}: Baseline value. (30 means Baseline 3.0)
  • -b:v {num} Specifies the video bitrate.
  • -r {num}: Specifies the output video frame rate.
  • -s {num}: Specifies the screen size, i.e. resolution. If set larger than the source resolution, the output is upscaled. There are predefined names, like presets, so you don't have to specify the resolution directly.
    • Ex) vga (640x480), sxga (1280x1024), wvga (852x480), hd720 (1280x720)
  • -threads {num}: Specifies the number of threads. You can specify multiple threads to improve speed. It doesn't have to match the number of CPU cores, but it is usually set to the core count.
  • -strict experimental: Option that relaxes the strictness of options
  • -c:v copy: codec, video, copy = copies the source video.
  • -c:a copy: codec, audio, copy = copies the source audio.
  • -vn: Remove output video
  • -an: Remove output audio
  • -sameq: Same quality setting as the source - Removed option
    • -qscale 0: Same quality setting as the source
  • -vframes: Number of video frames to record
  • -re - Read input at native frame rate. Mainly used to simulate a grab device.
    • In other words, if you want to stream a video file, you'll want to use this. Otherwise you may stream too fast (by default it tries to stream at line speed).
    • Typically this flag is not used when streaming from a live device; it is used when simulating live streaming with a stored file.
    • StreamingGuide – FFmpeg
  • -itsoffset -0.5 -i INPUT: Shifts the INPUT file timestamps 0.5 seconds earlier, then recognizes it as '1' (needed when using map)
  • -f concat: File concatenation
  • -safe 0: Option that disables ffmpeg's file path safety check
    • By default, when using the concat protocol, ffmpeg performs a safety check that disallows relative and absolute paths. This is to prevent potential security issues that file paths can cause.
    • However, if you need to specify file paths explicitly in a script, you can disable this safety check with the -safe 0 option. This is useful when specifying files using the current directory or other absolute paths.
  • -fflags +genpts: Generates new frame timestamps to fix playback time issues.

Hardware acceleration

NVidia

Example:

ffmpeg -y -hide_banner -analyzeduration 30M -probesize 100M -fflags +discardcorrupt  -i "in.ts" -vf "yadif=0:-1:0,scale=1280:720" -map 0:v:0 -c:v h264_nvenc -preset:v fast -rc constqp -qp 29.5 -profile:v high -movflags +faststart -map 0:a:0 -c:a:0 aac -b:a:0 160k -metadata:s:a:0 title="Audio#1" "out.mp4"

Quiet mode (silent/quieter/less verbose)

ffmpeg -hide_banner -loglevel error ...

DRM

See that page for how to encrypt using MPEG Common Encryption (CENC).

Streaming

RTMP stream Input to FLV file, reencode

$ ffmpeg -i rtmp://IP:PORT/live/STREAMNAME -c:a aac -strict -2 -c:v h264 OUTPUT.flv

MP4 file Input to RTMP stream, reencode

$ ffmpeg -re -i INPUT.mp4 -c:a aac -strict -2 -c:v h264 -f flv rtmp://IP:PORT/live/STREAMNAME

HLS stream input to RTMP stream, reencode

$ ffmpeg -i http://IP:PORT/hls/STREAMNAME/index.m3u8 -c:a aac -strict -2 -c:v h264 -f flv rtmp://IP:PORT/live/STREAMNAME

MP4 file input to RTSP stream, reencode

$ ffmpeg -re -i INPUT.mp4 -c:a aac -strict -2 -c:v h264 -f rtsp -rtsp_transport tcp rtsp://IP:PORT/STREAMNAME

HLS stream input to RTSP stream, reencode

$ ffmpeg -i http://IP:PORT/hls/STREAMNAME/index.m3u8 -c:a aac -strict -2 -c:v h264 -f rtsp -rtsp_transport tcp rtsp://IP:PORT/STREAMNAME

RTSP stream input over TCP to RTMP stream, copy

  • Using ffmpeg to ingest over TCP instead of UDP makes sure you don't have the packet loss problem that UDP has and gives a better and more stable picture for your stream.
$ ... -rtsp_transport tcp -i CameraURL -c copy -f flv rtmp://IP:PORT/live/STREAMNAME

Convert RTSP to HLS using FFmpeg

ffmpeg -fflags nobuffer \
 -rtsp_transport tcp \
 -i rtsp://your-rtsp-server:8554/CH001.sdp \
 -vsync 0 \
 -copyts \
 -vcodec copy \
 -movflags frag_keyframe+empty_moov \
 -an \
 -hls_flags delete_segments+append_list \
 -f segment \
 -segment_list_flags live \
 -segment_time 1 \
 -segment_list_size 3 \
 -segment_format mpegts \
 -segment_list /tmp/stream/index.m3u8 \
 -segment_list_type m3u8 \
 -segment_list_entry_prefix /stream/ \
 /tmp/stream/%d.ts

After running this command you will find the index.m3u8 file along with multiple .ts (segment files) in the output directory that you specify in the command.

In this the index.m3u8 is the playlis file and .ts files are the fragments. You need to serve these files using any http server. I used goof for this.

To display this video in a browoser, you need to include this index.m3u8 file in the video tag in your html page, for example.

<video id="video-player" controls preload="none">
    <source src="/output-directory/index.m3u8" type="application/x-mpegURL">
</video>

Once this is done, navigate to the html page from your browser, you will be able to see the live stream on linux without using any flash plugin.

Example

Example of cutting 30 seconds of video starting at 1 min 10 s
ffmpeg -y -i input.avi -ss 00:01:10 -t 30 -vcodec libx264 -b 3695k -r 29 -acodec ac3 -ar 48000 -ab 192k output.avi
Cuts the input video from start time 00:01:00 to end time 00:02:00.
ffmpeg -i video.mp4 -ss 00:01:00 -to 00:02:00 -c copy cut.mp4
Speed up video playback 4x (requires re-encoding, so -c copy can't be used)
ffmpeg -i TheGoodTheBadAndTheUgly.mp4 -vf "setpts=0.25*PTS" UpTheGoodTheBadAndTheUgly.mp4
Slow down video playback 2x (requires re-encoding, so -c copy can't be used)
ffmpeg -i TheGoodTheBadAndTheUgly.mp4 -vf "setpts=2*PTS" UpTheGoodTheBadAndTheUgly.mp4
Get video file info
ffmpeg -i video.avi
Make a video from images. Converts image files named like image1.jpg image2.jpg ... in the current directory into a video.mpg file
ffmpeg -f image2 -i image%d.jpg video.mpg
Convert a video file into multiple images (can convert to the following image formats: PGM, PPM, PAM, PGMYUV, JPEG, GIF, PNG, TIFF, SGI)
ffmpeg -i video.mpg image%d.jpg
Encode to a format for iPod, iPhone
ffmpeg -i source_video.avi input -acodec aac -ab 128kb -vcodec mpeg4 -b 1200kb -mbd 2 -flags +4mv+trell -aic 2 -cmp 2 -subcmp 2 -s 320x180 -title X final_video.mp4
Encode to a format for PSP
ffmpeg -i source_video.avi -b 300 -s 320x240 -vcodec xvid -ab 32 -ar 24000 -acodec aac final_video.mp4
Extract audio from a video and save it as mp3
ffmpeg -i source_video.avi -vn -ar 44100 -ac 2 -ab 192 -f mp3 sound.mp3
Convert a WAV file to an mp3 file
ffmpeg -i son_origine.avi -vn -ar 44100 -ac 2 -ab 192 -f mp3 son_final.mp3
Convert an AVI video to an .mpg video
ffmpeg -i video_origine.avi video_finale.mpg
Convert MPG to .avi
ffmpeg -i video_origine.mpg video_finale.avi
Convert AVI to animated gif (uncompressed)
ffmpeg -i video_origine.avi gif_anime.gif
Combine a sound file and a video file
ffmpeg -i son.wav -i video_origine.avi video_finale.mpg
How to make a Fade in and fade out on video + audio with ffmpeg
ffmpeg -i test.mp4 -vf "fade=in:0:50" -y test2.mp4
Command for converting an AVI file to FLV, the Flash file format
ffmpeg -i filename.avi -ar 22050 -ab 32 -f flv -s 320x240 filename.flv
Extract a screenshot image at a desired moment from the converted FLV file
ffmpeg -i filename.flv -f image2 -t 0.001 -ss 3 filename.jpg
Merge multiple videos into one
ffmpeg -i test1.avi -i test2.avi -vcodec copy -acodec copy -vcodec copy -acodec copy test12.avi -newvideo -newaudio
Combine one IMAGE with music
ffmpeg -f image2 -loop 1 -i test.jpg -y -i knstyle.mp3 -vcodec mpeg4 -t 10 output.mp4

Converting to GIF with good resolution

To capture the screen as video and then convert that AVI file to GIF:

$ ffmpeg -i df.avi -vf crop=640:300:79:49 tmp2/test%03d.jpeg
$ ffmpeg -start_number 86 -r 20 -f image2 -s 600x300 -i tmp2/test%03d.jpeg test.mp4
$ ffmpeg -i test.mp4 test.gif

A good-quality GIF can be converted as follows.

PALETTE_NAME=__palette__.png
OUTPUT_DIR=output

if [[ ! -d $OUTPUT_DIR ]]; then
    mkdir -p $OUTPUT_DIR
fi

for i in *.mpg; do
    ffmpeg -i $i -vf "fps=15,scale=600:-1:flags=lanczos,palettegen" -y $PALETTE_NAME
    ffmpeg -i $i -i $PALETTE_NAME -filter_complex "fps=15,scale=600:-1:flags=lanczos[x];[x][1:v]paletteuse" $OUTPUT_DIR/$i.gif
done

Screen recording

Linux: x11grab

x11 example:

ffmpeg -video_size 1024x768 -framerate 30 -f x11grab -i :0.0+100,200 output.mp4
  • -video_size - Recorded size
  • -framerate - Recording frame rate
  • -f x11grab -i :0.0+xxx,xxx - This means capturing the screen; the trailing +xxx,xxx means recording at a position offset by that many pixels from the top-left corner.

kmsgrab

KMS video input device.

ffmpeg -device /dev/dri/card0 -f kmsgrab -i - -vf 'hwmap=derive_device=vaapi,scale_vaapi=w=1920:h=1080:format=nv12' -c:v h264_vaapi -b:v 2500k -maxrate 4000k -y output-file.mkv

gdigrab (Windows)

Windows example:

ffmpeg -f gdigrab -i desktop -f dshow -i audio=[마이크 장치 명] -c:v h264_nvenc -r 30 -preset llhq -tune zerolatency -crf 25 -pix_fmt yuv420p [출력 파일 명]

Scaling (Resize; Scaling)

Various ways to scale:

$ ffmpeg -i input.avi -vf scale=320:240 output.avi
$ ffmpeg -i input.jpg -vf scale=320:240 output_320x240.png
$ ffmpeg -i input.jpg -vf scale=320:-1 output_320.png
$ ffmpeg -i input.jpg -vf scale=iw*2:ih input_double_width.png
$ ffmpeg -i input.jpg -vf scale=iw*.5:ih*.5 input_half_size.png
$ ffmpeg -i input.jpg -vf scale="'if(gt(a,4/3),320,-1)':'if(gt(a,4/3),-1,240)'" output_320x240_boxed.png

Same quality as the source

Copy without encoding using -c:v copy:

ffmpeg -i input.mp4 -c:v copy -c:a copy output.mp4

You can check the bitrate of the source video and set it to use the same bitrate.

ffmpeg -i input.mp4 -b:v <원본 비트레이트> -c:a copy output.mp4

When using CRF(Constant Rate Factor) (with codecs such as H.264), it is widely used to control encoding quality. The CRF value is set between 0 and 51; lower means higher quality. Values between 18 and 23 are typically used, and -crf 18 is considered nearly the same quality as the source.

ffmpeg -i input.mp4 -c:v libx264 -crf 18 -preset veryfast output.mp4

If you want quality similar to the source with the -q:v option, -q:v 2 or so is generally enough. However, since this option is VBR (Variable Bitrate), it is hard to guarantee exactly the same quality as the source.

ffmpeg -i input.mp4 -q:v 2 -c:a copy output.mp4

Stacking videos (stack)

Combine/stack two videos or images

Ffmpeg_vstack.png

ffmpeg -i input0 -i input1 -filter_complex vstack=inputs=2 output

Horizontal

Ffmpeg_hstack.png

ffmpeg -i input0 -i input1 -filter_complex hstack=inputs=2 output

With a border

Ffmpeg_stack_with_border.png

ffmpeg -i input0 -i input1 -filter_complex "[0]pad=iw+5:color=black[left];[left][1]hstack=inputs=2" output

Downmix and use original channel placements

Ffmpeg_stack_with_audio.png

ffmpeg -i input0 -i input1 -filter_complex "[0:v][1:v]vstack=inputs=2[v];[0:a][1:a]amerge=inputs=2[a]" -map "[v]" -map "[a]" -ac 2 output

Put all audio from each input into separate channels

Ffmpeg_stack_with_audio_sep_channels.png

ffmpeg -i input0 -i input1 -filter_complex "[0:v][1:v]vstack=inputs=2[v];[0:a][1:a]amerge=inputs=2,pan=stereo|c0<c0+c1|c1<c2+c3[a]" -map "[v]" -map "[a]"  output

Using audio from one particular input

ffmpeg -i input0 -i input1 -filter_complex "[0:v][1:v]vstack=inputs=2[v]" -map "[v]" -map 1:a output

Adding silent audio / If one input does not have audio

ffmpeg -i input0 -i input1 -filter_complex "[0:v][1:v]vstack=inputs=2[v];anullsrc[silent];[0:a][silent]amerge=inputs=2[a]" -map "[v]" -map "[a]" -ac 2 output.mp4

3 videos or images

Ffmpeg_3_hstack.png

ffmpeg -i input0 -i input1 -i input2 -filter_complex "[0:v][1:v][2:v]hstack=inputs=3[v]" -map "[v]" output

2x2 grid Using xstack

Ffmpeg_2x2_grid.png

ffmpeg -i input0 -i input1 -i input2 -i input3 -filter_complex "[0:v][1:v][2:v][3:v]xstack=inputs=4:layout=0_0|w0_0|0_h0|w0_h0[v]" -map "[v]" output

2x2 grid Using hstack and vstack

ffmpeg -i input0 -i input1 -i input2 -i input3 -filter_complex "[0:v][1:v]hstack=inputs=2[top];[2:v][3:v]hstack=inputs=2[bottom];[top][bottom]vstack=inputs=2[v]" -map "[v]" output

2x2 grid with text

Ffmpeg_2x2_grid_with_text.png

ffmpeg -i input0 -i input1 -i input2 -i input3 -filter_complex
"[0]drawtext=text='vid0':fontsize=20:x=(w-text_w)/2:y=(h-text_h)/2[v0];
 [1]drawtext=text='vid1':fontsize=20:x=(w-text_w)/2:y=(h-text_h)/2[v1];
 [2]drawtext=text='vid2':fontsize=20:x=(w-text_w)/2:y=(h-text_h)/2[v2];
 [3]drawtext=text='vid3':fontsize=20:x=(w-text_w)/2:y=(h-text_h)/2[v3];
 [v0][v1][v2][v3]xstack=inputs=4:layout=0_0|w0_0|0_h0|w0_h0[v]"
-map "[v]" output

4x4

ffmpeg -i input0 -i input1 -i input2 -i input3 -i input4 -i input5 -i input6 -i input7 -i input8 -i input9 -i input10 -i input11 -i input12 -i input13 -i input14 -i input15 -i input16 -filter_complex "[0:v][1:v][2:v][3:v][4:v][5:v][6:v][7:v][8:v][9:v][10:v][11:v][12:v][13:v][14:v][15:v]xstack=inputs=16:layout=0_0|w0_0|w0+w1_0|w0+w1+w2_0|0_h0|w4_h0|w4+w5_h0|w4+w5+w6_h0|0_h0+h4|w8_h0+h4|w8+w9_h0+h4|w8+w9+w10_h0+h4|0_h0+h4+h8|w12_h0+h4+h8|w12+w13_h0+h4+h8|w12+w13+w14_h0+h4+h8" output.mp4

If you need to scale the inputs first:

ffmpeg -i input0 -i input1 -i input2 -i input3 -i input4 -i input5 -i input6 -i input7 -i input8 -i input9 -i input10 -i input11 -i input12 -i input13 -i input14 -i input15 -i input16 -filter_complex "[0:v]scale=iw/4:-1[v0];[1:v]scale=iw/4:-1[v1];[2:v]scale=iw/4:-1[v2];[3:v]scale=iw/4:-1[v3];[4:v]scale=iw/4:-1[v4];[5:v]scale=iw/4:-1[v5];[6:v]scale=iw/4:-1[v6];[7:v]scale=iw/4:-1[v7];[8:v]scale=iw/4:-1[v8];[9:v]scale=iw/4:-1[v9];[10:v]scale=iw/4:-1[v10];[11:v]scale=iw/4:-1[v11];[12:v]scale=iw/4:-1[v12];[13:v]scale=iw/4:-1[v13];[14:v]scale=iw/4:-1[v14];[15:v]scale=iw/4:-1[v15];[v0][v1][v2][v3][v4][v5][v6][v7][v8][v9][v10][v11][v12][v13][v14][v15]xstack=inputs=16:layout=0_0|w0_0|w0+w1_0|w0+w1+w2_0|0_h0|w4_h0|w4+w5_h0|w4+w5+w6_h0|0_h0+h4|w8_h0+h4|w8+w9_h0+h4|w8+w9+w10_h0+h4|0_h0+h4+h8|w12_h0+h4+h8|w12+w13_h0+h4+h8|w12+w13+w14_h0+h4+h8" output.mp4

Resize/scale an input

ffmpeg -i input0 -i input2 -filter_complex "[0:v]scale=640:-1[v0];[v0][1:v]vstack=inputs=2" output

Delaying/pausing videos

ffmpeg -i top-left.mp4 -i top-right.mp4 -i bottom-left.mp4 -i bottom-right.mp4 -filter_complex "[1]tpad=start_mode=clone:start_duration=5[tr];[2]tpad=start_mode=clone:start_duration=10[bl];[3]tpad=start_mode=clone:start_duration=15[br];[0][tr][bl][br]xstack=inputs=4:layout=0_0|w0_0|0_h0|w0_h0[v];[1:a]adelay=5s:all=true[a1];[2:a]adelay=10s:all=true[a2];[3:a]adelay=15s:all=true[a3];[0:a][a1][a2][a3]amix=inputs=4[a]" -map "[v]" -map "[a]" output.mp4

Merging videos (Concat)

Used to join split videos. First, list the video files to join in a text file.

file 'abcdefg.mp4'
file 'smile.mp4'

If you saved it as a </code>filelist.txt</code> file, you can concatenate those files as follows.

ffmpeg -f concat -i filelist.txt -c copy output.mp4

To do it in one line on the command line:

ffmpeg -i "concat:in1.mp4|in2.mp4" -c copy "out.mp4"

Streaming over rtsp

ffmpeg -re -f concat -safe 0 -stream_loop -1 -i "$file_list" -c:v copy -c:a copy -f rtsp "$rtsp_url"

Streaming multiple image files at 5-second intervals

Create an images.txt file:

file 'image1.jpg'
duration 5
file 'image2.jpg'
duration 5
file 'image3.jpg'
duration 5
...

Run:

ffmpeg -stream_loop -1 -f concat -safe 0 -i images.txt -vf format=yuv420p -f rtsp rtsp://localhost:8554/demo

Without a list file

ffmpeg -framerate 1/5 -i image%03d.jpg -vf format=yuv420p -f rtsp rtsp://localhost:8554/demo

Using a filter

Result of asking ChatGPT. Needs verification:

ffmpeg -loop 1 -i image1.jpg -t 5 -loop 1 -i image2.jpg -t 5 -filter_complex "[0][1]concat=n=2:v=1:a=0,format=yuv420p" -f rtsp rtsp://localhost:8554/demo

TS File Concat

(for %i in (*.ts) do @echo file '%i') > mylist.txt
ffmpeg -f concat -i mylist.txt -c copy all.ts
ffmpeg -i all.ts -acodec copy -vcodec copy all.mp4

For numeric patterns

Image files need a framerate.

ffmpeg -framerate 25 -i %03d.png output.avi

Merging with a glob pattern

Image files need a framerate.

ffmpeg -framerate 25 -pattern_type glob -i "*.png" output.avi

Sorting the image list and passing it through a pipeline

Image files need a framerate.

cat $(find . -maxdepth 1 -name "*.png" | sort -V) | ffmpeg -framerate 25 -i - output.avi

Cropping a video region (crop)

To crop a 80×60 section, starting from position (200, 100):

$ ffmpeg -i in.mp4 -filter:v "crop=80:60:200:100" -c:a copy out.mp4

Splitting a video by playback duration

It cuts at the first frame after the time specified by -segment_time. So it isn't perfectly accurate:

ffmpeg -i input.mp4 -c copy -map 0 -segment_time 00:20:00 -f segment output%03d.mp4

If only the first chunk is playable, try adding -reset_timestamps 1:

ffmpeg -i input.mp4 -c copy -map 0 -segment_time 00:20:00 -f segment -reset_timestamps 1 output%03d.mp4

Generating demo/test videos (Demo/Test)

If you don't want to read all that, simply:

ffmpeg -f lavfi -i testsrc=size=1280x720:rate=30 -c:v libx264 -preset fast -tune zerolatency -f rtsp rtsp://localhost:8554/demo

Use lavfi as the Format on the Input Source side. It generates video without any particular input.

  • The allrgb source returns frames of size 4096x4096 of all rgb colors.
  • The allyuv source returns frames of size 4096x4096 of all yuv colors.
  • The color source provides an uniformly colored input.
  • The colorchart source provides a colors checker chart.
  • The colorspectrum source provides a color spectrum input.
  • The haldclutsrc source provides an identity Hald CLUT. See also haldclut filter.
  • The nullsrc source returns unprocessed video frames. It is mainly useful to be employed in analysis / debugging tools, or as the source for filters which ignore the input data.
  • The pal75bars source generates a color bars pattern, based on EBU PAL recommendations with 75% color levels.
  • The pal100bars source generates a color bars pattern, based on EBU PAL recommendations with 100% color levels.
  • The rgbtestsrc source generates an RGB test pattern useful for detecting RGB vs BGR issues. You should see a red, green and blue stripe from top to bottom.
  • The smptebars source generates a color bars pattern, based on the SMPTE Engineering Guideline EG 1-1990.
  • The smptehdbars source generates a color bars pattern, based on the SMPTE RP 219-2002.
  • The testsrc source generates a test video pattern, showing a color pattern, a scrolling gradient and a timestamp. This is mainly intended for testing purposes.
  • The testsrc2 source is similar to testsrc, but supports more pixel formats instead of just rgb24. This allows using it as an input for other tests without requiring a format conversion.
  • The yuvtestsrc source generates an YUV test pattern. You should see a y, cb and cr stripe from top to bottom.

Parameters

The sources accept the following parameters:

level
Specify the level of the Hald CLUT, only available in the haldclutsrc source. A level of N generates a picture of NNN by NNN pixels to be used as identity matrix for 3D lookup tables. Each component is coded on a 1/(N*N) scale.
color, c
Specify the color of the source, only available in the color source. For the syntax of this option, check the (ffmpeg-utils)"Color" section in the ffmpeg-utils manual.
size, s
Specify the size of the sourced video. For the syntax of this option, check the (ffmpeg-utils)"Video size" section in the ffmpeg-utils manual. The default value is 320x240.
This option is not available with the allrgb, allyuv, and haldclutsrc filters.
rate, r
Specify the frame rate of the sourced video, as the number of frames generated per second. It has to be a string in the format frame_rate_num/frame_rate_den, an integer number, a floating point number or a valid video frame rate abbreviation. The default value is "25".
duration, d
Set the duration of the sourced video. See (ffmpeg-utils)the Time duration section in the ffmpeg-utils(1) manual for the accepted syntax.
If not specified, or the expressed duration is negative, the video is supposed to be generated forever.
Since the frame rate is used as time base, all frames including the last one will have their full duration. If the specified duration is not a multiple of the frame duration, it will be rounded up.
sar
Set the sample aspect ratio of the sourced video.
alpha
Specify the alpha (opacity) of the background, only available in the testsrc2 source. The value must be between 0 (fully transparent) and 255 (fully opaque, the default).
decimals, n
Set the number of decimals to show in the timestamp, only available in the testsrc source.
The displayed timestamp value will correspond to the original timestamp value multiplied by the power of 10 of the specified value. Default value is 0.
type
Set the type of the color spectrum, only available in the colorspectrum source. Can be one of the following:
  • black, white, all
patch_size
Set patch size of single color patch, only available in the colorchart source. Default is 64x64.
preset
Set colorchecker colors preset, only available in the colorchart source.
Available values are: reference, skintones
Default value is reference.

Examples

Generate a video with a duration of 5.3 seconds, with size 176x144 and a frame rate of 10 frames per second:
testsrc=duration=5.3:size=qcif:rate=10
The following graph description will generate a red source with an opacity of 0.2, with size "qcif" and a frame rate of 10 frames per second:
[email protected]:s=qcif:r=10
If the input content is to be ignored, nullsrc can be used. The following command generates noise in the luma plane by employing the geq filter:
nullsrc=s=256x256, geq=random(1)*255:128:128

testsrc

The testsrc filter generates a test video pattern showing a color pattern, a scrolling gradient, and a timestamp. This is useful for testing purposes.

This example will create a 10 second output, 30 fps (300 frames total), with a frame size of 640x360

ffmpeg -f lavfi -i testsrc=duration=10:size=1280x720:rate=30 testsrc.mpg

The following command will generate a video with a duration of 5.3 seconds, with size 176x144 and a frame rate of 10 frames per second.

ffmpeg -f lavfi -i testsrc=duration=5.3:size=qcif:rate=10 testsrc2.mp4

smptebars

The smptebars source generates a color bars pattern, based on the SMPTE Engineering Guideline EG 1-1990.

The smptehdbars source generates a color bars pattern, based on the SMPTE RP 219-2002.

This example will create a 10 second output, 30 fps (300 frames total), with a frame size of 640x360:

ffmpeg -f lavfi -i smptebars=duration=10:size=640x360:rate=30 smptebars.mp4

color source

The following graph description will generate a red source with an opacity of 0.2, with size "qcif" and a frame rate of 10 frames per second with the duration of 5 seconds.

ffmpeg -f lavfi -i color=c=[email protected]:duration=5:s=qcif:r=10 colorsrc.mp4

rgbtestsrc

The rgbtestsrc source generates an RGB test pattern useful for detecting RGB vs BGR issues. We should see a red, green and blue stripe from top to bottom.

ffmpeg -f lavfi -i rgbtestsrc -pix_fmt yuv420p -t 5 rgbtestsrc.mp4

Formatting file names with time

strftime

Uses strftime() on the file name to expand segment file names to local time (localtime). Segment numbers can also be used in this mode, but to use them you must specify second_level_segment_index hls_flag, and %%d becomes the specifier.

ffmpeg -i in.nut -strftime 1 -hls_segment_filename 'file-%Y%m%d-%s.ts' out.m3u8

This example generates the playlist out.m3u8 and segment files (file-20160215-1455569023.ts, file-20160215-1455569024.ts, etc.). Note: the %s specifier is not available on some systems/environments. See the strftime() page.

ffmpeg -i in.nut -strftime 1 -hls_flags second_level_segment_index -hls_segment_filename 'file-%Y%m%d-%%04d.ts' out.m3u8

This example generates the playlist out.m3u8 and segment files (file-20160215-0001.ts, file-20160215-0002.ts, etc.).

strftime_mkdir

When used with -strftime_mkdir, all subdirectories that the file name expands into are created.

ffmpeg -i in.nut -strftime 1 -strftime_mkdir 1 -hls_segment_filename '%Y%m%d/file-%Y%m%d-%s.ts' out.m3u8

This example creates the directory 201560215 (if it doesn't exist), then generates the playlist out.m3u8 and segment files (20160215/file-20160215-1455569023.ts, 20160215/file-20160215-1455569024.ts, etc.). .

ffmpeg -i in.nut -strftime 1 -strftime_mkdir 1 -hls_segment_filename '%Y/%m/%d/file-%Y%m%d-%s.ts' out.m3u8

This example creates the directory hierarchy 2016/02/15 (if any part of it doesn't exist), then generates the playlist out.m3u8 and segment files 2016/02/15/file-20160215-1455569023.ts, 2016/02/15/file-20160215-1455569024.ts, etc.

Adjusting video quality (sameq, qscale)

It used to be the -sameq flag, but it's no longer used. Use -qscale 0.

Changing the audio sample format (sample_fmt)

ffmpeg -i … -c:a flac -sample_fmt s16 output.flac

Constant Rate Factor (CRF)

Controls quality by the picture quality our eyes perceive instead of by Bitrate.

Use this rate control mode if you want to keep the best quality and care less about the file size. This is the recommended rate control mode for most uses.

This method allows the encoder to attempt to achieve a certain output quality for the whole file when output file size is of less importance. This provides maximum compression efficiency with a single pass. By adjusting the so-called quantizer for each frame, it gets the bitrate needed to keep the requested quality level. The downside is that you can't tell it to get a specific file size or not go over a specific size or bitrate. This means that this method is not recommended for encoding videos for streaming.

Re-saving videos recorded for streaming in 1-hour units

mkdir records
ffmpeg -hide_banner -i rtsp://localhost:8554/cam4 -c copy -f segment -strftime 1 -strftime_mkdir 1 -segment_time 3600 -reset_timestamps 1 ./records/%Y%m%d-%H%M%S.mp4

Then in the records folder,

20240515_101044-328758.mp4
20240515_111042-062053.mp4
...

files are saved like this. I specified the -segment_time 3600 option, but the file sizes changed arbitrarily.

If you try to use these files directly, the following error occurs:

DTS 1624139402481, next:10790932074 st:0 invalid dropping
PTS 1624139402481, next:10790932074 invalid dropping st:0

DTS and PTS seem to be wrong... (I don't know why. My guess is that it cuts files depending on streaming conditions and the like.)

So make a list of these files

for f in *.mp4; do echo "file '$PWD/$f'"; done > file_list.txt

and re-encode with this list to split the files again.

mkdir output
ffmpeg -f concat -safe 0 -i file_list.txt -c:v libx264 -crf 18 -preset veryslow -c:a copy -f segment -strftime_mkdir 1 -strftime 1 -segment_time 3600 -reset_timestamps 1 ./output/%Y%m%d-%H%M%S.mp4

Re-encoding is required, so don't use the -c:v copy flag.

Horizontal flip/vertical flip (Flip)

ffmpeg -i input_video_file_path -vf hflip output_video_file_path
ffmpeg -i input_video_file_path -vf vflip output_video_file_path

Rotation (rotate)

$ ffmpeg -i input.m4v -metadata:s:v rotate="90" -codec copy output.m4v

Rotating camera videos

If you load camera videos with something like cv2, they display incorrectly. (rotated)

Camera videos have rotation info in their metadata, so remove it:

ffmpeg -i input.mp4 -c copy -metadata:s:v:0 rotate=0 output.mp4

That gives you the original file; rotate it again and encode it:

ffmpeg -i input.mp4 -vf "transpose=2" output.mp4

See the list below for transpose options:

  • 0 = 90CounterCLockwise and Vertical Flip (default)
  • 1 = 90Clockwise
  • 2 = 90CounterClockwise
  • 3 = 90Clockwise and Vertical Flip

For reference, a 180-degree rotation is just vflip, hflip:

ffmpeg.exe -i input.mp4 -vf "vflip,hflip" output.mp4

Merging video (map)

Video and Audio muxing example:

$ ffmpeg -i video_only.mp4 -i audio_only.webm -c:v copy -c:a aac  -map 0:v:0 -map 1:a:0 result.mp4

Converting video for mobile

File formats officially supported by Android:

Codec

Extension

Notes

H.263

3gp, mp4

H.264 AVC

3gp, mp4, ts

Encoding supported from Honeycomb
ts format also supported from Honeycomb

MPEG-4 SP

3gp

VP8

webm, mkv

Supported from 2.3.3
Streaming available from ICS

File formats officially supported by iPhone:

Codec

Extension

Notes

H.264

m4v, mp4, mov, 3gp

640 * 480, 30fps, 1.5Mbps
320 * 240, 30fps, 768Kbps

MPEG-4

m4v, mp4, mov, 3gp

640 * 480, 30fps, 2.5Mbps

For reference, under the iPhone video playback review criteria, playing a file of 10Mb or more in streaming form without using HLS can be a reason for Reject. Bitrate conditions when encoding:

Quality

Video

Audio

Low

96Kbps

64Kbps

Medium

256Kbps

64Kbps

High

800Kbps

64Kbps

Commonly used conversion for mobile:

$ ffmpeg -i input.avi -c:v libx264 -b:v 800k -c:a aac -b:a 64k -ar 44100 output.mp4

Converting to TS

See also: MPEG transport stream#Use ffmpeg

Infinite streaming (Infinite stream; -stream_loop)

You should be able to use the -stream_loop -1 flag before the input (-i):

$ ffmpeg -threads 2 -re -fflags +genpts -stream_loop -1 -i ./test.mp4 -c copy ./test.m3u8

The -fflags +genpts will regenerate the pts timestamps so it loops smoothly, otherwise the time sequence will be incorrect as it loops.

H264 conversion

Uses an encoding start time of 180 seconds, FrameRate 10 seconds, and the h.264 video codec.

$ ffmpeg -i n5.mp4 -ss 180 -r 10 -vcodec h264 n6.mp4

From 1 h 44 min 17 s of the input file, for 800 seconds: Video profile=high, Bitrate=2015kb/s, H264, Audio=copy

$ ffmpeg -ss 01:44:17 -t 800 -i original.mp4 -profile:v high -b:v 2015k -c:v h264 -c:a copy original-convert.mp4

Saving images at a specific frame STEP

$ ffmpeg -i sageri.mp4 -vf framestep=20,setpts=N/FRAME_RATE/TB result/result.%05d.jpg

Script to convert all mp4 files in a folder:

#!/bin/bash

for i in *.mp4; do
    dirname=${i%.*}
    if [[ ! -d "$dirname" ]]; then
        mkdir "$dirname"
    fi
    ffmpeg -i $i -vf framestep=20,setpts=N/FRAME_RATE/TB $dirname/$dirname.%05d.jpg
done

INFORMATION

This is the command I used when extracting frames from deep-learning videos

Extracting images per keyframe

Applies a filter that selects video frames by I-Frame.

$ ffmpeg -i save-20191127_104234.avi -q:v 2 -vf select="eq(pict_type\,PICT_TYPE_I)" -vsync 0 front1/%04d.jpg

Extracting an image at a specific frame

ffmpeg -i lcsc130906-164626.255.mp4 -s 320x240 -ss 00:00:13 -vcodec png test.png

Setting a thumbnail (Thumbnail) in FFmpeg

ffmpeg -loop 1 -i "thumb.jpg" -i "in.aac" -c:v libx264 -tune stillimage -acodec copy -pix_fmt yuv420p -shortest "out.mp4"

Creating an MP4 file with embedded subtitles

ffmpeg -i "in.mp4" -i "sub.srt" -map 0:v:0 -c:v copy -map 0:a:0 -c:a copy -map 1 -c:s:0 mov_text -metadata:s:s:0 title=srt -metadata:s:s:0 language=kor "out.mp4"

FFmpeg command to merge multiple images and music

(Tested with FFmpeg v1.2.2 on Android NDK)

# -threads 1: Thread 1개를 사용한다.
# -f image2: 이미지를 변환하는 포맷을 적용한다.
# -s 320x240: 영상의 크기는 320x240으로 적용한다.
# -r 18: FrameRate(FPS)는 18로 설정한다.
# -i /sdcard/sdcard0/DCIM/img%d.jpg: 위의 설정을 해당 INPUT파일에 적용한다.
# -----------------------------------------------------------------------
# -ss 2: 2초 부터 시작한다.
# -t 10: 10초동안 적용한다.
# -i /sdcard/sdcard0/Music/temp.mp3: 위의 설정을 해당 INPUT파일에 적용한다.
# -----------------------------------------------------------------------
# -acodec copy: 오디오코덱 정보를 복사(COPY)한다.
# -y: 동일한 파일이 존재할 경우 덮어쓰기 한다.
# /sdcard/sdcard0/Download/result.mp4: 위의 설정을 해당 OUTPUT파일에 적용한다.
# -----------------------------------------------------------------------
ffmpeg -threads 1 -f image2 -s 320x240 -r 18 -i /sdcard/sdcard0/DCIM/img%d.jpg -ss 2 -t 10 -i /sdcard/sdcard0/Music/temp.mp3 -acodec copy -y /sdcard/sdcard0/Download/result.mp4

Piping video and audio together

Use a named pipe (FIFO). Simplified example for Linux/macOS:

Make named pipes:

mkfifo video
mkfifo audio

Output/pipe video and audio to stdout. This is using ffmpeg to generate video and audio to the named pipes just for demonstration purposes.

ffmpeg -y -re -f lavfi -i testsrc2=s=1280x720:r=25 -f rawvideo video & ffmpeg -y -re -f lavfi -i sine=r=44100 -f s16le audio

Use the named pipes as inputs for ffmpeg:

ffmpeg -f rawvideo -video_size 320x240 -pixel_format yuv420p -framerate 25 -i video -f s16le -sample_rate 44100 -channels 1 -i audio -t 10 output.mp4

Printing the PTS of every frame

The -vf showinfo flag lets you see per-frame info for a video.

ffmpeg -i 20240516_000830-336375.mp4 -vf showinfo -f null -

The output looks like this:

DTS -18446492073, next:1684276 st:0 invalid dropping
PTS -18446492073, next:1684276 invalid dropping st:0
[Parsed_showinfo_0 @ 0x5e90efa16100] n:  44 pts: 127561 pts_time:1.41734 pos:   748517 fmt:yuvj420p sar:0/1 s:1920x1080 i:P iskey:0 type:P checksum:282D0C62 plane_checksum:[BC978477 F7302159 8DDE6683] mean:[103 126 135] stdev:[44.3 5.8 9.9]
[Parsed_showinfo_0 @ 0x5e90efa16100] color_range:pc color_space:bt709 color_primaries:bt709 color_trc:bt709
DTS -18446486043, next:1717643 st:0 invalid dropping
PTS -18446486043, next:1717643 invalid dropping st:0
[Parsed_showinfo_0 @ 0x5e90efa16100] n:  45 pts: 130564 pts_time:1.45071 pos:   760197 fmt:yuvj420p sar:0/1 s:1920x1080 i:P iskey:0 type:P checksum:15F81C80 plane_checksum:[C55EC981 3F730DCF 9C7F4521] mean:[102 126 136] stdev:[43.5 5.9 10.1]
[Parsed_showinfo_0 @ 0x5e90efa16100] color_range:pc color_space:bt709 color_primaries:bt709 color_trc:bt709
DTS -18446483073, next:1751010 st:0 invalid dropping
PTS -18446483073, next:1751010 invalid dropping st:0
[Parsed_showinfo_0 @ 0x5e90efa16100] n:  46 pts: 133567 pts_time:1.48408 pos:   779000 fmt:yuvj420p sar:0/1 s:1920x1080 i:P iskey:0 type:P checksum:A0AED87B plane_checksum:[45526828 5139182B 50745828] mean:[102 126 136] stdev:[43.5 5.9 10.1]
[Parsed_showinfo_0 @ 0x5e90efa16100] color_range:pc color_space:bt709 color_primaries:bt709 color_trc:bt709
DTS -18446477043, next:1784377 st:0 invalid dropping
PTS -18446477043, next:1784377 invalid dropping st:0
[Parsed_showinfo_0 @ 0x5e90efa16100] n:  47 pts: 136570 pts_time:1.51744 pos:   789899 fmt:yuvj420p sar:0/1 s:1920x1080 i:P iskey:0 type:P checksum:98464413 plane_checksum:[B4F2AAE9 75DA6E86 A1792A95] mean:[102 125 136] stdev:[43.3 5.9 10.3]
[Parsed_showinfo_0 @ 0x5e90efa16100] color_range:pc color_space:bt709 color_primaries:bt709 color_trc:bt709
...

To output only the info you want in jsonl format:

ffmpeg -i 20240516_000830-336375.mp4 -vf showinfo -f null - 2>&1 \
    | grep '^\[Parsed_showinfo' \
    | sed -e 's/\[.* @ 0x[a-f0-9]*\] //g' \
    | grep '^n:' \
    | sed -e 's/ fmt:.*//g' -e 's/n: *\([0-9]*\) *pts: *\([0-9]*\) *pts_time: *\([0-9.]*\) *pos: *\([0-9]*\)/{"n": \1, "pts": \2, "pts_time": \3, "pos": \4}/g'

The output looks like this:

{"n": 0, "pts": 6030, "pts_time": 0.067, "pos": 13942}
{"n": 1, "pts": 9000, "pts_time": 0.1, "pos": 73771}
{"n": 2, "pts": 18000, "pts_time": 0.2, "pos": 140669}
{"n": 3, "pts": 20250, "pts_time": 0.225, "pos": 154912}

As a script for convenience:

#!/usr/bin/env bash

REMOVE_LOGGING_PREFIX='s/\[.* @ 0x[a-f0-9]*\] //g'
REMOVE_FMT='s/ fmt:.*//g'
FORMAT_JSONL='s/n: *\([0-9]*\) *pts: *\([0-9]*\) *pts_time: *\([0-9.]*\) *pos: *\([0-9]*\)/{"n": \1, "pts": \2, "pts_time": \3, "pos": \4}/g'

function gen_pts
{
    if [[ ! -f "$1" ]]; then
        echo "Not found video file: '$1'" 1>&2
        exit 1
    fi

    ffmpeg -hide_banner -i "$1" -vf showinfo -f null - 2>&1 \
        | grep '^\[Parsed_showinfo' \
        | sed -e "$REMOVE_LOGGING_PREFIX" \
        | grep '^n:' \
        | sed -e "$REMOVE_FMT" \
        | sed -e "$FORMAT_JSONL"
}

while [[ -n $1 ]]; do
    echo "Run ffmpeg: '$1' ..."
    gen_pts "$1" > "$1.pts"
    shift
done

Filter complex

How to use the -filter_complex flag.

SeAH video processing example

ffmpeg -i video1.mp4 -i video2.mp4 -filter_complex "[0:v]scale=1920:1080[left];[1:v]scale=1920:1080[right];[right]hflip[right_flip];[left][right_flip]hstack=inputs=2[v]" -map "[v]" output.mp4
  1. Scale video1.mp4 to 1920x1080 and put it on the left,
  2. scale video2.mp4 to 1920x1080, flip it horizontally (hflip), and put it on the right,
  3. then stack the two videos horizontally (hstack)

Realtime Overlay

ffmpeg -re -loop 1 -i smpte-color-bars-1080p.png -vf drawtext="fontfile=monofonto.ttf: fontsize=96: box=1: [email protected]: boxborderw=5: fontcolor=white: x=(w-text_w)/2: y=((h-text_h)/2)+((h-text_h)/4): text='%{gmtime\:%H\\\\\:%M\\\\\:%S}'" -r 25 -vcodec libx264 -f mpegts udp://127.0.0.1:1234

The important bit for the timecode being: text='%{gmtime\:%H\\\\\:%M\\\\\:%S}'

There is some crazy escaping in there to get the colons to display(in bash), but that is UTC/GMT time of day timecode burnt in... just need to figure out the syntax for multiple drawtext functions now and I'm all set...

Realtime Overlay 2

-vf drawtext="expansion=strftime:fontfile='/usr/share/fonts/cantarell/Cantarell-Light.otf':fontsize=14:fontcolor=white:shadowcolor=black:shadowx=2:shadowy=1:text='%Y-%m-%d\ %H\\\\:%M\\\\:%S':x=8:y=8"

Ffmpeg-embed-current-time-example-02.png

Stream Mapping (-map flag)

The -map option is used to choose which streams from the input should be included in the output. The -map option can also be used to exclude specific streams with negative mapping.

Ffmpeg_map_example.png

Stream specifiers

Some options are applied per-stream, e.g. bitrate or codec. Stream specifiers are used to precisely specify which stream(s) a given option belongs to.

A stream specifier is a string generally appended to the option name and separated from it by a colon. E.g. -codec:a:1 ac3 contains the a:1 stream specifier, which matches the second audio stream. Therefore, it would select the ac3 codec for the second audio stream.

A stream specifier can match several streams, so that the option is applied to all of them. E.g. the stream specifier in -b:a 128k matches all audio streams.

An empty stream specifier matches all streams. For example, -codec copy or -codec: copy would copy all the streams without reencoding.

Possible forms of stream specifiers are:

stream_index
Matches the stream with this index. E.g. -threads:1 4 would set the thread count for the second stream to 4. If stream_index is used as an additional stream specifier (see below), then it selects stream number stream_index from the matching streams. Stream numbering is based on the order of the streams as detected by libavformat except when a program ID is also specified. In this case it is based on the ordering of the streams in the program.
stream_type[:additional_stream_specifier]
'v' or 'V' for video
  • 'v' matches all video streams,
  • 'V' only matches video streams that are not attached pictures, video thumbnails, or cover art.
'a' for audio
's' for subtitles
'd' for data
't' for attachments
If additional_stream_specifier is used, it matches streams that both have this type (Type) and match the additional_stream_specifier.
p:program_id[:additional_stream_specifier]
Matches streams which are in the program with the id program_id. If additional_stream_specifier is used, then it matches streams which both are part of the program and match the additional_stream_specifier.
#stream_id or i:stream_id
Match the stream by stream id (e.g. PID in MPEG-TS container).
m:key[:value]
Matches streams with the metadata tag key having the specified value. If value is not given, matches streams that contain the given tag with any value.
u
Matches streams with usable configuration, the codec must be defined and the essential information such as video dimension or audio sample rate must be present.

Note that in ffmpeg, matching by metadata will only work properly for input files.

Low-latency mode (Lowest Latency)

  • Input Flags
    • -fflags nobuffer
    • -flags low_delay
  • Output Flags
    • -c:v libx264
    • -preset ultrafast
    • -crf 30

H.264

RTSP flags

rtsp_transport

  -rtsp_transport    <flags>      ED...... set RTSP transport protocols (default 0)
     udp                          ED...... UDP
     tcp                          ED...... TCP
     udp_multicast                .D...... UDP multicast
     http                         .D...... HTTP tunneling

Use this when you get an error related to FFmpeg#Nonmatching transport in server reply.

rtsp_flags

  -rtsp_flags        <flags>      .D...... set RTSP flags (default 0)
     filter_src                   .D...... only receive packets from the negotiated peer IP
     listen                       .D...... wait for incoming connections
     prefer_tcp                   ED...... try RTP via TCP first, if available

With -rtsp_flags listen, it waits until a connection is made.

Generating multi-resolution HLS

ffmpeg -f flv -i "rtmp://server/live/livestream" \
  -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 -map 0:v:0 -map 0:a:0 \
  -c:v libx264 -crf 22 -c:a aac -ar 44100 \
  -filter:v:0 scale=w=480:h=360  -maxrate:v:0 600k -b:a:0 500k \
  -filter:v:1 scale=w=640:h=480  -maxrate:v:1 1500k -b:a:1 1000k \
  -filter:v:2 scale=w=1280:h=720 -maxrate:v:2 3000k -b:a:2 2000k \
  -var_stream_map "v:0,a:0,name:360p v:1,a:1,name:480p v:2,a:2,name:720p" \
  -preset fast -hls_list_size 10 -threads 0 -f hls \
  -hls_time 3 -hls_flags independent_segments \
  -master_pl_name "livestream.m3u8" \
  -y "livestream-%v.m3u8"

WARNING

Need to test the command-line result again. Probably wrong

The master m3u8, generated by FFmpeg:

#EXTM3U
#EXT-X-VERSION:6
#EXT-X-STREAM-INF:BANDWIDTH=1210000,RESOLUTION=480x360,CODECS="avc1.640015,mp4a.40.2"
livestream-360p.m3u8

#EXT-X-STREAM-INF:BANDWIDTH=2283600,RESOLUTION=640x480,CODECS="avc1.64001e,mp4a.40.2"
livestream-480p.m3u8

#EXT-X-STREAM-INF:BANDWIDTH=3933600,RESOLUTION=1280x720,CODECS="avc1.64001f,mp4a.40.2"
livestream-720p.m3u8

Saving HLS while streaming output using the m3u8 file

Using two command lines

ffmpeg -i rtsp://admin:[email protected]/stream1 -c copy asdf.m3u8
ffmpeg -i asdf.m3u8 -f rtsp rtsp://localhost:8554/stream

FFmpeg options by device

Android Conversions

device

screen resolution

command

Nexus One
(if input video size > 800x480)

800x480

ffmpeg -i ally.avi -y -acodec aac -strict experimental -ac 2 -ab 160k -s 800x480 -vcodec libx264 -vpre ipod640 -vpre slow -crf 22 -f mp4 1.mp4

Nexus One
(if input video size <= 800x480)

800x480

ffmpeg -i ally.avi -y -acodec aac -strict experimental -ac 2 -ab 160k -vcodec libx264 -vpre ipod640 -vpre slow -crf 22 -f mp4 2.mp4

Dream/G1
if input video size > 480x320

480x320

ffmpeg -i ally.avi -y -acodec aac -strict experimental -ac 2 -ab 160k -vcodec libx264 -s 480x320 -vpre ipod640 -vpre slow -crf 22 -f mp4 3.mp4

Dream/G1
if input video size <= 480x320

480x320

ffmpeg -i ally.avi -y -acodec aac -strict experimental -ac 2 -ab 160k -vcodec libx264 -vpre ipod640 -vpre slow -crf 22 -f mp4 4.mp4

Magic/myTouch

480x320

same as G1

Droid
(if input video size > 854x480)

854x480

ffmpeg -i ally.avi -y -acodec aac -strict experimental -ac 2 -ab 160k -vcodec libx264 -s 854x480 -vpre ipod640 -vpre slow -crf 22 -f mp4 5.mp4

Droid
(if input video size <= 854x480)

854x480

ffmpeg -i ally.avi -y -acodec aac -strict experimental -ac 2 -ab 160k -vcodec libx264 -vpre ipod640 -vpre slow -crf 22 -f mp4 6.mp4

Eris/Desire

480x320

same as G1

Hero

480x320

same as G1

Cliq/DEXT

480x320

same as G1

Behold II

480x320

same as G1

Apple Format Conversions

device

screen resolution

command

iPhone

320x480

ffmpeg -i ally.avi -acodec aac -strict experimental -ac 2 -ab 160k -s 480x320 -vcodec libx264 -vpre slow -vpre ipod640 -b 1200k -f mp4 a1.mp4

ipod touch

same as iphone

same as iphone

ipod nano

320x480

same as iphone

ipod classic

640x480

same as iphone

iPhone 4/iPod Touch 4

640x480

ffmpeg -i ally.avi -acodec aac -strict experimental -ac 2 -ab 160k -s 640x480 -vcodec libx264 -vpre slow -vpre ipod640 -b 1200k -f mp4 -threads 0 a2.mp4

iPad

1024x768

ffmpeg -i ally.avi -acodec aac -strict experimental -ac 2 -ab 160k -s 1024x768 -vcodec libx264 -vpre slow -vpre ipod640 -b 1200k -f mp4 -threads 0 a3.mp4

Apple Universal

1280x720

ffmpeg -i ally.avi -acodec aac -strict experimental -ac 2 -ab 160k -s 1080x720 -vcodec libx264 -vpre slow -vpre ipod640 -b 1200k -f mp4 -threads 0 a4.mp4

Old Android Conversions

device

screen resolution

command

Nexus One
(if input video size > 800x480)

800x480

ffmpeg -i all.flv -y -f mp4 -strict experimental -vcodec mpeg4 -sameq -s 800x480 -acodec aac -ab 160000 -r 18 old2.mp4

Nexus One
(if input video size <= 800x480)

800x480

ffmpeg -i INPUT -y -f mp4 -vcodec mpeg4 -sameq -acodec aac -ab 160000 -r 18 OUTPUT

Dream/G1
if input video size > 480x320

480x320

ffmpeg -i all.flv -y -f mp4 -strict experimental -vcodec mpeg4 -sameq -s 480x320 -acodec aac -ab 160000 -r 18 old3.mp4

Dream/G1
if input video size <= 480x320

480x320

same as old2

Magic/myTouch

480x320

same as G1

Droid
(if input video size > 854x480)

854x480

ffmpeg -i all.flv -y -f mp4 -strict experimental -vcodec mpeg4 -sameq -s 854x480 -acodec aac -ab 160000 -r 18 old4.mp4

Droid
(if input video size <= 854x480)

850x480

ffmpeg -i all.flv -y -f mp4 -vcodec mpeg4 -sameq -acodec aac -ab 160000 -r 18 old5.mp4

Eris/Desire

480x320

same as G1

Nexus One
(if input video size > 800x480)

480x320

same as G1

Nexus One
(if input video size > 800x480)

480x320

same as G1

Nexus One
(if input video size > 800x480)

480x320

same as G1

Old Apple Format Conversions

device

screen resolution

command

iPhone

320x480

ffmpeg -i ally.avi -acodec aac -strict experimental -ac 2 -ab 160k -s 480x320 -vcodec libx264 -vpre slow -vpre ipod640 -b 1200k -f mp4 a1.mp4

ipod touch

same as iphone

same as iphone

ipod nano

same as iphone

same as iphone

ipod classic

same as iphone

same as iphone

iPad/iPhone G4

for 3.5

ffmpeg -i all.flv -acodec aac -ab 160000 -strict experimental -vcodec mpeg4 -b 1200kb -mbd 2 -cmp 2 -subcmp 2 -s 640x480 -r 20 olda2.mp4

iPad

1024x768

ffmpeg -i need a command to output to h.264 OUTPUT

Apple Universal

1280x720

ffmpeg -i all.flv -acodec aac -ab 160000 -strict experimental -vcodec mpeg4 -b 1200kb -mbd 2 -cmp 2 -subcmp 2 -s 1280x720 -r 20 olda3.mp4

What I tested

[Ohys-Raws] 1280x720
ffmpeg -i input.mkv -c:a copy -s 1280x720 -vcodec libx264 -b:v 1200k a4.mp4
Wonju City drone fire detection 1280x720 (average 740k)
ffmpeg -i input.mp4 -profile:v high -b:v 750k -c:v h264 output.mp4

Applying Whisper

FFmpeg 8.0 officially added support for the Whisper speech recognition model

ffmpeg -i input.mp4 -vn \  
-af "whisper=model=../whisper.cpp/models/ggml-base.en.bin:language=en:queue=3:destination=output.srt:format=srt" \  
-f null -  

FFplay

Mac OSX Homebrew install:

$ brew install ffmpeg --with-sdl2

See that page for details.

Troubleshooting

Consolidated in the FFmpeg#Troubleshooting section.

See also

Favorite site

Online Tools

  • FFmpeg Explorer! - Test ffmpeg filters online
    • Test FFMpeg's various filters in the browser in real time
    • Shows the filter graph in a GUI. You can change connections between filters, and each item's detailed options are listed on the right and can be changed
    • Renders a short 3-second video in real time so you can compare while watching the result
    • Shows the actual input command for the filters you tested, so you can copy and use it
    • Open source, implemented with ffmpeg.wasm
    • Shows error logs and provides an option to clear errors
    • Especially useful for people unfamiliar with FFmpeg or who want to experiment with various filters and options

Tip & Guide

References


  1. High_quality_GIF_with_FFmpeg.pdf ↩

  2. Using_ffmpeg_to_convert_a_set_of_images_into_a_video.pdf ↩

  3. Ffmpeg_commandline_howto.pdf ↩

author Zer0 sitemap