Files
gtav-src/tools_ng/bin/audio/FaceFx 2012/Scripts/render.py
T
2025-09-29 00:52:08 +02:00

176 lines
8.7 KiB
Python
Executable File

# This is a general render script that uses ffmpeg.exe. It requires that you create a
# "Render" folder in your My Documents/FaceFX Studio 20XX folder, and place ffmpeg.exe
# in there. You can set console variables to control how the script will behave (what
# camera to use, if you want to render out one animation, or an entire group, etc.)
# See the comments below for more info.
from FxStudio import *
from FxAnimation import *
import sys, os, time, math
def getRenderSetting(cvarName, defaultValue):
retVal = getConsoleVariableImpl(cvarName);
if None == retVal:
retVal = defaultValue
FxStudio.echo("setting console variable " + cvarName + " to " + str(retVal) )
return retVal
def getRenderSettingOptions(cvarName, defaultValue, options):
FxStudio.echo("Options for console variable " + cvarName + " include: " + str(options));
return getRenderSetting(cvarName, defaultValue)
def renderFaceFX():
# This is the output directory and where ffmpeg.exe is found.
# You need to create the Render folder manually.
# This should look something like: My Documents/FaceFX Studio 2010/Render
# Make sure you have write access to this folder!
userRenderDir = getConsoleVariable( "g_userdirectory") + "Render\\"
# ----------------------------------------------------------------------
# Settings. These are retrieved from console variables for easy access
# If no console variable is set, we provide default values.
# The getRenderSetting function takes the variable name as the first
# parameter and the default value you want to use if the variable is not
# yet set as the second parameter.
# ----------------------------------------------------------------------
outputDirectory = getRenderSetting( "r_outputdir", userRenderDir)
if not os.path.exists(outputDirectory):
outputDirectoryReturn = FxStudio.displayDirectorySelectionDialog('The default render folder ' + outputDirectory + ' did not exist. Select a Folder for temporary render files.')
outputDirectory = str(outputDirectoryReturn) + "\\"
if None == outputDirectoryReturn:
raise RuntimeError, "No render folder";
ffmpegdir = getRenderSetting( "r_ffmpegdir", userRenderDir)
FFMPEGFilePath = ffmpegdir + "ffmpeg.exe"
if not os.path.exists(FFMPEGFilePath):
FFMPEGFilePathReturn = FxStudio.displayFileOpenDialog("Locate FFMPEG.exe. It is not in the default location.", ffmpegdir, default_filename="ffmpeg.exe", file_must_exist=True)
FFMPEGFilePath = str(FFMPEGFilePathReturn)
if None == FFMPEGFilePathReturn:
raise RuntimeError, "No ffmpeg.exe";
# we can only render movies if ffmpeg is found.
renderMode = getRenderSettingOptions( "r_rendermode", "anim", ["anim", "group", "all"])
FPS = int(getRenderSetting( "r_fps", 20))
pixelW = int(getRenderSetting( "r_pixelw", 640))
pixelH = int(getRenderSetting( "r_pixelh", 480))
# Change these numbers to increase or decrease the quality of the movie. Higher quality is bigger file size.
# low quality - qmin = 10, qmax = 51
# high quality - qmin = 1, qmax = 51
qmin_setting = float(getRenderSetting( "r_compression_min", 7))
qmax_setting = float(getRenderSetting( "r_compression_max", 51))
imageFormat = getRenderSetting( "r_imageformat", "BMP")
# Change the extension here to render out a different type of movie (AVI, MPG, FLV, WMV, etc.)
movieFormat = getRenderSetting( "r_movieformat", "FLV")
# The default camera is used by not passing in an argument for the camera. The default is the
# camera selected when you initially open the scene. Use "Default_Render_Cam" to specify
# That nothing should be passed in.
camera = getRenderSetting( "r_camera", "Default_Render_Cam")
if camera == "Default_Render_Cam" and len(getCameraNames()) > 0:
camera = getSingleChoiceFromUser("Choose a camera from which to render:", "Camera Selection", getCameraNames())
if camera == "":
camera = "Default_Render_Cam"
facefxFilename = os.path.basename(FxStudio.getActorPath()).replace(".facefx", "")
# Create the output directory.
os.system("mkdir " + "\"" + outputDirectory + "\"")
screenshotFilename = outputDirectory + facefxFilename + "." + imageFormat
screenshot_folder = outputDirectory + "__temp__screenshots\\"
os.system("mkdir " + "\"" + screenshot_folder + "\"")
# Add quotes to the exe path
FFMPEGFilePath = "\"" + FFMPEGFilePath + "\""
filebase = "fx_render"
screenshot_file = screenshot_folder + filebase
selectedGroup = getSelectedAnimGroupName()
selectedAnim = getSelectedAnimName()
animationNames = getAnimationNames()
if getSelectedAnimName() == "" and renderMode == "anim":
raise RuntimeError, "No animation selected!"
for group in animationNames:
if (group[0] == selectedGroup) or renderMode == "all":
for animName in group[1]:
if (animName == selectedAnim) or renderMode == "all" or renderMode == "group":
outputFileName = facefxFilename + "_" + group[0] + "_" + animName + "." + movieFormat
outputMovie = "\"" + outputDirectory + outputFileName + "\""
selectAnimation(group[0], animName);
selectedAnim = Animation(group[0], animName);
# Unfortunately, ffmpg's itsoffset isn't working properly by letting us delay the audio by the amount
# that the animation starts before time 0. As a result, we need to start at 0, and "chop off" negative
# keys.
#animStartTime = selectedAnim.startTime
animStartTime = 0
animEndTime = selectedAnim.endTime
offsetTime = -animStartTime;
timestep = 1.0/FPS;
i = 0
t = animStartTime
paddedZeros = "000"
while t < animEndTime:
setCurrentTime(t)
t += timestep
if i > 9:
paddedZeros = "00"
if i > 99:
paddedZeros = "0"
if i > 999:
paddedZeros = ""
if camera != "Default_Render_Cam":
issueCommand('render -w "%s" -h "%s" -f "%s" -camera "%s" -fsaa 1;'%(pixelW, pixelH, screenshot_file + paddedZeros + str(i) + "." + imageFormat, camera))
else:
issueCommand('render -w "%s" -h "%s" -f "%s" -fsaa 1;'%(pixelW, pixelH, screenshot_file + paddedZeros + str(i) + "." + imageFormat))
i += 1
i -= 1
# replaceing relevant sections with this should work but it doesn't: imageFormat + "\" -itsoffset " + str(offsetTime) + " -i \""
# we use "call" to get around a problem with having spaces in the EXE name and argument names discussed here: http://bugs.python.org/issue1524
command = "call " + FFMPEGFilePath + " -r " + str(FPS) + " -y -f image2 -i " + "\"" + screenshot_file + "%04d." + imageFormat + "\" ";
if os.path.exists(selectedAnim.absoluteAudioAssetPath):
# we resample the audio with -ar 22050 because it is required for mp3-based output formates like FLV (11025 and 44100 work as well)
command += "-i \"" + selectedAnim.absoluteAudioAssetPath + "\" -ar 22050 "
command += "-qmin " + str(qmin_setting) + " -qmax " + str(qmax_setting) + " -r " + str(FPS) + " " + outputMovie ;
if os.system(command) == 1:
print "ffmpeg failed to convert the file. Make sure the file is not in use or write protected. The following is the command that failed:\n" + command
print "warning: some versions of ffmpeg report audio failure, but actually succeed in converting the audio."
#raise RuntimeError, "ffmpeg failed to convert the file."
else:
FxStudio.echo("Saved file: " + outputMovie);
#delete screenshot files. Only match the exact file pattern to avoid deleting important files
command = "del \"" +screenshot_folder + filebase + "*." + imageFormat + "\"";
os.system(command)
if renderMode == "anim":
retVal = getConsoleVariableImpl("r_saveFileName");
if None == retVal:
browseDialogFileReturn = FxStudio.displayFileSaveDialog("Move the file to a different location if you prefer.",outputDirectory, default_filename=outputFileName, wildcard="*."+movieFormat)
if None != browseDialogFileReturn:
browseDialogFile = str(browseDialogFileReturn)
command = "move " + outputMovie + " \"" + browseDialogFile + "\"";
os.system(command)
#this will fail if there are any files in it, so it is relatively safe regardless of how careless you get with this script.
os.rmdir(screenshot_folder)
if getSelectedAnimation()[1] == "":
errorBox("No animation selected! This script requires a selected animation to run.")
raise RuntimeError, "No animation is selected. Can not run script."
if isNoSave():
errorBox("This script can not be run from the no-save version of FaceFx Studio. It relies on the render command which saves files.")
raise RuntimeError, "No-save version can't use render command."
#Do the Render
renderFaceFX();