209 lines
6.7 KiB
Python
209 lines
6.7 KiB
Python
import os
|
|
import sys
|
|
import traceback
|
|
import subprocess
|
|
|
|
def clearScreen():
|
|
os.system('cls' if os.name == 'nt' else 'clear')
|
|
|
|
def convertFilesInImport():
|
|
for filename in os.listdir('input'):
|
|
print(f"{getInputPath()}{filename}")
|
|
frame_rate_string = getFrameRate(f"{getInputPath()}{filename}")
|
|
width = int(getWidth(f"{getInputPath()}{filename}"))
|
|
height = int(getHeight(f"{getInputPath()}{filename}"))
|
|
frame_rate = eval(frame_rate_string)
|
|
print(f"Frame rate is: {frame_rate}")
|
|
print(f"Width is: {width}")
|
|
print(f"Height is: {height}")
|
|
if width > height:
|
|
bitrate = getRecommendedBitrateSetting(width,frame_rate)
|
|
else:
|
|
bitrate = getRecommendedBitrateSetting(height,frame_rate)
|
|
print(f"Recommended bitrate: {bitrate}")
|
|
current_bitrate = int(getBitrate(f"{getInputPath()}{filename}"))
|
|
if current_bitrate < bitrate:
|
|
print(f"Current bitrate of {current_bitrate} is less than recommended. Using {current_bitrate}")
|
|
|
|
print("Converting now...")
|
|
#os.path.splitext(filename)[0] gets ride of file extension
|
|
#yadiff is for deinterlace
|
|
|
|
#Windows and Linux have different nulls. Windows null and Linux /dev/null
|
|
FNULL = open(os.devnull, 'w')
|
|
ffmpegcmd_nvidia = getFfmpegExe() + " -i " + getInputPath() + filename + " -vf yadif -b " + str(bitrate) + " -minrate " + str(bitrate) + " -maxrate " + str(bitrate) + " -bufsize " + str(bitrate) + " -vcodec h264_nvenc " + getAudioSetting() + " -y " + getOutputPath() + os.path.splitext(filename)[0] + ".mp4"
|
|
|
|
# shell=True is not safe but needs used because I do not comma separate the commmand like:
|
|
# ["ffmpeg.exe", "-i", "etc"]
|
|
process = subprocess.Popen(ffmpegcmd_nvidia, stdout=FNULL, stderr=FNULL, shell=True)
|
|
process.communicate()[0]
|
|
if process.returncode != 0:
|
|
print("Using Nvidia gpu failed... Trying Intel.")
|
|
ffmpegcmd_intel = ffmpegcmd_nvidia.replace("h264_nvenc", "h264_qsv")
|
|
else:
|
|
continue
|
|
process = subprocess.Popen(ffmpegcmd_intel, stdout=FNULL, stderr=FNULL, shell=True)
|
|
process.communicate()[0]
|
|
if process.returncode != 0:
|
|
print("Using Intel gpu failed... Trying CPU.")
|
|
ffmpegcmd = ffmpegcmd_nvidia.replace("h264_qsv", "h264")
|
|
else:
|
|
continue
|
|
process = subprocess.Popen(ffmpegcmd, stdout=FNULL, stderr=FNULL, shell=True)
|
|
process.communicate()[0]
|
|
if process.returncode != 0:
|
|
raise Exception('There was an error running ffmpeg.')
|
|
|
|
def getFrameRate(file):
|
|
ffprobe_args = "-v 0 -of csv=p=0 -select_streams v:0 -show_entries stream=r_frame_rate"
|
|
ffprobe_exe = getFfprobeExe()
|
|
ffprobe_command = f"{ffprobe_exe} {ffprobe_args} {file}"
|
|
# popen then .read() allows setting stdout to a variable
|
|
return os.popen(ffprobe_command).read()
|
|
|
|
def getWidth(file):
|
|
ffprobe_args = "-v 0 -of csv=p=0 -select_streams v:0 -show_entries stream=width"
|
|
ffprobe_exe = getFfprobeExe()
|
|
ffprobe_command = f"{ffprobe_exe} {ffprobe_args} {file}"
|
|
# popen then .read() allows setting stdout to a variable
|
|
return os.popen(ffprobe_command).read()
|
|
|
|
def getHeight(file):
|
|
ffprobe_args = "-v 0 -of csv=p=0 -select_streams v:0 -show_entries stream=height"
|
|
ffprobe_exe = getFfprobeExe()
|
|
ffprobe_command = f"{ffprobe_exe} {ffprobe_args} {file}"
|
|
# popen then .read() allows setting stdout to a variable
|
|
return os.popen(ffprobe_command).read()
|
|
|
|
def getBitrate(file):
|
|
ffprobe_args = "-v 0 -of csv=p=0 -select_streams v:0 -show_entries stream=bit_rate"
|
|
ffprobe_exe = getFfprobeExe()
|
|
ffprobe_command = f"{ffprobe_exe} {ffprobe_args} {file}"
|
|
# popen then .read() allows setting stdout to a variable
|
|
return os.popen(ffprobe_command).read()
|
|
|
|
def getFfmpegPath():
|
|
if(sys.platform == "win32"):
|
|
return "ffmpeg\\windows"
|
|
elif(sys.platform == "darwin"):
|
|
return "ffmpeg/osx"
|
|
else:
|
|
# Linux sys.platform returns 'linux'
|
|
returnErrorAndExit("Your os is not supported. Try using Windows or OSX")
|
|
|
|
def getFfmpegExe():
|
|
path = getFfmpegPath()
|
|
if(sys.platform == "win32"):
|
|
return f"{path}\\ffmpeg.exe"
|
|
else:
|
|
return f"{path}/ffmpeg"
|
|
|
|
def getFfprobeExe():
|
|
path = getFfmpegPath()
|
|
if(sys.platform == "win32"):
|
|
return f"{path}\\ffprobe.exe"
|
|
else:
|
|
return f"{path}/ffprobe"
|
|
|
|
def getOutputPath():
|
|
if(sys.platform == "win32"):
|
|
return "output\\"
|
|
else:
|
|
return "output/"
|
|
|
|
def getInputPath():
|
|
if(sys.platform == "win32"):
|
|
return "input\\"
|
|
else:
|
|
return "input/"
|
|
|
|
# def askForResolution():
|
|
# inputresolution = "0"
|
|
# while(inputresolution != "1" and inputresolution != "2" and inputresolution != "3" and inputresolution != "4" and inputresolution != "5" and inputresolution != "6" and inputresolution != "7" and inputresolution != "8"):
|
|
# clearScreen()
|
|
# print("Tell me about your source video.")
|
|
# print("1. 4k at a slow frame rate (24, 25, 30)")
|
|
# print("2. 1080p at a slow frame rate (24, 25, 30)")
|
|
# print("3. 720p at a slow frame rate (24, 25, 30)")
|
|
# print("4. 480p at a slow frame rate (24, 25, 30)")
|
|
# print("5. 4k at a fast frame rate (48, 50, 60)")
|
|
# print("6. 1080p at a fast frame rate (48, 50, 60)")
|
|
# print("7. 720p at a fast frame rate (48, 50, 60)")
|
|
# print("8. 480p at a fast frame rate (48, 50, 60)")
|
|
# inputresolution = input("Please enter a number from above: ")
|
|
# return inputresolution
|
|
|
|
def askForAudioOutput():
|
|
audioOutput = "0"
|
|
while(audioOutput != "1" and audioOutput != "2" and audioOutput != "3" and audioOutput != "4"):
|
|
clearScreen()
|
|
print("Tell me what you would like your audio to output as.")
|
|
print("1. For no audio")
|
|
print("2. For Mono audio")
|
|
print("3. For Stereo audio")
|
|
print("4. For 5.1 audio")
|
|
audioOutput = input("Please enter a number from above: ")
|
|
return audioOutput
|
|
|
|
def getRecommendedBitrateSetting(longest_side,frame_rate):
|
|
# Bitrates recommended from YouTube: https://support.google.com/youtube/answer/1722171?hl=en
|
|
if frame_rate <= 30:
|
|
if longest_side > 1920:
|
|
# 4k size
|
|
# 40,000k bitrate
|
|
return 40000000
|
|
elif longest_side > 1280:
|
|
# 1080p size
|
|
# 8000k bitrate
|
|
return 8000000
|
|
elif longest_side > 852:
|
|
# 720p size
|
|
# 5000k bitrate
|
|
return 5000000
|
|
else:
|
|
# 480p size
|
|
# 2500k bitrate
|
|
return 2500000
|
|
else:
|
|
if longest_side > 1920:
|
|
# 4k size
|
|
# 55,000k bitrate
|
|
return 55000000
|
|
elif longest_side > 1280:
|
|
# 1080p size
|
|
# 12,000k bitrate
|
|
return 12000000
|
|
elif longest_side > 852:
|
|
# 720p size
|
|
# 7500k bitrate
|
|
return 7500000
|
|
else:
|
|
# 480p size
|
|
# 4000k bitrate
|
|
return 4000000
|
|
|
|
def getAudioSetting():
|
|
if(audio == "1"):
|
|
return " -an"
|
|
elif(audio == "2"):
|
|
return " -ab 128k"
|
|
elif(audio == "3"):
|
|
return " -ab 384k"
|
|
elif(audio == "4"):
|
|
return " -ab 512k"
|
|
|
|
|
|
def returnErrorAndExit(message):
|
|
input(message)
|
|
sys.exit(1)
|
|
|
|
#Run Program
|
|
try:
|
|
# resolution = askForResolution()
|
|
audio = askForAudioOutput()
|
|
convertFilesInImport()
|
|
input("Done. Press enter to exit.")
|
|
except Exception:
|
|
print(traceback.print_exc())
|
|
input("Press enter to exit.")
|
|
sys.exit(1) |