Skip to content

Commit

Permalink
Optimized and rewritten some code, added a bunch
Browse files Browse the repository at this point in the history
bunch of fallbacks in case stuff fails
  • Loading branch information
JeffersonTan committed Mar 27, 2024
1 parent d943f34 commit 0b4d02f
Showing 1 changed file with 166 additions and 17 deletions.
183 changes: 166 additions & 17 deletions main.sh
Original file line number Diff line number Diff line change
@@ -1,52 +1,201 @@
#!/bin/bash

echo Welcome to my simple ffmpeg GPU accelerator thingy
# Colour formatting stuff
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# Script description
echo Welcome to my ffmpeg GPU accelerator thingy

# This part checks if lshw is installed or not
if command -- lshw >/dev/null 2>&1; then
echo -e "${GREEN}lshw is installed\n${NC}"
else
echo -e "${RED}lshw not found, please install lshw before running this script.\n${NC}"
exit 1
fi

echo "--------------------"

# Lists out GPU in a system, ignores errors about the command running in non-sudo mode, then filters out the vendors
listGPU=$( (lshw -C video) 2>/dev/null | awk '$1=="vendor:"{$1=""; print}')

declare -i GPUType
GPUType=0

# Function for detecting intel GPU to avoid duplicated codes
detect_intel () {
# echo -e "${BLUE}Intel${NC} GPU detected"
Intel=true
GPUType+=1
}

# Logic for checking which GPU exists in system
if (grep NVIDIA <<< $listGPU) 1>/dev/null ; then
# echo -e "${GREEN}NVIDIA${NC} GPU detected"
Nvidia=true
GPUType+=5
elif (grep Intel <<< $listGPU) 1>/dev/null ; then
detect_intel
fi

if (grep AMD <<< $listGPU) 1>/dev/null ; then
# echo -e "${RED}AMD${NC} GPU detected"
AMD=true
GPUType+=3
elif (grep Intel <<< $listGPU) 1>/dev/null ; then
detect_intel
else
echo Unknown GPU
fi

case $GPUType in
1)
echo -e "Only ${BLUE}Intel${NC} GPU detected, possibly integrated graphics or Intel Arc"
;;
3)
echo -e "Only ${RED}AMD${NC} GPU detected, probably an AMD-only system."
;;
4)
echo -e "${BLUE}Intel${NC} and ${RED}AMD${NC} detected, probably a system with an Intel processor with iGPU and AMD graphics."
;;
5)
echo -e "Only ${GREEN}Nvidia${NC} GPU detected. Possibly a system with a single dedicated Nvidia graphics."
;;
6)
echo -e "${BLUE}Intel${NC} and ${GREEN}Nvidia${NC} detected, possibly a hybrid system like a laptop."
;;
8)
echo -e "${RED}AMD${NC} and ${GREEN}Nvidia${NC} detected, probably a system with AMD APU and Nvidia GPU."
;;
*)
echo "Unknown system type"
;;
esac

echo -e "--------------------\n"

read -p 'Please type input name here: ' inputfile
read -p 'Please type output name here (without extensions): ' outputfile

PS3=$'Which video codec do you want to use?\n'
# Video codec choice
PS3=$'Which video codec do you want to use? (Make sure your hardware supports it!)\n'
select vidcodecchoice in h264 hevc
do
case $vidcodecchoice in
h264)
printf "$vidcodecchoice selected\n"
vidcodec=${vidcodecchoice}_vaapi
break
;;
hevc)
printf "$vidcodecchoice selected\n"
vidcodec=${vidcodecchoice}_vaapi
break
;;
*)
echo "Invalid option"
echo $RED "Invalid option" $NC
;;
esac
done

# Video quality choice
read -p 'Please enter your desired video quality (CQP): ' vidqual
eval $(ffprobe -v quiet -select_streams a:0 -of flat=s=_ -show_entries stream=codec_name "$inputfile")

# This part checks whether or not $inputfile has mp3 or aac audio codec already. If it does, then it'll just copy the audio stream over to avoid re-encoding.
eval $(ffprobe -v quiet -select_streams a:0 -of flat=s=_ -show_entries stream=codec_name "$inputfile")
if [[ $streams_stream_0_codec_name == "mp3" || $streams_stream_0_codec_name == "aac" ]]; then
audcodec="copy"
else
read -p 'Please enter your desired audio quality (bitrate): ' audqual
audcodec="aac -b:a $audqual"
fi

# Change resolution choice
printf "Do you want to change resolutions?\n"
read changeres

if [ $changeres == yes ]; then
printf "\n"
read -p "enter the width here: " vidwidth
read -p 'enter the height here: ' vidheight
vidfilter="format=nv12,hwupload,deinterlace_vaapi=rate=field:auto=1,scale_vaapi=w=$vidwidth:h=$vidheight"
elif [ $changeres == no ]; then
vidfilter="format=nv12,hwupload,deinterlace_vaapi=rate=field:auto=1"
else
printf "Unknown parameter"
fi
resChange () {
if [[ $changeres == yes || $changeres == y ]]; then
printf "\n"
read -p "enter the width here: " vidwidth
read -p "enter the height here: " vidheight
vidfilterVAAPI="-vf format=nv12,hwupload,deinterlace_vaapi=rate=field:auto=1,scale_vaapi=w=$vidwidth:h=$vidheight"
vidfilterQSV="-vf format=qsv,hwupload,deinterlace_qsv,scale_qsv=w=$vidwidth:h=$vidheight"
vidfilterCUDA="-vf format=cuda,hwupload,yadif_cuda=deint=interlaced,scale_cuda=w=$vidwidth:h=$vidheight"
elif [[ $changeres == no || $changeres == n ]]; then
vidfilterVAAPI="-vf format=nv12,hwupload,deinterlace_vaapi=rate=field:auto=1"
vidfilterQSV="-vf format=qsv,hwupload,deinterlace_qsv"
vidfilterCUDA="-vf format=cuda,hwupload,yadif_cuda=deint=interlaced"
else
printf "Unknown parameter"
fi
}

# Choose encoder type based on detected GPUs
encType () {
case $GPUType in
1) # Intel GPU
hwEncode="$vidfilterQSV -c:v ${vidcodecchoice}_qsv -global_quality $vidqual"
hwDecode="-hwaccel qsv -hwaccel_output_format qsv -vcodec ${vidcodecchoice}_qsv"
;;
3 | 4) # AMD GPU
hwEncode="$vidfilterVAAPI ${vidcodecchoice}_vaapi -rc_mode CQP -qp $vidqual"
hwDecode="-vaapi_device /dev/dri/renderD128"
;;
5 | 6 | 8) # Nvidia GPU
hwEncode="$vidfilterCUDA -c:v ${vidcodecchoice}_nvenc -cq $vidqual"
hwDecode="-hwaccel cuda -hwaccel_output_format cuda"
;;
*)
echo "Something went wrong!"
exit 1
;;
esac
}

# Final command for running ffmpeg
run_ffmpeg () {
resChange
encType
ffmpeg -hide_banner $hwDecode -i "$inputfile" $hwEncode -fps_mode passthrough -c:a $audcodec "$outputfile.mp4"
}

on_error() {
echo -e "${RED}Exit code: $?${NC}"
if [[ $GPUType == 6 || ! $? == 0 ]] ; then
read -p "Oh no! Nvidia transcoding failed! Do you want to try again with Intel QSV? " tryIntel
case $tryIntel in
[Yy][Ee][Ss] | [Yy] | [Tt][Rr][Uu][Ee] | [Tt])
GPUType=1
echo ""
run_ffmpeg || on_error "Error occured!"
;;
[Nn][Oo] | [Nn] | [Ff][Aa][Ll][Ss][Ee] | [Ff])
echo "Goodbye!"
exit 0
;;
*)
echo "Invalid input: $tryIntel"
;;
esac
elif [[ $GPUType == 8 || ! $? == 0 ]] ; then
read -p "Oh no! Nvidia transcoding failed! Do you want to try again with Intel QSV? " tryAMD
case $tryAMD in
[Yy][Ee][Ss] | [Yy] | [Tt][Rr][Uu][Ee] | [Tt])
GPUType=3
echo ""
run_ffmpeg || on_error "Error occured!"
;;
[Nn][Oo] | [Nn] | [Ff][Aa][Ll][Ss][Ee] | [Ff])
echo "Goodbye!"
exit 0
;;
*)
echo "Invalid input: $tryAMD"
;;
esac
fi
}

ffmpeg -vaapi_device /dev/dri/renderD128 -i "$inputfile" -vf $vidfilter -c:v $vidcodec -fps_mode passthrough -rc_mode CQP -qp $vidqual -c:a $audcodec "$outputfile.mp4"
run_ffmpeg || on_error "Error occured!"

0 comments on commit 0b4d02f

Please sign in to comment.