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)