Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/bin/bash
- ffmpeg="$(command -v ffmpeg)"
- dest="/home/zefie/downloads/manual"
- ext=mkv # output ext
- fps=24 # video fps for tuning
- olddir="old" # where source files go when we are done (relative to $workdir)
- outdir="zefie" # where new files go when we are done (relative to $workdir)
- baddir="bad" # where files with decode errors end up (relative)
- ffmpeg_avg_br=5M
- ffmpeg_buf=8M
- ffmpeg_max_br=12M
- ffmpeg_aud_opts=(-b:a 320k)
- ffmpeg_mov_avg_br=10M
- ffmpeg_mov_buf=10M
- ffmpeg_mov_max_br=20M
- ffmpeg_mov_aud_opts=("${ffmpeg_aud_opts[@]}")
- vcodec=hevc
- acodec=aac
- ffmpeg_threads=4
- preset=hq
- twopass=true
- errchk=1
- delete=1
- use_nvidia=1 # comment/unset to disable
- use_nvidia_encoder=1 # ignored if use_nvidia unset
- use_nvidia_decoder=1 # ignored if use_nvidia unset
- REPLACE=( \
- "H.264|HEVC" \
- "x264|HEVC" \
- "NTb|zefie" \
- "QOQ|zefie" \
- "DDP5.1|AAC5.1" \
- "DD+2.0|AAC2.0" \
- )
- # end config
- ffmpeg_opts=()
- processed_count=0
- FILES=()
- if [ "${1}" == "movie" ]; then
- echo " [!!!] Executing in movie mode, using higher bitrates."
- ffmpeg_avg_br="${ffmpeg_mov_avg_br}";
- ffmpeg_buf="${ffmpeg_mov_buf}";
- ffmpeg_max_br="${ffmpeg_mov_max_br}";
- ffmpeg_aud_opts=("${ffmpeg_mov_aud_opts[@]}")
- shift;
- fi
- if [ "${1}" == "noerr" ]; then
- echo " [!!!] Executing in noerr mode, ffmpeg will NOT fail on minor errors!"
- errchk=
- shift;
- fi
- if [ "${1}" == "nomove" ]; then
- echo " [!!!] Executing in nomove mode, will not move failed files to ${baddir} !"
- nomove=1
- shift;
- fi
- if [ "${1}" == "nodel" ]; then
- echo " [!!!] Executing in old mode, will not delete files, will place them in ${olddir}"
- delete=
- shift;
- fi
- if [ -z "${1}" ] || [ ! -d "${1}" ]; then
- if [ ! -z "${1}" ] && [ -f "${1}" ]; then
- workdir="$(realpath "$(dirname "${1}")")"
- singlefile="$(realpath "${1}")"
- echo " [***] Single File Mode: ${singlefile} ..."
- else
- workdir="$(realpath "${PWD}")"
- fi
- else
- workdir="$(realpath "${1}")"
- fi
- echo " [***] Working in ${workdir} ..."
- if [ -z "${delete}" ]; then
- olddir="${workdir}/${olddir}";
- fi
- outdir="${workdir}/${outdir}"
- baddir="${workdir}/${baddir}"
- function detect_hw_encoder() {
- if [ -e "/dev/nvidia0" ] && [ ! -z "${use_nvidia}" ] && [ ! -z "${use_nvidia_encoder}" ]; then
- case "${vcodec}" in
- hevc)
- echo hevc_nvenc;
- ;;
- h264)
- echo h264_nvenc;
- ;;
- *)
- echo "${vcodec}";
- ;;
- esac
- else
- case "${vcodec}" in
- hevc)
- echo libx265;
- ;;
- h264)
- echo libx264;
- ;;
- *)
- echo "${vcodec}";
- ;;
- esac
- fi
- }
- function detect_hw_decoder() {
- local codec_data codec_res;
- codec_data="$(mediainfo --Inform="Video;%Format%" "${1}")"
- if [ -e "/dev/nvidia0" ] && [ ! -z "${use_nvidia}" ] && [ ! -z "${use_nvidia_decoder}" ]; then
- case "${codec_data}" in
- AVC)
- echo " [***] Using NVidia Accelerated H.264 Decoder" 1>&2
- codec_res=(-hwaccel cuvid -c:v h264_cuvid);
- ;;
- HEVC)
- echo " [***] Using NVidia Accelerated HEVC Decoder" 1>&2
- codec_res=(-hwaccel cuvid -c:v henc_cuvid);
- ;;
- MJPEG)
- echo " [***] Using NVidia Accelerated MJPEG Decoder" 1>&2
- codec_res=(-hwaccel cuvid -c:v mjpeg_cuvid);
- ;;
- MPEG1)
- echo " [***] Using NVidia Accelerated MPEG1 Decoder" 1>&2
- codec_res=(-hwaccel cuvid -c:v mpeg1_cuvid);
- ;;
- MPEG2)
- echo " [***] Using NVidia Accelerated MPEG2 Decoder" 1>&2
- codec_res=(-hwaccel cuvid -c:v mpeg2_cuvid);
- ;;
- MPEG4)
- echo " [***] Using NVidia Accelerated MPEG4 Decoder" 1>&2
- codec_res=(-hwaccel cuvid -c:v mpeg4_cuvid);
- ;;
- VC1)
- echo " [***] Using NVidia Accelerated VC1 Decoder" 1>&2
- codec_res=(-hwaccel cuvid -c:v vc1_cuvid);
- ;;
- VP8)
- echo " [***] Using NVidia Accelerated VP8 Decoder" 1>&2
- codec_res=(-hwaccel cuvid -c:v vp8_cuvid);
- ;;
- VP9)
- echo " [***] Using NVidia Accelerated VP9 Decoder" 1>&2
- codec_res=(-hwaccel cuvid -c:v vp9_cuvid);
- ;;
- *)
- echo " [***] Using Software Video Decoder" 1>&2
- codec_res=();
- ;;
- esac
- else
- echo " [***] Using Software Video Decoder" 1>&2
- codec_res=();
- fi
- echo "${codec_res[@]}"
- }
- function prepare_ffmpeg_opts() {
- local cuvid_dec ffmpeg_opts_in ffmpeg_opts_qual ffmpeg_opts_out codec ffmpeg_opts_audio_out ffmpeg_opts_in_generic;
- ffmpeg_opts_audio_out=(-c:a "${acodec}" "${ffmpeg_aud_opts[@]}")
- ffmpeg_opts_in_generic=(-y -loglevel warning -stats -threads "${ffmpeg_threads}")
- if [ ! -z "${errchk}" ]; then
- ffmpeg_opts_in_generic=("${ffmpeg_opts_in_generic[@]}" -xerror)
- fi
- codec=$(detect_hw_encoder);
- # shellcheck disable=SC2207
- cuvid_dec=($(detect_hw_decoder "${1}"));
- if [ "${codec}" = "hevc_nvenc" ]; then
- echo " [***] Using NVidia Accelerated HEVC Encoder" 1>&2
- ffmpeg_opts_in=("${ffmpeg_opts_in_generic[@]}" "${cuvid_dec[@]}")
- ffmpeg_opts_qual=(-preset "${preset}" -profile:v main -level:v 5.1 -2pass "${twopass}" -tier high -rc:v vbr_hq -b:v "${ffmpeg_avg_br}" -maxrate:v "${ffmpeg_max_br}" -bufsize:v "${ffmpeg_buf}" -g $((fps * 10)) -map 0 -movflags use_metadata_tags -movflags faststart)
- ffmpeg_opts_out=("${ffmpeg_opts_audio_out[@]}" -c:v "${codec}" "${ffmpeg_opts_qual[@]}" -f matroska)
- fi
- if [ "${codec}" = "libx265" ]; then
- echo " [***] Using Software x265 Encoder" 1>&2
- ffmpeg_opts_in=("${ffmpeg_opts_in_generic[@]}" "${cuvid_dec[@]}")
- ffmpeg_opts_qual=(-preset "${preset}" -tune grain -x265-params "'-no-scenecut=1:-2pass=${twopass}:-rc=vbr_hq:-rc-lookahead=${fps}:-surfaces=56'" -b:v "${ffmpeg_avg_br}" -maxrate:v "${ffmpeg_max_br}" -bufsize:v "${ffmpeg_buf}" -g $((fps * 10)) -map 0 -movflags use_metadata_tags -movflags faststart)
- ffmpeg_opts_out=("${ffmpeg_opts_audio_out[@]}" -c:v "${codec}" "${ffmpeg_opts_qual[@]}" -f matroska)
- fi
- ffmpeg_opts=("${ffmpeg_opts_in[@]}" -i "${1}" "${ffmpeg_opts_out[@]}" "${2}")
- }
- zcmd() {
- while [ ! -z "${1}" ]; do
- case "${1}" in
- silent)
- local SILENT=1;
- shift
- ;;
- errchk)
- local ERRCHK=1;
- shift
- ;;
- *)
- break;
- ;;
- esac
- done
- if [ -z ${SILENT} ]; then
- echo " [***] Executing: ${*}"
- fi
- "${@}";
- local RES=$?
- if [ ${RES} != 0 ] && [ ! -z ${ERRCHK} ]; then
- echo "exiting with error ${RES}"
- exit "${RES}"
- fi
- return ${RES}
- }
- function process_file() {
- local fname res;
- if [ -z "${ext}" ]; then
- ext="$(echo "${f}" | rev | cut -d'.' -f1 | rev)"
- fi
- fname="$(basename "${f}" | rev | cut -d'.' -f2- | rev)"
- # renaming for output
- for rep in "${REPLACE[@]}"; do
- rep1=$(echo "${rep}" | cut -d'|' -f1)
- rep2=$(echo "${rep}" | cut -d'|' -f2)
- # shellcheck disable=SC2001
- fname="$(echo "${fname}" | sed "s|${rep1}|${rep2}|")"
- unset rep1 rep2;
- done
- if [ ! -d "${outdir}" ]; then
- zcmd errchk mkdir "${outdir}"
- fi
- # shellcheck disable=SC2207
- prepare_ffmpeg_opts "${1}" "${outdir}/${fname}.${ext}"
- zcmd "${ffmpeg}" "${ffmpeg_opts[@]}"
- res=$?
- if [ ${res} -eq 0 ] && [ -f "${outdir}/${fname}.${ext}" ]; then
- if [ -z "${delete}" ]; then
- if [ ! -d "${olddir}" ]; then
- zcmd errchk mkdir "${olddir}"
- fi
- zcmd errchk mv -v "${f}" "${olddir}/$(basename "${f}")"
- else
- zcmd errchk rm -v "${f}"
- fi
- if [ ! -z "${dest}" ] && [ ! -z "${errchk}" ]; then
- # move to dest, if defined, and if not running in noerr mode
- mv -v "${outdir}/${fname}.${ext}" "$(realpath "${dest}")/${fname}.${ext}"
- fi
- else
- if [ "${res}" -ne 255 ]; then
- echo " [!!!] errors while encoding ${f}!"
- if [ -z "${nomove}" ]; then
- if [ ! -d "${baddir}" ]; then
- zcmd errchk mkdir "${baddir}"
- fi
- echo " Moving ${f} to ${baddir} ..."
- zcmd silent errchk mv "${f}" "${baddir}/$(basename "${f}")"
- fi
- echo " Removing incomplete encoding at ${outdir}/${fname}.${ext} ..."
- zcmd silent rm -f "${outdir}/${fname}.${ext}"
- else
- echo "exiting with error ${res}"
- exit ${res}
- fi
- fi
- processed_count=$((processed_count+1))
- }
- if [ -z "${singlefile}" ]; then
- while IFS= read -r -d '' file; do
- if [ -f "${file}" ]; then
- if [ "$(echo "${file}" | grep 'zefie\.' -c)" -eq 0 ]; then
- FILES=("${FILES[@]}" "${file}")
- fi
- fi
- done < <(find "${workdir}" -maxdepth 1 -regextype posix-extended -regex '.*\.(mp4|mkv)' -print0);
- else
- FILES=("${singlefile}")
- fi
- if [ "${#FILES[@]}" -gt 0 ]; then
- if [ -z "${singlefile}" ]; then
- # shellcheck disable=SC2207
- IFS=$'\n' sorted=($(sort <<<"${FILES[*]}")); unset IFS;
- FILES=("${sorted[@]}")
- unset sorted;
- echo -n " [***] Found ${#FILES[@]} file"
- if [ "${#FILES[@]}" -ne 1 ]; then
- echo -n "s";
- fi
- echo " ... processing now."
- fi
- for f in "${FILES[@]}"; do
- echo " [***] Processing ${f} (file $((processed_count+1)) of ${#FILES[@]}, $((${#FILES[@]}-processed_count-1)) remaining) ..."
- process_file "${f}"
- done
- else
- echo " [!!!] Did not find any files :("
- exit 1
- fi
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement