Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
ffmpeg guide

ffmpeg

Converting Audio into Different Formats / Sample Rates

Minimal example: transcode from MP3 to WMA:
ffmpeg -i input.mp3 output.wma

You can get the list of supported formats with:
ffmpeg -formats

Convert WAV to MP3, mix down to mono (use 1 audio channel), set bit rate to 64 kbps and sample rate to 22050 Hz:
ffmpeg -i input.wav -ac 1 -ab 64000 -ar 22050 output.mp3

Convert any MP3 file to WAV 16khz mono 16bit:
ffmpeg -i 111.mp3 -acodec pcm_s16le -ac 1 -ar 16000 out.wav

Convert any MP3 file to WAV 20khz mono 16bit for ADDAC WAV Player:
ffmpeg -i 111.mp3 -acodec pcm_s16le -ac 1 -ar 22050 out.wav
cd into dir for batch process:
for i in *.mp3; do ffmpeg -i "$i" -acodec pcm_s16le -ac 1 -ar 22050 "${i%.mp3}-encoded.wav"; done

Picking the 30 seconds fragment at an offset of 1 minute:
In seconds
ffmpeg -i input.mp3 -ss 60 -t 30 output.wav

In HH:MM:SS format
ffmpeg -i input.mp3 -ss 0:01:00 -t 0:00:30 output.wav

Split an audio stream at specified segment rate (e.g. 3 seconds)
ffmpeg -i somefile.mp3 -f segment -segment_time 3 -c copy out%03d.mp3

Extract Audio

ffmpeg -i input-video.avi -vn -acodec copy output-audio.aac

vn is no video.
acodec copy says use the same audio stream that's already in there.

ffmpeg -i video.mp4 -f mp3 -ab 192000 -vn music.mp3

The -i option in the above command is simple: it is the path to the input file. The second option -f mp3 tells ffmpeg that the ouput is in mp3 format. The third option i.e -ab 192000 tells ffmpeg that we want the output to be encoded at 192Kbps and -vn tells ffmpeg that we dont want video. The last param is the name of the output file.

Replace Audio on a Video without re-encoding.

strip audio stream away from video
ffmpeg -i INPUT.mp4 -codec copy -an OUTPUT.mp4

combine the two streams together (new audio with originally exisiting video)
ffmpeg -i 36.MOV -i 36.wav -map 0:v -map 1:a -c copy -y 36-encoded.mov
or add an offset to audio
ffmpeg -i 36.MOV -itsoffset -0.25 -i 36.wav -map 0:v -map 1:a -c copy -y 36-encoded.mov
or
ffmpeg -i INPUT.mp4 -i AUDIO.wav -shortest -c:v copy -c:a aac -b:a 256k OUTPUT.mp4


You say you want to "extract audio from them (mp3 or ogg)". But what if the audio in the mp4 file is not one of those? you'd have to transcode anyway. So why not leave the audio format detection up to ffmpeg?

To convert one file:

ffmpeg -i videofile.mp4 -vn -acodec libvorbis audiofile.ogg

To convert many files:

for vid in *.mp4; do ffmpeg -i "$vid" -vn -acodec libvorbis "${vid%.mp4}.ogg"; done

You can of course select any ffmpeg parameters for audio encoding that you like, to set things like bitrate and so on.

Use -acodec libmp3lame and change the extension from .ogg to .mp3 for mp3 encoding.

If what you want is to really extract the audio, you can simply "copy" the audio track to a file using -acodec copy. Of course, the main difference is that transcoding is slow and cpu-intensive, while copying is really quick as you're just moving bytes from one file to another. Here's how to copy just the audio track (assuming it's in mp3 format):

ffmpeg -i videofile.mp4 -vn -acodec copy audiofile.mp3

Note that in this case, the audiofile format has to be consistent with what the container has (i.e. if the audio is AAC format, you have to say audiofile.aac). You can use the ffprobe command to see which formats you have, this may provide some information:

for file in *; do ffprobe $file 2>&1 |grep Audio; done

A possible way to automatically parse the audio codec and name the audio file accordingly would be:

for file in *mp4 *avi; do ffmpeg -i "$file" -vn -acodec copy "$file".ffprobe "$file" 2>&1 |sed -rn 's/.Audio: (...), ./\1/p'; done

Note that this command uses sed to parse output from ffprobe for each file, it assumes a 3-letter audio codec name (e.g. mp3, ogg, aac) and will break with anything different.


Encoding multiple files

You can use a Bash "for loop" to encode all files in a directory:

$ mkdir newfiles
$ for f in *.m4a; do ffmpeg -i "$f" -codec:v copy -codec:a libmp3lame -q:a 2 newfiles/"${f%.m4a}.mp3"; done


ffmpeg -i input.m4a -acodec libmp3lame -ab 128k output.mp3
m4a to mp3 conversion with ffmpeg and lame

A batch file version of the same command would be:
for f in *.m4a; do ffmpeg -i "$f" -acodec libmp3lame -ab 256k "${f%.m4a}.mp3"; done


Extract Single Image from a Video at Specified Frame

$ vf [ss][filename][outputFileName]
where vf is a custom bash script as follows:
$ ffmpeg -ss $1 -i $2 -qmin 1 -q:v 1 -qscale:v 2 -frames:v 1 -huffman optimal $3.jpg

ss offset = frame number divided by FPS of video = the decimal (in milliseconds) ffmpeg needs i.e. 130.5

Merge Multiple Videos

concat demuxer
$ cat mylist.txt
file '/path/to/file1'
file '/path/to/file2'
file '/path/to/file3'

$ ffmpeg -f concat -safe 0 -i mylist.txt -c copy output.mp4

Split a Video into Images

$ ffmpeg -i video.flv image%d.jpg

Convert Images into a Video

$ ffmpeg -f image2 -i image%d.jpg imagestovideo.mp4
$ ffmpeg -i image-%03d.png -c:v libx264 -pix_fmt yuv420p test.mp4
$ ffmpeg -r 1/5 -i image-%03d.png -c:v libx264 -vf fps=25 -pix_fmt yuv420p test.mp4

Convert Single Image into a Video

$ ffmpeg -loop 1 -i image.png -c:v libx264 -t 60 -pix_fmt yuv420p -vf scale=1920:1080 out.mp4

Convert non-sequentially named Images in a directory

$ ffmpeg -framerate 30 -pattern_type glob -i '*.jpeg' -c:v libx264 -pix_fmt yuv420p gan-1.mov

Convert image sequence of many different sizes and conform to specific frame size

$ ffmpeg -i image-%04d.jpg -c:v libx264 -pix_fmt yuv420p -vf "scale=max(1280\,a*720):max(1280\,720/a),crop=1280:720" test.mp4

Guarantee aspect ratio from image sequence

$ ffmpeg -i image-%04d.jpg -c:v libx264 -pix_fmt yuv420p -vf "scale=720:-2" test.mp4

Evaluate which ratio to apply for scaling, then scale with the requisite amount of padding

$ ffmpeg -i image-%04d.jpg -c:v libx264 -pix_fmt yuv420p -vf "scale=iw*min(1280/iw\,720/ih):ih*min(1280/iw\,720/ih), pad=1280:720:(1280-iw*min(1280/iw\,720/ih))/2:(720-ih*min(1280/iw\,720/ih))/2" test.mp4

1920 version

$ ffmpeg -i image-%04d.jpg -c:v libx264 -pix_fmt yuv420p -vf "scale=iw*min(1920/iw\,1080/ih):ih*min(1920/iw\,1080/ih), pad=1920:1080:(1920-iw*min(1920/iw\,1080/ih))/2:(1080-ih*min(1920/iw\,1080/ih))/2" test.mp4

Convert .mov (JPEG-A or other codec) to H264 .mp4

ffmpeg -i input.mov -vcodec libx264 -pix_fmt yuv420p output.mp4

Convert mp4 to webm

$ ffmpeg -i example.mp4 -f webm -c:v libvpx -b:v 1M -acodec libvorbis example.webm -hide_banner
more info

Simple FLAC convert

ffmpeg -i audio.xxx -c:a flac audio.flac

Mix Stereo to Mono

You can modify a video file directly without having to re-encode the video stream. However the audio stream will have to be re-encoded.
Left channel to mono: ffmpeg -i video.mp4 -map_channel 0.1.0 -c:v copy mono.mp4

Left channel to stereo:
ffmpeg -i video.mp4 -map_channel 0.1.0 -map_channel 0.1.0 -c:v copy stereo.mp4

If you want to use the right channel, write 0.1.1 instead of 0.1.0.

Trim End of file (mp3)

Here's a command line that will slice to 30 seconds without transcoding:
ffmpeg -t 30 -i inputfile.mp3 -acodec copy outputfile.mp3


To Encode or Re-encode ?

Do you need to cut video with re-encoding or without re-encoding mode? You can try to following below command.
Synopsis: ffmpeg -i [input_file] -ss [start_seconds] -t [duration_seconds] [output_file]

use ffmpeg cut mp4 video without re-encoding

Example:
ffmpeg -i source.mp4 -ss 00:00:05 -t 00:00:10 -c copy cut_video.mp4

use ffmpeg cut mp4 video with re-encoding

Example:
ffmpeg -i source.mp4 -ss 00:00:05 -t 00:00:10 -async 1 -strict -2 cut_video.mp4

If you want to cut off section from the beginning, simply drop -t 00:00:10 from the command

reduce filesize

Example:
ffmpeg -i input.mov -vcodec libx264 -crf 24 output.mp4

It reduced a 100mb video to 9mb.. Very little change in video quality.

Example:
ffmpeg -i video.mov -vf eq=saturation=0 -s 640x480 -c:v libx264 -crf 24 output.mp4

make a grayscale version and scale to 640x480

Convert MKV to MP4

ffmpeg -i file.mkv

check for streams that you want (video/audio). be sure to convert/specify DTS 6 channel audio stream

ffmpeg -i input.mkv -strict experimental -map 0:0 -map 0:1 -c:v copy -c:a:1 libmp3lame -b:a 192k -ac 6 output.mp4

Add Watermark overlay (png) to the center of a video

ffmpeg -i source.mov -i watermark.png -filter_complex "overlay=x=(main_w-overlay_w)/2:y=(main_h-overlay_h)/2" output.mp4

Concat a video with a reversed copy of itself for ping-pong looping effect

ffmpeg -i input.mp4 -filter_complex "[0:v]reverse,fifo[r];[0:v][r] concat=n=2:v=1 [v]" -map "[v]" output.mp4


more commands
http://www.catswhocode.com/blog/19-ffmpeg-commands-for-all-needs

@ishanjain28

This comment has been minimized.

Copy link

@ishanjain28 ishanjain28 commented Sep 17, 2017

This is super useful. Thanks a lot. :)

