Small feature request for viewport capture extension

Hello,

we are using the viewport-capture-extension for automated video generation for products with animations. Now we would like to produce videos that can be played in a loop. The optimal variant would be to duplicate the frames in the frames folder in reverse order. The extension already determines the frames by the existence of the corresponding files, but it stops when “framecount” is reached…

        if os.path.isfile(frame_path) and os.access(frame_path, os.R_OK):
           self._frame_filenames.append(frame_path)
          next_frame += 1
           frame_count += 1
          if frame_count == total_frames:
               break
       else:
           break

If you could remove this check and update the framecount with the count determined from the files, it should be possible to hold the process when the last frame is rendered, duplicate the frames in reverse order and voila: I have my perfectly looping video :-)

Thank you very much

Carl

I think it is much mor simple to just encode the video by myself :-)

And this allows me to generate a perfectly looping video even without writing duplicated files to disk…

Perhaps you can integrate this feature to one of the next versions of the capture extension…

import os
import threading
import carb

from omni.kit.capture.viewport.helper import get_num_pattern_file_path

try:
from video_encoding import get_video_encoding_interface
except ImportError:
get_video_encoding_interface = lambda: None

g_video_encoding_api = get_video_encoding_interface()

def generateVideo(video_name, frames_dir, filename_prefix, filename_num_pattern,start_number, total_frames, frame_rate, image_type=“.png”, loop=False, holdStart=0.0, holdEnd=0.0):
carb.log_warn(f"Using videoencoding plugin to encode video ({video_name})")
global g_video_encoding_api

if g_video_encoding_api is None:
	carb.log_warn("Video encoding api not available; cannot encode video.")
	return False

next_frame = start_number
frame_count = 0
_frame_filenames = []
while True:
	frame_path = get_num_pattern_file_path(frames_dir,filename_prefix,filename_num_pattern,next_frame,image_type)
	if os.path.isfile(frame_path) and os.access(frame_path, os.R_OK):
		_frame_filenames.append(frame_path)
		next_frame += 1
		frame_count += 1
		if frame_count == total_frames:
			break
	else:
		break
	
	carb.log_warn(f"Found {len(_frame_filenames)} frames to encode.")
	if len(_frame_filenames) == 0:
		carb.log_warn(f"No frames to encode.")
		return False
	
	finalFrameCount = len(_frame_filenames)
	
	if loop:
		finalFrameCount *= 2
		
		if holdEnd > 0:
			finalFrameCount += int(24 * holdEnd)

		if holdStart > 0:
			finalFrameCount += int(24 * holdStart)

	if not g_video_encoding_api.start_encoding(video_name, frame_rate, finalFrameCount, True):
		carb.log_warn(f"videoencoding plug failed to start encoding.")
		return False

	try:
		for frame_filename in _frame_filenames:
			g_video_encoding_api.encode_next_frame_from_file(frame_filename)
	
		if loop:
			if holdEnd  > 0:
				for frameIndex in range(0, int(24 * holdEnd)):
					g_video_encoding_api.encode_next_frame_from_file(_frame_filenames[len(_frame_filenames) - 1])
		
			for frame_filename in reversed(_frame_filenames):
				g_video_encoding_api.encode_next_frame_from_file(frame_filename)

			if holdStart > 0:
				for frameIndex in range(0, int(24 * holdStart)):
					g_video_encoding_api.encode_next_frame_from_file(_frame_filenames[0])
	except:
		import traceback

		carb.log_warn(traceback.format_exc())
	finally:
		g_video_encoding_api.finalize_encoding()
		carb.log_warn(f"videoencoding done")

generateVideo(“D:/Temp/MyVideo.mp4”, “D:/Users/c.Bickmeier/Documents/Kit/shared/capture/Capture_frames”, “Capture”, “.####”, 40, 20, 24, loop=True, holdStart=1, holdEnd=1)

of course the 24 has to be replaced with frame_rate
:-)