Untitled
unknown
plain_text
2 years ago
10 kB
8
Indexable
def split_by_groups(df): index_list = list(df.index[df.isnull().all(1)]) groups = [] start_idx = 0 for end_idx in index_list: group = df[start_idx:end_idx] groups.append(group) start_idx = end_idx + 1 groups.append(df[start_idx:]) return groups def manage_group(group_frame): group_name = group_frame.iloc[0]["group"] client = group_frame.iloc[0]["client"] main_result_dir = "result" source_dir = f"result/{group_name}" result_dir_path = f"result/{group_name}_result" upload_client_path = dbx_upload_result_path + "/" + client folder_exists = False files_tree = dbx.files_list_folder(dbx_upload_result_path) for entry in files_tree.entries: if entry.name == client and isinstance(entry, dropbox.files.FolderMetadata): folder_exists = True break if not folder_exists: dbx.files_create_folder_v2(upload_client_path) if not os.path.exists(source_dir): os.makedirs(source_dir) if not os.path.exists(main_result_dir): os.makedirs(main_result_dir) if not os.path.exists(result_dir_path): os.makedirs(result_dir_path) mashups = [] for index, row in group_frame.iterrows(): local_path = f"{source_dir}/{index}.mp4" if row["video_source"] == "youtube": download_video_from_yt(row["youtube_link"], source_dir, f"{index}.mp4") elif row["video_source"] == "dropbox": download_video_from_db(row["video_name"], local_path) else: logging.critical("invalid source") return mp_clip = mpy.VideoFileClip(local_path) if not pd.isna(row['finish_result']): path = dbx_path + row['finish_result'] try: # получаем список файлов и папок в указанной директории results = dbx.files_list_folder(path) for entry in results.entries: if isinstance(entry, dropbox.files.FolderMetadata) and entry.path_display == path: # папка уже существует, используем ее print(f"Folder {path} already exists.") break else: # папки в списке нет, создаем новую dbx.files_create_folder_v2(path) print(f"Folder {path} has been created.") except dropbox.exceptions.ApiError as e: print(f"Error accessing folder {path}: {e}") upload_client_path = path #обрезать по длине desired_duration = 15 mp_clip = crop_clip_duration(desired_duration, row['timestamp_left'], row['timestamp_right'], mp_clip) #выровнять соотношение сторон aspect_ratio = mp_clip.w / mp_clip.h desired_ratio = 9 / 16 mp_clip = crop_clip_size(desired_ratio, aspect_ratio, mp_clip) if row['invert_vertical']: print(row['invert_vertical']) mp_clip = mp_clip.fx(mpy.vfx.mirror_x) if not pd.isna(row['cut_orig_video']): mp_clip = crop_top_bottom_x(mp_clip, int(row['cut_orig_video'])) if row["music_from_video"]: audio_clip = mp_clip.audio else: local_track_path = f"{source_dir}/track.mp3" track_path = row["track_name"] if not os.path.exists(local_track_path): with open(local_track_path, 'wb') as f: metadata, res = dbx.files_download(dbx_path + track_path) f.write(res.content) audio_clip = AudioFileClip(local_track_path) if row["origin"]: local_origin_path = f"{result_dir_path}/origin_{index}.mp4" if not os.path.exists(local_origin_path): mp_clip = mp_clip.set_audio(audio_clip) mp_clip.write_videofile(local_origin_path, **settings) upload_video_to_dbx(local_path=local_origin_path, dbx_upload_path=upload_client_path+f"/{group_name}_origin{index}.mp4") if row["subs"]: color = row["sub_color"] or "white" make_subs_clip(mp_clip, audio_clip, color, source_dir, result_dir_path, index, dbx_subs_path=row["sub_name"], upload_path=upload_client_path+f"/{group_name}_subs{index}.mp4") if row["mashup"]: mashups.append(mp_clip.subclip(0, 5).fx(mpy.vfx.fadein, 2).fx(mpy.vfx.fadeout, 2)) if len(mashups) > 0: make_mashups(mashups, audio_clip, local_save_path=f"{result_dir_path}/mashup", upload_path=f"{upload_client_path}/{group_name}_mashup") def make_mashups(clips, audio, local_save_path, upload_path): # Находим наименьшую ширину и высоту среди всех клипов min_w = min([clip.size[0] for clip in clips]) min_h = min([clip.size[1] for clip in clips]) # Приводим все клипы к одному размеру resized_clips = [] for clip in clips: if clip.size[0] != min_w or clip.size[1] != min_h: # Если размер клипа не совпадает с минимальным размером, # то обрезаем или изменяем масштаб if clip.size[0] > min_w: clip = clip.crop(x1=(clip.size[0]-min_w)/2, x2=min_w+(clip.size[0]-min_w)/2) elif clip.size[0] < min_w: clip = clip.resize(width=min_w) if clip.size[1] > min_h: clip = clip.crop(y1=(clip.size[1]-min_h)/2, y2=min_h+(clip.size[1]-min_h)/2) elif clip.size[1] < min_h: clip = clip.resize(height=min_h) resized_clips.append(clip) #массив всех комбинаций из клипов perms = permutations(resized_clips) count = 0 for perm in perms: order = ''.join([str(resized_clips.index(clip) + 1) for clip in perm]) final_clip = concatenate_videoclips(perm) final_clip = final_clip.set_audio(audio) if not os.path.exists(local_save_path): final_clip.write_videofile(local_save_path + f"_{order}.mp4", **settings) upload_video_to_dbx(local_path=local_save_path + f"_{order}.mp4", dbx_upload_path=upload_path + f"{order}.mp4") count = count + 1 def make_subs_clip(clip, audio_clip, color, source_dir, result_dir_path, index, dbx_subs_path, upload_path): local_sub_path = f"{source_dir}/subs.srt" local_subs_clip_path = f"{result_dir_path}/subs_{index}.mp4" if not os.path.exists(local_subs_clip_path): try: with open(local_sub_path, 'wb') as f: metadata, res = dbx.files_download(dbx_path + dbx_subs_path) f.write(res.content) sub_clip = make_subs(clip, local_sub_path, color) sub_clip = sub_clip.set_audio(audio_clip) sub_clip.write_videofile(local_subs_clip_path, **settings) upload_video_to_dbx(local_path=local_subs_clip_path, dbx_upload_path=upload_path) except Exception as e: logging.critical(f"something went wrong with subtitle file: {e}") def make_subs(clip, sub_path, color): font_size = int(min(clip.size[0], clip.size[0]) * 0.05) generator = lambda txt: TextClip(txt, font='Arial', fontsize=font_size, color=color) subs = SubtitlesClip(sub_path, generator) subtitles = SubtitlesClip(subs, generator) result = CompositeVideoClip([clip, subtitles.set_pos(('center', 'center'))]) return result def download_video_from_db(path, local_path): if not os.path.exists(local_path): try: with open(local_path, 'wb') as f: metadata, res = dbx.files_download(dbx_path + path) f.write(res.content) except Exception as e: logging.critical(f"something went wrong: {e}") def download_video_from_yt(link, group_name, file_name): yt = YouTube(link) print(link) yt.streams.filter(progressive=False, file_extension='webm').order_by('resolution')[-1].download(group_name, filename=file_name) def upload_video_to_dbx(local_path, dbx_upload_path): with open(local_path, "rb") as f: dbx.files_upload(f.read(), dbx_upload_path) def crop_clip_size(desired_ratio, aspect_ratio, clip): if aspect_ratio > desired_ratio: # вырезаем кусок по горизонтали width = int(clip.size[1] * desired_ratio) x_center = int((clip.size[0] - width) / 2) crop_area = (x_center, 0, x_center + width, clip.size[1]) else: # вырезаем кусок по вертикали height = int(clip.size[0] / desired_ratio) y_center = int((clip.size[1] - height) / 2) crop_area = (0, y_center, clip.size[0], y_center + height) return clip.crop(*crop_area) def crop_clip_duration(desired_duration, start, end, clip): if clip.duration > desired_duration: if pd.isna(end): minutes, seconds = start.split(':') start = int(minutes) * 60 + int(seconds) end = start + desired_duration clip = clip.subclip(start, end) else: clip = clip.subclip(start, end) return clip def crop_top_bottom_x(clip, x): video_height = clip.size[1] crop_top = int(video_height * (x / 100)) crop_bottom = int(video_height * (1 - x / 100)) clip = clip.crop(y1=crop_top, y2=crop_bottom) return clip def delete_folder(folder_path): print("deleting") for process in psutil.process_iter(): try: for file in process.open_files(): if file.path.startswith(folder_path): process.kill() break except Exception as e: pass shutil.rmtree(folder_path, ignore_errors=True) def main(): groups = split_by_groups(data_table) for group in groups: try: manage_group(group) except Exception as e: logging.critical(f"invalid group {group.iloc[0]['group']}: {e}") # remove_result() main() def remove_result(): delete_folder("result")
Editor is loading...