I have a function that replay some steps from a .json file and another fuction which record those steps. I need the recordingScreen function to stop once the playActions function finishes simultaneously (by using the flag) and create a video for each iteration, but it only creates the video for the last file (iteration)
I have tried with a flag that changes from false when the playActions function finishes I have also tried with queue from this example link and using using a threadsafe threading.Event()
from this example link. But as I am a beginner I have not been able to implement any of them correctly within my code, which is as follow:
files= ["actions_test_10-07-2020_15-56-43.json", "actions_test_10-08-2020_14-59-00.json"]
date = datetime.today().strftime("%m-%d-%Y_%H-%M-%S")
Stop_recording = False
def main():
initializePyAutoGUI()
countdownTimer()
for i in range(len(files)):
global Stop_recording
Stop_recording = False
t1 = threading.Thread(target=playActions, args=[files[i]])
t2 = threading.Thread(target=recordScreen)
t1.start()
t2.start()
t1.join()
t2.join()
print("Done")
def recordScreen():
output = '{}.avi'.format(date)
img = pyautogui.screenshot()
img = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
# get info from img
height, width, channels = img.shape
# Define the codec and create VideoWriter object
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter(output, fourcc, 20.0, (width, height))
while not Stop_recording:
img = pyautogui.screenshot()
image = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)
out.write(image)
StopIteration(0.5)
out.release()
cv2.destroyAllWindows()
def playActions(filename):
# Read the file
script_dir = os.path.dirname(__file__)
filepath = os.path.join(script_dir, 'recordings', filename)
with open(filepath, 'r') as jsonfile:
# parse the json
data = json.load(jsonfile)
# loop over each action
# Because we are not waiting any time before executing the first action, any delay before the initial
# action is recorded will not be reflected in the playback.
for index, action in enumerate(data):
action_start_time = time()
# look for escape input to exit
if action['button'] == 'Key.esc':
break
# perform the action
if action['type'] == 'keyDown':
key = convertKey(action['button'])
pyautogui.keyDown(key)
print("keyDown on {}".format(key))
elif action['type'] == 'keyUp':
key = convertKey(action['button'])
pyautogui.keyUp(key)
print("keyUp on {}".format(key))
elif action['type'] == 'click' and action['button'] == "Button.right":
pyautogui.rightClick(action['pos'][0], action['pos'][1], duration=0.25)
print("right click on {}".format(action['pos']))
elif action['type'] == 'click' and action['button'] == "Button.left":
# Check if the period between clicks is short and perform a double click then, otherwise
# it performs a single click
if index > 0:
if (data[index]['time']) - (data[index - 1]['time']) < 0.5:
pyautogui.doubleClick(action['pos'][0], action['pos'][1])
print("Double click on {}".format(action['pos']))
pyautogui.leftClick(action['pos'][0], action['pos'][1], duration=0.25)
print("left click on {}".format(action['pos']))
# then sleep until next action should occur
try:
next_action = data[index + 1]
except IndexError:
# this was the last action in the list
break
elapsed_time = next_action['time'] - action['time']
# if elapsed_time is negative, that means our actions are not ordered correctly. throw an error
if elapsed_time < 0:
raise Exception('Unexpected action ordering.')
# adjust elapsed_time to account for our code taking time to run
elapsed_time -= (time() - action_start_time)
if elapsed_time < 0:
elapsed_time = 0
print('sleeping for {}'.format(elapsed_time))
sleep(elapsed_time)
global Stop_recording
Stop_recording = True