@jjgh

This comment has been minimized.

Copy link

@jjgh jjgh commented Sep 19, 2017

You're missing command lines from copying audio streams to other containers without re-encoding, which are among the most useful commands because you have no quality loss and can make a stream compatible with different devices! It's all in ffmpeg home page!

@vahotm

This comment has been minimized.

Copy link

@vahotm vahotm commented Nov 11, 2017

ffmpeg -i input.mp4 a-vn -acodec copy output.aac

You're welcome.

@protrolium

This comment has been minimized.

Copy link
Owner Author

@protrolium protrolium commented Feb 23, 2018

this is a bit disorganized and idiosyncratic to my usage. happy some of you are finding it useful. I need to go through and arrange it a bit better.

@smallfryy

This comment has been minimized.

Copy link

@smallfryy smallfryy commented Apr 2, 2018

This is awesome!

@thecodingchicken

This comment has been minimized.

Copy link

@thecodingchicken thecodingchicken commented May 24, 2018

This is really useful for batch processing! Thanks!

@zhibirc

This comment has been minimized.

Copy link

@zhibirc zhibirc commented Oct 12, 2018

Very handy, thanks a lot!

@AjeethRakkapan

This comment has been minimized.

Copy link

@AjeethRakkapan AjeethRakkapan commented Feb 11, 2019

I just have a doubt! How to differentiate a music and voice in a video file using FFMPEG?

