import hou
import os
import subprocess

def playblast(path, name):

    ffmpeg_path = "C:/ffmpeg/bin/ffmpeg.exe"

    if not os.path.exists(path):
        os.makedirs(path)
        
    padding = 4
    frames_dir = os.path.join(path, "frames")
    
    if not os.path.exists(frames_dir):
        os.makedirs(frames_dir)
    
    playblast_output = os.path.join(frames_dir, "{0}.$F{1}.png".format(name, padding))
    quicktime_output = os.path.join(path, "{0}.mp4".format(name))

    
    start_frame = int(hou.playbar.frameRange()[0])
    end_frame = int(hou.playbar.frameRange()[1])
    
    desktop = hou.ui.curDesktop()
    viewport_panel = desktop.paneTabOfType(hou.paneTabType.SceneViewer)
    
    viewport = viewport_panel.curViewport()

    if viewport.type() == hou.geometryViewportType.Perspective:
        camera_path = viewport.cameraPath()
        if camera_path:
            active_cam = hou.node(camera_path)

    width = 1920
    height = 1080
    
    if active_cam:
        width = int(active_cam.evalParm("resx"))
        height = int(active_cam.evalParm("resy"))

    scene = viewport_panel
    scene.flipbookSettings().stash()
    flip_book_options = scene.flipbookSettings()
    
    flip_book_options.output(playblast_output)
    flip_book_options.frameRange((start_frame, end_frame))
    flip_book_options.useResolution(1)
    flip_book_options.resolution((width, height))
    scene.flipbook(scene.curViewport(), flip_book_options)
    
    normalized_frames_dir = frames_dir.replace("\\\\", "/")
    normalized_quicktime_output = quicktime_output.replace("\\\\", "/")
    
    source_path = "{0}/{1}.%{2:02d}d.png".format(normalized_frames_dir, name, padding)
    
    framerate = hou.fps()
    crf = 18
    preset = "fast"
    
    ffmpeg_cmd = ffmpeg_path
    ffmpeg_cmd += ' -y -framerate {0} -start_number {1} -i "{2}"'.format(framerate, str(start_frame), source_path)
    ffmpeg_cmd += ' -c:v libx264 -crf:v {0} -preset:v {1} -profile high -level 4.0 -pix_fmt yuv420p'.format(crf, preset)
    ffmpeg_cmd += ' "{0}"'.format(quicktime_output)
   
    gif_output = os.path.join(path, "{0}.gif".format(name))
    normalized_gif_output = gif_output.replace("\\\\", "/")
    
    # FFmpeg command for GIF creation - using the same source frames
    gif_cmd = ffmpeg_path
    gif_cmd += ' -y -framerate {0} -start_number {1} -i "{2}"'.format(framerate, str(start_frame), source_path)
    gif_cmd += ' -vf "fps=24,format=yuv420p"'
    gif_cmd += ' "{0}"'.format(normalized_gif_output)
    
    print("Executing: " + ffmpeg_cmd)
    try:
        subprocess.call(ffmpeg_cmd, shell=True)
        print("Successfully created: " + quicktime_output)
        return quicktime_output
    except Exception as e:
        print("Error executing ffmpeg: " + str(e))
        return None
    
name = "test"
path = "C:/temp"
playblast(path, name)

Versioned with gif

kind of versioned

import hou
import os
import subprocess

def playblast(path, name, version_up=True):

    ffmpeg_path = "O:/users/cooper.johnstone/assets/apps/ffmpeg/ffmpeg.exe"
    
    if not os.path.exists(ffmpeg_path):
        print("ffmpeg path dosnt exist")
        return

    if not os.path.exists(path):
        os.makedirs(path)
    
    versions = sorted(os.listdir(path))
    
    if versions:
        latest_version = int(versions[-1])
        if version_up == True:
            path = os.path.join(path, str(latest_version+1))
        else:
            path = os.path.join(path, str(latest_version))
    else:
        path = os.path.join(path, str(1))

    padding = 4
    frames_dir = os.path.join(path, "frames")
    
    if not os.path.exists(frames_dir):
        os.makedirs(frames_dir)
    
    playblast_output = os.path.join(frames_dir, "{0}.$F{1}.png".format(name, padding))
    quicktime_output = os.path.join(path, "{0}.mp4".format(name))

    
    start_frame = int(hou.playbar.frameRange()[0])
    end_frame = int(hou.playbar.frameRange()[1])
    
    desktop = hou.ui.curDesktop()
    viewport_panel = desktop.paneTabOfType(hou.paneTabType.SceneViewer)
    
    viewport = viewport_panel.curViewport()

    if viewport.type() == hou.geometryViewportType.Perspective:
        camera_path = viewport.cameraPath()
        if camera_path:
            active_cam = hou.node(camera_path)

    width = 1920
    height = 1080
    
    if active_cam:
        width = int(active_cam.evalParm("resx"))
        height = int(active_cam.evalParm("resy"))

    scene = viewport_panel
    scene.flipbookSettings().stash()
    flip_book_options = scene.flipbookSettings()
    
    flip_book_options.output(playblast_output)
    flip_book_options.frameRange((start_frame, end_frame))
    flip_book_options.useResolution(1)
    flip_book_options.resolution((width, height))
    scene.flipbook(scene.curViewport(), flip_book_options)
    
    normalized_frames_dir = frames_dir.replace("\\\\", "/")
    normalized_quicktime_output = quicktime_output.replace("\\\\", "/")
    
    source_path = "{0}/{1}.%{2:02d}d.png".format(normalized_frames_dir, name, padding)
    
    framerate = hou.fps()
    crf = 18
    preset = "fast"
    # FFmpeg command for mp4 creation
    ffmpeg_cmd = ffmpeg_path
    ffmpeg_cmd += ' -y -framerate {0} -start_number {1} -i "{2}"'.format(framerate, str(start_frame), source_path)
    ffmpeg_cmd += ' -c:v libx264 -crf:v {0} -preset:v {1} -profile high -level 4.0 -pix_fmt yuv420p'.format(crf, preset)
    ffmpeg_cmd += ' "{0}"'.format(normalized_quicktime_output)
    
    gif_output = os.path.join(path, "{0}.gif".format(name))
    normalized_gif_output = gif_output.replace("\\\\", "/")
    
    # FFmpeg command for GIF creation
    gif_cmd = ffmpeg_path
    gif_cmd += ' -y -framerate {0} -start_number {1} -i "{2}"'.format(framerate, str(start_frame), source_path)
    gif_cmd += ' -filter_complex "fps=12,scale=400:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse"'
    gif_cmd += ' "{0}"'.format(normalized_gif_output)
    
    print("Executing: " + ffmpeg_cmd)
    try:
        subprocess.call(ffmpeg_cmd, shell=True)
        subprocess.call(gif_cmd, shell=True)
        print("Successfully created: " + quicktime_output)
        return quicktime_output
    except Exception as e:
        print("Error executing ffmpeg: " + str(e))
        return None
    
hip = hou.getenv("HIP")
hipname = hou.getenv("HIPNAME")
hip_parts = hip.split("/")
hip_parts.insert(hip_parts.index("setups")+1, "_playblast")
hip_parts.append(hipname)
path = "/".join(hip_parts)
name = hipname

playblast(path, name, version_up=True)