└── ffmpeg ├── ffmpeg-post_process-clean_audio_noise.sh ├── ffmpeg-post_process-add_audio.sh ├── ffmpeg-convert-one_pass.sh └── ffmpeg-convert-two_pass.sh /ffmpeg/ffmpeg-post_process-clean_audio_noise.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -u 5 | set -o pipefail 6 | 7 | 8 | ### 9 | ### Check required tools 10 | ### 11 | if ! command -v ffmpeg >/dev/null 2>&1; then 12 | >&2 echo "Error, 'ffmpeg' binary required, but not found." 13 | exit 1 14 | fi 15 | 16 | 17 | ### 18 | ### Check command line arguments 19 | ### 20 | if [ "${#}" -ne "1" ]; then 21 | >&2 echo "Usage ${0} " 22 | exit 1 23 | fi 24 | if [ ! -f "${1}" ]; then 25 | >&2 echo "Usage ${0} " 26 | exit 1 27 | fi 28 | 29 | VIDEO="${1}" 30 | EXT="$( echo "${VIDEO}" | awk -F'.' '{print $NF}' )" 31 | 32 | # Reduce noise 33 | ffmpeg -nostdin -y \ 34 | -i "${VIDEO}" \ 35 | -af "afftdn=nf=-25" \ 36 | -c:v copy \ 37 | "${VIDEO}-reduced-noise.${EXT}" 38 | -------------------------------------------------------------------------------- /ffmpeg/ffmpeg-post_process-add_audio.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -u 5 | set -o pipefail 6 | 7 | 8 | ### 9 | ### How much volume of the audio track 10 | ### 11 | VOLUME=0.5 12 | 13 | 14 | 15 | ### 16 | ### Check required tools 17 | ### 18 | if ! command -v ffmpeg >/dev/null 2>&1; then 19 | >&2 echo "Error, 'ffmpeg' binary required, but not found." 20 | exit 1 21 | fi 22 | 23 | 24 | ### 25 | ### Check command line arguments 26 | ### 27 | if [ "${#}" -ne "2" ]; then 28 | >&2 echo "Usage ${0} " 29 | exit 1 30 | fi 31 | if [ ! -f "${1}" ]; then 32 | >&2 echo "Usage ${0} " 33 | exit 1 34 | fi 35 | if [ ! -f "${2}" ]; then 36 | >&2 echo "Usage ${0} " 37 | exit 1 38 | fi 39 | 40 | VIDEO="${1}" 41 | AUDIO="${2}" 42 | 43 | EXT="$( echo "${VIDEO}" | awk -F'.' '{print $NF}' )" 44 | 45 | 46 | # Add audio song to file 47 | ffmpeg -nostdin -y \ 48 | -i "${VIDEO}" \ 49 | -i "${AUDIO}" \ 50 | -filter_complex "[0:a]volume=3[a0];[1:a]volume=${VOLUME}[a1];[a0][a1]amerge=inputs=2[a]" \ 51 | -map 0:v \ 52 | -map "[a]" \ 53 | -c:v copy \ 54 | -ac 2 \ 55 | -shortest \ 56 | "${VIDEO}-song.${EXT}" 57 | -------------------------------------------------------------------------------- /ffmpeg/ffmpeg-convert-one_pass.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -u 5 | set -o pipefail 6 | 7 | 8 | 9 | ### 10 | ### ffmpeg definitions 11 | ### 12 | CRF=22 # Video quality 13 | AUDIO_KB=128 # Desired audio bitrate 14 | RESOLUTION=640 # Desired output resolution 15 | FRAMES=30 # Output frame rate 16 | PRESET=slow # FFMPEG preset (ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow) 17 | 18 | 19 | ### 20 | ### Check required tools 21 | ### 22 | if ! command -v ffmpeg >/dev/null 2>&1; then 23 | >&2 echo "Error, 'ffmpeg' binary required, but not found." 24 | exit 1 25 | fi 26 | if ! command -v ffprobe >/dev/null 2>&1; then 27 | >&2 echo "Error, 'ffprobe' binary required, but not found." 28 | exit 1 29 | fi 30 | 31 | 32 | ### 33 | ### Check command line arguments 34 | ### 35 | if [ "${#}" -ne "1" ]; then 36 | >&2 echo "Error, you must specify a file or directory." 37 | >&2 echo "Usage ${0} " 38 | exit 1 39 | fi 40 | if [ ! -f "${1}" ] && [ ! -d "${1}" ]; then 41 | >&2 echo "Error, '${1}' is not a file or directory." 42 | >&2 echo "Usage ${0} " 43 | exit 1 44 | fi 45 | DIRECTORY="${1}" 46 | 47 | 48 | ### 49 | ### Loop over files in directory and convert 50 | ### 51 | /bin/ls -1 "${DIRECTORY}" | grep -iE '\.(mov|avi|mp4)$' | while read -r filename; do 52 | 53 | # Show info 54 | echo "${filename} [len: ${SECONDS}sec | resolution: ${RESOLUTION}x | crf: ${CRF} | frames: ${FRAMES}]" 55 | 56 | ffmpeg -nostdin -y \ 57 | -i "${filename}" \ 58 | -preset ${PRESET} \ 59 | -movflags faststart \ 60 | \ 61 | -c:v libx265 \ 62 | -crf "${CRF}" \ 63 | \ 64 | -c:a aac \ 65 | -b:a ${AUDIO_KB}k \ 66 | \ 67 | -filter:a "volume=30dB" \ 68 | -filter:v "scale=${RESOLUTION}:-2:flags=lanczos, fps=fps=${FRAMES}" \ 69 | \ 70 | "${filename}-${RESOLUTION}-crf${CRF}-fps${FRAMES}.mp4" 71 | done 72 | -------------------------------------------------------------------------------- /ffmpeg/ffmpeg-convert-two_pass.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e 4 | set -u 5 | set -o pipefail 6 | 7 | 8 | 9 | ### 10 | ### ffmpeg definitions 11 | ### 12 | SIZE_MB=60 # End file size in MB 13 | AUDIO_KB=128 # Desired audio bitrate 14 | RESOLUTION=800 # Desired output resolution 15 | FRAMES=30 # Output frame rate 16 | PRESET=slow # FFMPEG preset (ultrafast, superfast, veryfast, faster, fast, medium, slow, slower, veryslow) 17 | 18 | 19 | ### 20 | ### Check required tools 21 | ### 22 | if ! command -v ffmpeg >/dev/null 2>&1; then 23 | >&2 echo "Error, 'ffmpeg' binary required, but not found." 24 | exit 1 25 | fi 26 | if ! command -v ffprobe >/dev/null 2>&1; then 27 | >&2 echo "Error, 'ffprobe' binary required, but not found." 28 | exit 1 29 | fi 30 | 31 | 32 | ### 33 | ### Check command line arguments 34 | ### 35 | if [ "${#}" -ne "1" ]; then 36 | >&2 echo "Error, you must specify a file or directory." 37 | >&2 echo "Usage ${0} " 38 | exit 1 39 | fi 40 | if [ ! -f "${1}" ] && [ ! -d "${1}" ]; then 41 | >&2 echo "Error, '${1}' is not a file or directory." 42 | >&2 echo "Usage ${0} " 43 | exit 1 44 | fi 45 | DIRECTORY="${1}" 46 | 47 | 48 | ### 49 | ### Loop over files in directory and convert 50 | ### 51 | /bin/ls -1 "${DIRECTORY}" | grep -iE '\.(mov|avi|mp4)$' | while read -r filename; do 52 | SECONDS="$( \ 53 | ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "${filename}" \ 54 | | grep -Eo '^[0-9]+' \ 55 | )" 56 | KBITS=$(( SIZE_MB * 8192 / SECONDS )) 57 | VIDEO_KB=$(( KBITS - AUDIO_KB )) 58 | 59 | # Show info 60 | echo "${filename} [len: ${SECONDS}sec | resolution: ${RESOLUTION}x | quality: ${VIDEO_KB}Kbit/s | frames: ${FRAMES}]" 61 | 62 | # Pass 1 63 | ffmpeg -nostdin -y \ 64 | -i "${filename}" \ 65 | -x265-params pass=1 \ 66 | -preset ${PRESET} \ 67 | \ 68 | -c:v libx265 \ 69 | -b:v ${VIDEO_KB}k \ 70 | \ 71 | -c:a aac \ 72 | -b:a ${AUDIO_KB}k \ 73 | \ 74 | -filter:v "scale=${RESOLUTION}:-2:flags=lanczos, fps=fps=${FRAMES}" \ 75 | \ 76 | -f mp4 /dev/null \ 77 | 78 | # Pass 2 79 | ffmpeg -nostdin -y \ 80 | -i "${filename}" \ 81 | -x265-params pass=2 \ 82 | -preset ${PRESET} \ 83 | -movflags faststart \ 84 | \ 85 | -c:v libx265 \ 86 | -b:v ${VIDEO_KB}k \ 87 | \ 88 | -c:a aac \ 89 | -b:a ${AUDIO_KB}k \ 90 | \ 91 | -filter:a "volume=30dB" \ 92 | -filter:v "scale=${RESOLUTION}:-2:flags=lanczos, fps=fps=${FRAMES}" \ 93 | \ 94 | "${filename}-${RESOLUTION}-size${SIZE_MB}-fps${FRAMES}.mp4" 95 | done 96 | --------------------------------------------------------------------------------