I have a movie.mp4 file, I extracted the audio from the video file using FFMPEG (ffmpeg -i video.mp4 -c:a pcm_s16le audio.wav).

Now from the audio file I can get the waveform, is there any way that I can differentiate the music and the voice from the audio file in the waveform and is it a best way to differentiate? I need the start time and the end time of the music from the extracted audio file.

So, at the end I might be getting multiple or single music file from the audio file.

@gaol

This comment has been minimized.

Copy link

@gaol gaol commented Apr 3, 2019

awesome !!

@cpwnd

This comment has been minimized.

Copy link

@cpwnd cpwnd commented Apr 29, 2019

For anybody having problems with extracting audio using -vn -acodec copy: I used -map 0:a:0 -c copy instead. Make sure use the right stream specifiers (in the most cases it should be 0:a:0) and no accidentially different output file extension than in the source file.

@freeload101

This comment has been minimized.

Copy link

@freeload101 freeload101 commented May 18, 2019

find . -name "*.mp4" -maxdepth 1 -exec ffmpeg -i '{}' -vn -acodec libmp3lame '{}'.mp3 ;

use cuda

find . -name "*.mp4" -maxdepth 1 -exec ffmpeg -hwaccel cuvid -i '{}' -vn -acodec libmp3lame '{}'.mp3 ;

@riophae

This comment has been minimized.

Copy link

@riophae riophae commented Jun 20, 2019

Thanks! Very helpful.

@martin-kuenzel

This comment has been minimized.

Copy link

@martin-kuenzel martin-kuenzel commented Jul 13, 2019

regarding to this section

A possible way to automatically parse the audio codec and name the audio file accordingly would be:
for file in *mp4 *avi; do ffmpeg -i "$file" -vn -acodec copy "$file".ffprobe "$file" 2>&1 |sed -rn 's/.Audio: (...), ./\1/p'; done

Note that this command uses sed to parse output from ffprobe for each file, it assumes a 3-letter audio codec name (e.g. mp3, ogg, aac) and will break with anything different.

Inspired by your given example, the following command is the one I use now. With the modifications in the sed the 3-letter problem probably shouldn't be an issue anymore. (even though I haven't tried any other longer/shorter formats yet)

for file in *.mp4 *.avi; do ffmpeg -i "$file" -y -vn -acodec copy "$file".$(ffprobe "$file" 2>&1 | sed -nr 's/^.*Audio:\s*(\w+)\s*.*$/\1/p'); done

@emersonbrogadev

This comment has been minimized.

Copy link

@emersonbrogadev emersonbrogadev commented Aug 11, 2019

This is GOLD!

@wuhuanyu

This comment has been minimized.

Copy link

@wuhuanyu wuhuanyu commented Aug 31, 2019

You saved my life. Many times!

@Yene-Me

This comment has been minimized.

Copy link

@Yene-Me Yene-Me commented Oct 13, 2019

Great work, thank you

@EliasPereirah

This comment has been minimized.

Copy link

@EliasPereirah EliasPereirah commented Oct 31, 2019

Someone can help me?
I need to create an video from imagens, but i need to put a audio into this video too.
I could do this, but the video get an error when i upload it to YouTube. Is like the video ends before the audio, like was somethin a part.
I think to solve this i would have to kown the duration of the audio, but i didn't know how to do this.
Please, help me.
Sorry the bad english

@likeayaz

This comment has been minimized.

Copy link

@likeayaz likeayaz commented Nov 27, 2019

I am trying to use this code in my python code as I have to convert .mp3 file to .wav file.
Convert any MP3 file to WAV 16khz mono 16bit:
ffmpeg -i audio.mp3 -acodec pcm_s16le -ac 1 -ar 22050 out.wav

But I am getting this error

fmpeg -i audio.mp3 -acodec pcm_s16le -ac 1 -ar 22050 out.wav
^
SyntaxError: invalid syntax

could you help me out please??

@1c7

This comment has been minimized.

Copy link

@1c7 1c7 commented Dec 4, 2019

Thank you~

@CreamyCookie

This comment has been minimized.

Copy link

@CreamyCookie CreamyCookie commented Dec 30, 2019

Thank you @protrolium and @martin-kuenzel

for file in *.mp4 *.avi; do ffmpeg -i "$file" -y -vn -acodec copy "$file".$(ffprobe "$file" 2>&1 | sed -nr 's/^.*Audio:\s*(\w+)\s*.*$/\1/p'); done

Here's a script version of that command that you allows you to (optionally) enter file(s) or a glob pattern (extract-audio.sh or extract-audio.sh test.mp4 or extract-audio.sh a.mp4 bee.mkv or extract-audio.sh *.webm).

#!/usr/bin/env bash

# License: CC0 1.0 Universal (public domain)

files=( "$@" )

# no arguments given
if [ -z ${1+x} ]; then
    files=(*.webm *.mp4 *.avi *.mkv)
fi


declare -A codec_name_to_extension
codec_name_to_extension["vorbis"]="ogg"


for i in "${files[@]}"; do
    ext=$(ffprobe "$i" 2>&1 | sed -nr 's/^.*Audio:\s*(\w+)\s*.*$/\1/p')
    
    if [ ${codec_name_to_extension[$ext]+x} ]; then
        ext="${codec_name_to_extension[$ext]}"
    fi
    
    ffmpeg -i "$i" -y -vn -acodec copy "${i%.*}.${ext}"
done

It also deals with the one case I'm aware of where the ffprobe result causes errors with the extraction.

@Infinitay

This comment has been minimized.

Copy link

@Infinitay Infinitay commented Jan 3, 2020

I have a video with two audio streams that I wanted to extract the audio for; however, because there were two audio streams, I had to merge them into one. Did some googling and with the help of this Gist, I came up with a few solutions.

What didn't work for me initially

Resulted in an error

ffmpeg.exe -i '.\Desktop 2020.01.03 - 03.14.03.02.DVR.mp4' -filter_complex "[0:a]amerge=inputs=2[a]" -ac 2 -map 0:v -map "[a]" -acodec copy 'output.aac'

I can't remember exactly what the error was, but I believe it was something along the lines of not being able to use filtering and streamcopy. A shame because it was the first solution I found and was rather simple. I guess the reason it didn't work in my situation was because I was attempting to extract the audio while in the example the snippet was found in, they were going from mp4 -> mp4, no audio extraction.


Other solutions I have tried, though they were all identical in the grand scheme of things

Output 1

ffmpeg.exe -i '.\Desktop 2020.01.03 - 03.14.03.02.DVR.mp4' -vn -ss '00:04:20' -to '00:04:42' -c:v copy -acodec libmp3lame -ab 256k -b:a 160k -ac 2 -filter_complex amerge=inputs=2 'output1.mp3'

I tried manually specifying the codec to use as mp3, but honestly I don't remember why exactly. Looking back at this now, I noticed that I didn't need the video, had -vn so -c:v copy seemed unnecessary. Also, I was already specify the audio bitrate via ab 256k, so -b:a 160k was also unnecessary.


Output 2

ffmpeg.exe -i '.\Desktop 2020.01.03 - 03.14.03.02.DVR.mp4' -vn -ss '00:04:20' -to '00:04:42' -c:v copy -c:a mp3 -b:a 160k -ac 2 -filter_complex amerge=inputs=2 'output2.mp3'

Looking back at this now, I noticed that I didn't need the video, had -vn so -c:v copy seemed unnecessary. I don't know what urged me to not specify the codec to use, or why I used it in the first output. Nonetheless, I had to keep -b:a 160k here.

Question: What is the difference between -b:a <bitrate>k and ab <bitrate>k? Are they the same thing but different formatting? ie -bitrate:audio vs audiobitrate respectively.


Output 3

ffmpeg.exe -i '.\Desktop 2020.01.03 - 03.14.03.02.DVR.mp4' -vn -ss '00:04:20' -to '00:04:42' -acodec libmp3lame -ab 256k -b:a 160k -ac 2 -filter_complex amerge=inputs=2 'output3.mp3'

All the above carries on over to here, except that I changed the bitrate to 256k. Now that I am writing this post, I think I can clean this up more in the final output


