Files
camcorder-convert/ffmpeg-files.py

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)