FFmpeg and SOX
common usage
ffmpeg -i input.mp4 -hide_banner # getting input file information
ffmpeg -i input.webm -qscale 0 output.mp4 # convert video preserving the quality of source video file
ffmpeg -formats # list all supported formats
ffmpeg -i input.mp4 -vn -ar 44100 -ac 2 -ab 320k -f mp3 output.mp3 # split audio vn: disable video. -ar audio frequency (common values 22050, 44100, 48000 Hz). -ac: number of audio channels. -ab: audio bitrate. -f: format.
ffmpeg -i input.mp3 -af 'volume=0.5' output.mp3 # decrease volume by half (use numbers greater than 1 to increase volume)
ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" output.mp4 # increase/decrease(0.5 double, 2 half) the video playback speed
ffmpeg -i input.mp4 -filter:a "atempo=2.0" -vn output.mp4 # Increase/decrease Audio playback speed (available value 0.5-2.0)
ffmpeg -i input.mp4 -filter:v scale=1280:720 -c:a copy output.mp4
ffmpeg -i input.mp4 -s 1280x720 -c:a copy output.mp4 # set a particular resolution
ffmpeg -i input.mp4 -vf scale=1280:-1 -c:v libx264 -preset veryslow -crf 24 -ac 2 -c:a aac -strict -2 -b:a 128k output.mp4 # reduce size and quality of output file
ffmpeg -i input.mp3 -ab 128 output.mp3 # reduce audio bitrate (available bitrates: 96, 112, 128, 160, 192, 256, 320kbps)
ffmpeg -i input.mp4 -an output.mp4 # remove audio
ffmpeg -i input.mp4 -vn output.mp3 # remove video
ffmpeg -i input.mp4 -r 1 -f image2 image-%2d.png # extract images -r: frame rate (image per second). -f: format. %2d name outputs image-01.png - image-99.png
ffmpeg -i input.mp4 -filter:v "crop=w:h:x:y" output.mp4 # crop video
ffmpeg -i input.mp4 -aspect 16:9 output.mp4 # set the aspect ratio (common ratios: 16:9, 4:3, 16:10, 5:4, 2:21:1, 2:35:1, 2:39:1)
ffmpeg -loop 1 -i inputimage.jpg -i inputaudio.mp3 -c:v libx264 -c:a aac -strict experimental -b:a 192k -shortest output.mp4 # add poster image to audio
ffmpeg -i input.mp4 -codec:v h264 -codec:a copy -ss 00:00:10.70 -t 01:10:52.26 output.mp4 # split a video from starting from 00:00:10.70 and end in 01:10:52.26
ffmeg -i vinput.mp4 -codec:v h264 -an -sn -dn -ss 00:05:00 -t 00:10:00 -i ainput.mp4 -codec:a mp3 -vn -ss 00:12:00 -t 00:17:00 output.mp4 # create output.mp4 using vinput.mp4 from 00:05:00 to 00:10:00 as video source and ainput.mp4 from 00:12:00 -t 00:17:00 as audio source
ffmpeg -f concat -safe 0 -i <PATH-TO-LIST> -c copy ouput
ffmpeg -i "concat:input1.mp4|input2.mp4|input3.mp4" -c copy output.mp4 # concatinating the files in list
fmpeg -i input.mp4 -i subtitle.srt -map 0 -map 1 -c copy -c:v libx264 -crf 23 -preset veryfast output.mp4
ffmpeg -i infile.mp4 -i infile.srt -c copy -c:s mov_text outfile.mp4 # add subtitle
ffmpeg -i input.mp4 -vf "transpose=1" output.mp4
ffmpeg -i input.mp4 -vf "transpose=clock" output.mp4 # rotate the given video by 90 degrees clockwise.
# 0. Rotate by 90 degrees counter-clockwise and flip vertically. This is the default.
# 1. Rotate by 90 degrees clockwise.
# 2. Rotate by 90 degrees counter-clockwise.
# 3. Rotate by 90 degrees clockwise and flip vertically.
metadata
ffmpeg -i in.mp4 -f ffmetadata in.txt # Save the global metadata to a text file
ffmpeg -i in.mp4 -c copy -map_metadata 0 -map_metadata:s:v 0:s:v -map_metadata:s:a 0:s:a -f ffmetadata in.txt # Save metadata from the video and audio streams
ffprobe -show_streams -show_format input.mkv # Use ffprob for information
ffprobe -show_frames input.mkv # Use ffprobe or information about each single frame in a video file
ffmpeg -i source.mp4 -metadata album_artist='VAR' -c copy output.mp4 # Set metadata
find /home/user/videos-to-process/ -type f -iname '*.mp4' -exec ffmpeg -i "{}" -codec copy -metadata artist="John Smith" -metadata album="Foo Bar" "{}.new.mp4" \; -exec mv "{}.new.mp4" "{}" \; # set metadata
lbry preferred format
ffmpeg -i input.avi -c:v libx264 -crf 21 -preset faster -pix_fmt yuv420p -maxrate 5000K -bufsize 5000K -vf 'scale=if(gte(iw\,ih)\,min(1920\,iw)\,-2):if(lt(iw\,ih)\,min(1920\,ih)\,-2)' -movflags +faststart -c:a aac -b:a 160k output.mp4
convert a PDF to video
convert -density 400 input.pdf picture.png # convert PDF to picture-1.png, ...
ffmpeg -r 1/10 -i picture-%01d.png -c:v libx264 -r 30 -pix_fmt yuv420p video.mp4 # -r 1/10: Display each image for 10 seconds.
noise reduction using sox
#!/usr/bin/env bash
usage ()
{
echo 'Usage : noiseclean.sh <input video file> <output video file>'
exit
}
# Tests for requirements
ffmpeg -version >/dev/null || { echo >&2 "We require 'ffmpeg' but it's not installed. Install it by 'sudo apt-get install ffmpeg' Aborting."; exit 1; }
sox --version >/dev/null || { echo >&2 "We require 'sox' but it's not installed. Install it by 'sudo apt-get install sox' Aborting."; exit 1; }
if [ "$#" -ne 2 ]
then
usage
fi
if [ ! -e "$1" ]
then
echo "File not found: '$1'"
exit
fi
if [ -e "$2" ]
then
read -p "File '$2' already exists, overwrite? [y/N]: " yn
case $yn in
[Yy]* ) break;;
* ) exit;;
esac
fi
inBasename=$(basename "$1")
inExt="${inBasename##*.}"
isVideoStr=`ffprobe -v warning -show_streams "$1" | grep codec_type=video`
if [[ ! -z $isVideoStr ]]
then
isVideo=1
echo "Detected '$inBasename' as a video file"
else
isVideo=0
echo "Detected '$inBasename' as an audio file"
fi
read -p "Sample noise start time [00:00:00]: " sampleStart
if [[ -z $sampleStart ]] ; then sampleStart="00:00:00"; fi
read -p "Sample noise end time [00:00:00.500]: " sampleEnd
if [[ -z $sampleEnd ]] ; then sampleEnd="00:00:00.500"; fi
read -p "Noise reduction amount [0.21]: " sensitivity
if [[ -z $sensitivity ]] ; then sensitivity="0.21"; fi
tmpVidFile="/tmp/noiseclean_tmpvid.$inExt"
tmpAudFile="/tmp/noiseclean_tmpaud.wav"
noiseAudFile="/tmp/noiseclean_noiseaud.wav"
noiseProfFile="/tmp/noiseclean_noise.prof"
tmpAudCleanFile="/tmp/noiseclean_tmpaud-clean.wav"
echo "Cleaning noise on '$1'..."
if [ $isVideo -eq "1" ]; then
ffmpeg -v warning -y -i "$1" -qscale:v 0 -vcodec copy -an "$tmpVidFile"
ffmpeg -v warning -y -i "$1" -qscale:a 0 "$tmpAudFile"
else
cp "$1" "$tmpAudFile"
fi
ffmpeg -v warning -y -i "$1" -vn -ss "$sampleStart" -t "$sampleEnd" "$noiseAudFile"
sox "$noiseAudFile" -n noiseprof "$noiseProfFile"
sox "$tmpAudFile" "$tmpAudCleanFile" noisered "$noiseProfFile" "$sensitivity"
if [ $isVideo -eq "1" ]; then
ffmpeg -v warning -y -i "$tmpAudCleanFile" -i "$tmpVidFile" -vcodec copy -qscale:v 0 -qscale:a 0 "$2"
else
cp "$tmpAudCleanFile" "$2"
fi
echo "Done"
booksplit
#!/bin/sh
# Requires ffmpeg (audio splitting) and my `tag` wrapper script.
[ ! -f "$2" ] && printf "The first file should be the audio, the second should be the timecodes.\
" && exit
echo "Enter the album/book title:"; read -r booktitle
echo "Enter the artist/author:"; read -r author
echo "Enter the publication year:"; read -r year
inputaudio="$1"
# Get a safe file name from the book.
escbook="$(echo "$booktitle" | iconv -cf UTF-8 -t ASCII//TRANSLIT | tr -d '[:punct:]' | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | sed "s/-\+/-/g;s/\(^-\|-\$\)//g")"
! mkdir -p "$escbook" && echo "Do you have write access in this directory?" && exit 1
# As long as the extension is in the tag script, it'll work.
ext="opus"
#ext="${1#*.}"
# Get the total number of tracks from the number of lines.
total="$(wc -l < "$2")"
while read -r x;
do
end="$(echo "$x" | cut -d' ' -f1)"
[ -n "$start" ] &&
echo "From $start to $end; $track $title"
file="$escbook/$(printf "%.2d" "$track")-$esctitle.$ext"
[ -n "$start" ] && echo "Splitting \"$title\"..." &&
ffmpeg -nostdin -y -loglevel -8 -i "$inputaudio" -ss "$start" -to "$end" -vn -c copy "$file" &&
echo "Tagging \"$title\"..." && tag -a "$author" -A "$booktitle" -t "$title" -n "$track" -N "$total" -d "$year" "$file"
title="$(echo "$x" | cut -d' ' -f 2-)"
esctitle="$(echo "$title" | iconv -cf UTF-8 -t ASCII//TRANSLIT | tr -d '[:punct:]' | tr '[:upper:]' '[:lower:]' | tr ' ' '-' | sed "s/-\+/-/g;s/\(^-\|-\$\)//g")"
track="$((track+1))"
start="$end"
done < "$2"
# The last track must be done outside the loop.
echo "From $start to the end: $title"
file="$escbook/$(printf "%.2d" "$track")-$esctitle.$ext"
echo "Splitting \"$title\"..." && ffmpeg -nostdin -y -loglevel -8 -i "$inputaudio" -ss "$start" -vn -c copy "$file" &&
echo "Tagging \"$title\"..." && tag -a "$author" -A "$booktitle" -t "$title" -n "$track" -N "$total" -d "$year" "$file"
tag script
#!/bin/sh
err() { echo "Usage:
tag [OPTIONS] file
Options:
-a: artist/author
-t: song/chapter title
-A: album/book title
-n: track/chapter number
-N: total number of tracks/chapters
-d: year of publication
-g: genre
-c: comment
You will be prompted for title, artist, album and track if not given." && exit 1 ;}
while getopts "a:t:A:n:N:d:g:c:f:" o; do case "${o}" in
a) artist="${OPTARG}" ;;
t) title="${OPTARG}" ;;
A) album="${OPTARG}" ;;
n) track="${OPTARG}" ;;
N) total="${OPTARG}" ;;
d) date="${OPTARG}" ;;
g) genre="${OPTARG}" ;;
c) comment="${OPTARG}" ;;
f) file="${OPTARG}" ;;
*) printf "Invalid option: -%s\
" "$OPTARG" && err ;;
esac done
shift $((OPTIND - 1))
file="$1"
[ ! -f "$file" ] && echo "Provide file to tag." && err
[ -z "$title" ] && echo "Enter a title." && read -r title
[ -z "$artist" ] && echo "Enter an artist." && read -r artist
[ -z "$album" ] && echo "Enter an album." && read -r album
[ -z "$track" ] && echo "Enter a track number." && read -r track
case "$file" in
*.ogg) echo "Title=$title
Artist=$artist
Album=$album
Track=$track
Total=$total
Date=$date
Genre=$genre
Comment=$comment" | vorbiscomment -w "$file" ;;
*.opus) echo "Title=$title
Artist=$artist
Album=$album
Track=$track
Total=$total
Date=$date
Genre=$genre
Comment=$comment" | opustags -i -S "$file" ;;
*.mp3) eyeD3 -Q --remove-all -a "$artist" -A "$album" -t "$title" -n "$track" -N "$total" -Y "$date" "$file" ;;
*) echo "File type not implemented yet." ;;
esac
use
booksplit path/to/audio path/to/timecodefile
timecodefile:
00:00:00 first part name hh:mm:ss second part name …
filters
frozen frames with mpdecimate
ffmpeg -i input.mkv -vf mpdecimate,setpts=N/FRAME_RATE/TB -an output.mkv # remove frozen frames
ffmpeg -hide_banner -nostats -an -i $IN -vf "freezedetect=n=${NOISE}dB:d=${DURATION}" -f null - 2>&1 | grep -e "freeze_start" -e "freeze_end" # detect frozen frames
video stabliser vidstabs
ffmpeg -i input.mp4 -vf vidstabdetect -f null - # Use default values
ffmpeg -i input.mp4 -vf vidstabdetect=shakiness=10:accuracy=15:result="mytransforms.trf" -f null - # Analyzing strongly shaky video and putting the results in file mytransforms.trf
ffmpeg -i input.mp4 -vf vidstabdetect=show=1 dummy_output.mp4 # Visualizing the result of internal transformations in the resulting video
ffmpeg -i input.mp4 -vf vidstabdetect=shakiness=5:show=1 dummy_output.mp4 # Analyzing a video with medium shakiness
ffmpeg -i input.mp4 -vf vidstabtransform,unsharp=5:5:0.8:3:3:0.4 out_stabilized.mp4 # Using default values
ffmpeg -i input.mp4 -vf vidstabtransform=zoom=5:input="mytransforms.trf" out_stabilized.mp4 # Zooming-in a bit more and load transform data from a given file
ffmpeg -i input.mp4 -vf vidstabtransform=smoothing=30:input="mytransforms.trf" out_stabilized.mp4 # Smoothening the video even more