Final Output

ffmpeg.exe -i '.\Desktop 2020.01.03 - 03.14.03.02.DVR.mp4' -vn -ss '00:04:20' -to '00:04:42' -acodec libmp3lame -ab 358k -ac 2 -filter_complex amerge=inputs=2 'output4.mp3'

Well, here we are. The final revision that works fine, except that I noticed the audio bitrate was 320 kbps instead of 358 kbps, which was the original video file's audio bitrate. Why is that? I think I could clean this up even further by not specifying the codec as I did not in Output 2 to condense the command.


Findings

I found that all of the audio extractions (Outputs 1-4), assuming I left them all at the same bitrate, completed at the same exact time, with the same exact properties. Is there a way I can make this simpler or perhaps more efficient?

I hope this helps anyone else that is new to ffmpeg or simply having trouble with merging multiple audio streams from one input into one audio stream, and extracting that audio stream into a mp3 or other audio format. Also, this example is specifically for 2 audio streams. If you have more, I haven't tried it myself yet, but I believe it should be as simple as changing the command to -ac <number-of-audio-streams> -filter_complex amerge=inputs=<number-of-audio-streams> in theory.

@baofeidyz

This comment has been minimized.

Copy link

@baofeidyz baofeidyz commented Jan 3, 2020

How to convert audio from DTS to AC3 when the video has two audio streams with ffmpeg?

@CreamyCookie

This comment has been minimized.

Copy link

@CreamyCookie CreamyCookie commented Jan 3, 2020

New version that extracts all audio streams (numbered sequentially, starting with 0, but no number is added if there's only one):

#!/usr/bin/env bash

# License: CC0 1.0 Universal (public domain)

files=( "$@" )

# no arguments given
if [ -z ${1+x} ]; then
    files=(*.webm *.mp4 *.avi *.mkv)
fi


declare -A codec_name_to_extension
codec_name_to_extension["vorbis"]="ogg"


for i in "${files[@]}"; do
    extensions=($(ffprobe "$i" 2>&1 | sed -nr 's/^.*Audio:\s*(\w+)\s*.*$/\1/p'))
    
    add_args=()
    n=0
    for ext in "${extensions[@]}"; do
        base_out="${i%.*}"
        if [[ "${#extensions[@]}" != "1" ]]; then
            base_out="${base_out}.$n"
        fi
        
        if [ ${codec_name_to_extension[$ext]+x} ]; then
            ext="${codec_name_to_extension[$ext]}"
        fi
        
        add_args+=(-map a:$n -c copy "${base_out}.${ext}")
        
        n=$((n+1))
    done
    ffmpeg -i "$i" -y -vn "${add_args[@]}"
done

The previous version didn't work when there were multiple audio streams. Maybe this helps you @baofeidyz

@bhavikpatel08

This comment has been minimized.

Copy link

@bhavikpatel08 bhavikpatel08 commented Mar 5, 2020

very useful! Thanks

@cdpadilla42

This comment has been minimized.

Copy link

@cdpadilla42 cdpadilla42 commented Apr 5, 2020

Just plane works! Thank you for this

@ShijianXu

This comment has been minimized.

Copy link

@ShijianXu ShijianXu commented May 8, 2020

Hi, this is very useful.
Besides, does anyone know how to filter videos that do not have audio or have silent audio?
Many thanks!

@yoonghm

This comment has been minimized.

Copy link

@yoonghm yoonghm commented May 9, 2020

I tried to extract mp3 from a video from SUBARU すばる. The extracted mp3 audio has noise in the beginning there was not from the original audio. Is there a way to overcome this?

@chaeya

This comment has been minimized.

Copy link

@chaeya chaeya commented May 13, 2020

It's very useful. Thanks

@BobRJacada

This comment has been minimized.

Copy link

@BobRJacada BobRJacada commented Aug 12, 2020

This is so simple, clear and useful that I'd say it's a work of art. Thanks!

@ScienceMatters

This comment has been minimized.

Copy link

@ScienceMatters ScienceMatters commented Aug 20, 2020

I'm having trouble converting from .mkv to .avi and being able to open in imageJ for editing purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.