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
You can get the list of installed codecs with:
ffmpeg -codecs
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.
preferred method
ffmpeg -i INPUT.mp4 -i AUDIO.wav -shortest -c:v copy -c:a aac -b:a 256k OUTPUT.mp4
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
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
Rotate Video by editing metadata (without re-encoding).
ffmpeg -i input.m4v -map_metadata 0 -metadata:s:v rotate="90" -codec copy output.m4v
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
Simple FLAC convert
ffmpeg -i audio.xxx -c:a flac audio.flac
Merge Two Mono tracks into Stereo
ffmpeg -i left.wav -i right.wav -codec:a pcm_s16le -strict -2 -filter_complex "[0:a][1:a]amix" -ac 2 output.wav
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
Subdivide an audio file by time interval
ffmpeg -i file.wav -f segment -segment_time 5 -c copy out%03d.wav
add a filter to fade in / fade out the segments (created in the above command)
for i in *.wav; do ffmpeg -i "$i" -c pcm_s16le -af "afade=t=in:st=0:d=0.05,afade=t=out:st=0.9:d=0.1" "${i%.wav}-fade.wav"; done
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 MP4 to WEBM
ffmpeg -i input.mp4 -c:v libvpx-vp9 -crf 31 -b:v 1M output.webm
more info
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
Reverse a video
ffmpeg -i vid.mp4 -vf reverse reversed.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
Convert to different frame rate while preserving audio sync
ffmpeg -i <input> -filter:v fps=fps=30 <output>
Extract embeded subtitle track from mkv
ffmpeg -i input.mkv -map "0:m:language:eng" -map "-0:v" -map "-0:a" output.srt
more commands
http://www.catswhocode.com/blog/19-ffmpeg-commands-for-all-needs
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 viaab 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
andab <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.