@ganstar565

Как правильно настроить работу процессов и как можно оптимизировать код?

Подрабатываю репетитором, веду уроки в zoom. Урок длиться час, но каждые ~27мин конференцию нужно перезапускать т.к. уроки записываются через тот же zoom, то и на один урок у меня приходится 2 видео. Накидал себе скрипт который объеденяет все сегодняшние видео(по 30 мин) в уроки по часу.
spoiler
import datetime
import os 
import sys

from moviepy.editor import VideoFileClip, concatenate_videoclips
from pyautogui import prompt
from multiprocessing import Process


# Директория с папками с видео
os.chdir(r"C:\Users\razor_star\Documents\Zoom")

now = datetime.datetime.now()
if len(str(now.month)) == 2: zero_m = ""
else: zero_m = 0

if len(str(now.day)) == 2: zero_d = ""
else: zero_d = 0


now_full = f"{now.year}-{zero_m}{now.month}-{zero_d}{now.day}"
										
today = [] # массив, где каждый элемент - папка с сегодняшним видео
td = [[]] # массив, где каждый элемент - массив где каждый элемент папка с целым видео (если их склеить)

# заполняем today и td
for i in os.listdir():
	if i.startswith(now_full):
		today.append(i)
		

for i in range(0, len(today)):
	td[-1].append(today[i])
	if i %2:
		td.append([])


td.pop(-1) #удаляем лишний(пустой) массив

if len(today) % 2:
	print(f"не четное колво видео {len(today)}")


# Склеивает 2 части урока в одно видео
def concatenate(dirr: list, name: str) -> None:
	part = 0
	for x in dirr: # dirr - массив с двумя папками(строками) в которых лежат видео которые нужно склеить
		part += 1
		url = r"C:\Users\razor_star\Documents\Zoom\\" + x
		os.chdir(url)
		print(f"часть {part} переходим на {url}")
		
		for f in os.listdir():
			if f.endswith("mp4"): 
				print(f"{url}\\{f}")
				if part ==1: 
					print(os.listdir(), f)
					lesson1 = VideoFileClip(f)
				else: 
					print(f"{name} в работе")
					print(os.listdir(), f)
					lesson2 = VideoFileClip(f)
					os.chdir(r"C:\code\multi")
					if f"lesson_{now_full}" not in os.listdir():
						os.mkdir(f"lesson_{now_full}")
					os.chdir(fr"C:\code\multi\\lesson_{now_full}")
					concatenate_videoclips([lesson1, lesson2]).write_videofile("ready.mp4")
					os.rename("ready.mp4", f"{name.capitalize()} {x.split()[0]}.mp4")
					print(f"{name} готово")
					

				#print(f"меняем {f} на {name.capitalize()} {x.split()[0]} ч{part}.mp4")
				#os.rename(f, f"{name.capitalize()} {x.split()[0]} ч{part}.mp4")
	if part == 2: return



if __name__ == "__main__":
	process_list = []


	for dirr in td:
		print(td)
		name = prompt(f" Введи имя ученика с которым у тебя был урок в {dirr[0].split()[1]}", "имя")
		if name == "некст": continue

		concatenate(dirr, name)
# 		mp = Process(target = concatenate, args = (dirr, name ))
# 		process_list.append(mp)
# 		mp.start()
# 		#print(dirr)


# input()
	#for i in process_list:
	#	i.join()


В этом виде код работает хорошо, но обрабатывает каждое видео по очереди, хотелось бы на каждую обработку выделить отдельный процесс. Пробовал разные способы, но либо на одно время окно вылазит несколько раз, либо на выходе из 8 видео получаю одно смешанное с артефактами.

Стоит уточнить что имя папки с видео начинается на дату этой конференции.

Очень приветствуются советы по оптимизации\повышении читабельности кода. Я понимаю что я намудрил он выглядит стремно и можно сделать лучше.
  • Вопрос задан
  • 71 просмотр
Решения вопроса 1
Vindicar
@Vindicar
RTFM!
from multiprocessing import Pool

def concatenate(video1: str, video2: str, output: str) -> bool:
    """Склеивает два видео и пишет результат в файл output.
    Не стоит использовать глобальные объекты. 
    Стоит принимать как параметры и возвращать только базовые типы данных 
    (булевы, числа, строки, кортежи, списки, словари)."""
    ...   # верни True при успехе, False при неудаче. Лови все исключения.

if __name__ == '__main__':
    videos_to_process = [  # этот список формируешь по своей логике.
        ('18_05_video1.avi', '18_05_video2.avi', r'output\18_05.avi'),  # порядок как у аргументов concatenate()
        ('17_05_video1.avi', '17_05_video2.avi', r'output\17_05.avi'),
    ]
    with Pool() as pool:  # по умолчанию пул создаст по одному процессу на ядро
        results = pool.starmap(concatenate, videos_to_process)
    if not all(results):  # хотя одна функция вернула False?
        for (v1, v2, vr), success in zip(videos_to_process, results):
            if not success:  # выясняем, которая
                print(f'Video merge failed: {v1} + {v2} -> {vr}')
    else:
        print('All videos merged successfully.')
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы