def _combine(sequence_out: list, step_data: StepData, values: dict): try: args = ["ffmpeg", "-loglevel", "8", "-i"] concat = "concat:" file_temp = [] output = resources.get_temp_resource_path(f"file.mkv", step_data.data["_pipe_id"]) for idx, file in enumerate(sequence_out): temp_file = resources.get_temp_resource_path(f"temp{idx}.ts", step_data.data["_pipe_id"]) args2 = ["ffmpeg", "-loglevel", "8", "-i", file, "-c", "copy", "-bsf:v", "h264_mp4toannexb", "-f", "mpegts", temp_file] subprocess.run(args2, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=True) file_temp.append(temp_file) for idx, file in enumerate(file_temp): if idx != 0: concat += "|" concat += file args.extend((concat, "-codec", "copy", output)) subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=True) new_output = resources.get_out_path(values["out_time"], step_data.get_config("output_path", ""), step_data.get_config("job_name", "")) args = ["ffmpeg", "-loglevel", "8", "-i", output, new_output] subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=True) values["sequence"] = output except subprocess.CalledProcessError as e: raise FFmpegError(e.returncode, e.output.decode("utf-8")) from e
def __cleanup(self): if self.__no_tmp_dir: return # delete directory logger.info("Cleaning up...") shutil.rmtree(resources.get_temp_resource_path("", self.id), ignore_errors=True) logger.info("Finished cleanup!")
def _audios_to_audio(audios, step_data: StepData): with open( resources.get_temp_resource_path("input.txt", step_data.data["_pipe_id"]), "w") as file: for i in audios: file.write("file 'file:" + i + "'\n") output = resources.new_temp_resource_path(step_data.data["_pipe_id"], "mp3") args1 = [ "ffmpeg", "-loglevel", "8", "-f", "concat", "-safe", "0", "-i", resources.get_temp_resource_path("input.txt", step_data.data["_pipe_id"]), "-c", "copy", output ] subprocess.run(args1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=True) return output
def __cleanup(self): if self.__no_tmp_dir: return # delete directory logger.info("Cleaning up...") shutil.rmtree(resources.get_temp_resource_path("", self.id), ignore_errors=True) files = glob.glob(resources.get_image_path("diagrams") + "/*") for f in files: os.remove(f) logger.info("Finished cleanup!")
def __setup(self): logger.info(f"Initializing {self.__log_name} {self.id}...") self.__start_time = time.time() # Insert job into Table log_id = self.__update_db(insert_log, self.__job_id, self.__log_states["running"], round(self.__start_time)) self.__log_id = log_id # Load json config file with resources.open_resource(f"steps/{self.__step_name}.json") as fp: self.__config = json.loads(fp.read()) # Load and merge global presets with resources.open_resource(f"steps/global_presets.json") as fp: global_presets = json.loads(fp.read()) self.__config["presets"] = { **global_presets.get("presets", {}), **self.__config.get("presets", {}) } if not self.__no_tmp_dir: os.mkdir(resources.get_temp_resource_path("", self.id)) # Init Steps config with default config steps_config = self.__get_default_config( self.__config.get("run_config", {})) steps_config.update(self.steps_config) self.steps_config = steps_config # Init out_time self.__config["out_time"] = datetime.fromtimestamp( self.__start_time).strftime(DATE_FORMAT) logger.info(f"Initialization finished!")
def _generate(images, audios, audio_l, step_data: StepData, values: dict): try: if step_data.get_config("h264_nvenc", False): os.environ['LD_LIBRARY_PATH'] = "/usr/local/cuda/lib64" # Concatenate audio files if values["sequence"].get("audio_breaks", False): temp_audios = [] for idx, s_audio in enumerate(audios): temp_audios.append(resources.new_temp_resource_path(step_data.data["_pipe_id"], "wav")) args = ["ffmpeg", "-loglevel", "8", "-i", s_audio, temp_audios[idx]] subprocess.run(args) combined_sound = AudioSegment.empty() for idx, i in enumerate(temp_audios): sound = AudioSegment.from_file(i, "wav") combined_sound += sound time_diff = audio_l[idx] - MP3(audios[idx]).info.length if time_diff > 0: silence = AudioSegment.silent(duration=time_diff * 1000) combined_sound += silence temp_output = resources.new_temp_resource_path(step_data.data["_pipe_id"], "wav") combined_sound.export(temp_output, format="wav") output = resources.new_temp_resource_path(step_data.data["_pipe_id"], "mp3") args = ["ffmpeg", "-loglevel", "8", "-i", temp_output, "-vn", "-ar", "44100", "-ac", "2", "-b:a", "192k", output] subprocess.run(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=True) else: with open(resources.get_temp_resource_path("input.txt", step_data.data["_pipe_id"]), "w") as file: for i in audios: file.write("file 'file:" + i + "'\n") output = resources.new_temp_resource_path(step_data.data["_pipe_id"], "mp3") args1 = ["ffmpeg", "-loglevel", "8", "-f", "concat", "-safe", "0", "-i", resources.get_temp_resource_path("input.txt", step_data.data["_pipe_id"]), "-c", "copy", output] subprocess.run(args1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=True) # Generate video output2 = resources.get_out_path(values["out_time"], step_data.get_config("output_path", ""), step_data.get_config("job_name", "")) if step_data.get_config("separate_rendering", False): output2 = resources.get_out_path(values["out_time"], step_data.get_config("output_path", ""), step_data.get_config("job_name", "") + "_0") args2 = ["ffmpeg", "-loglevel", "8", "-y"] for i in range(0, len(images)): args2.extend(("-loop", "1", "-t", str(round(audio_l[i], 2)), "-i", images[i])) args2.extend(("-i", output, "-c:a", "copy")) filter = "" for i in range(0, len(images) - 1): filter += f"[{i + 1}]format=yuva444p,fade=d={values['sequence'].get('transitions', 0.8)}:t=in:alpha=1,setpts=PTS-STARTPTS+{_sum_audio_l(audio_l, i)}/TB[f{i}];" for j in range(0, len(images) - 1): if j == 0: filter += "[0][f0]overlay[bg1];" elif j == len(images) - 2: filter += f"[bg{j}][f{j}]overlay,format=yuv420p[v]" else: filter += f"[bg{j}][f{j}]overlay[bg{j + 1}];" if len(images) > 1: if len(images) == 2: filter = f"[1]format=yuva444p,fade=d={values['sequence'].get('transitions', 0.8)}:t=in:alpha=1,setpts=PTS-STARTPTS+{_sum_audio_l(audio_l, 0)}/TB[f0];[0][f0]overlay,format=yuv420p[v]" args2.extend(("-filter_complex", filter, "-map", "[v]", "-map", str(len(images)) + ":a")) else: args2.extend(("-pix_fmt", "yuv420p")) if step_data.get_config("h264_nvenc", False): args2.extend(("-c:v", "h264_nvenc")) args2.extend(("-s", "1920x1080", output2)) subprocess.run(args2, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=True) values["sequence"] = output2 except subprocess.CalledProcessError as e: raise FFmpegError(e.returncode, e.output.decode("utf-8")) from e
def tearDown(self): shutil.rmtree(resources.get_temp_resource_path("", "101"), ignore_errors=True)
def setUp(self): resources.RESOURCES_LOCATION = "tests/resources" os.makedirs(resources.get_resource_path("temp"), exist_ok=True) os.makedirs(resources.get_temp_resource_path("", "101"), exist_ok=True)
def _generate(images, audios, audio_l, step_data: StepData, values: dict): try: if step_data.get_config("h264_nvenc", False): os.environ['LD_LIBRARY_PATH'] = "/usr/local/cuda/lib64" # Concatenate audio files with open( resources.get_temp_resource_path("input.txt", step_data.data["_pipe_id"]), "w") as file: for i in audios: file.write("file 'file:" + i + "'\n") output = resources.new_temp_resource_path(step_data.data["_pipe_id"], "mp3") args1 = [ "ffmpeg", "-loglevel", "8", "-f", "concat", "-safe", "0", "-i", resources.get_temp_resource_path("input.txt", step_data.data["_pipe_id"]), "-c", "copy", output ] subprocess.run(args1, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=True) # Generate video output2 = resources.get_out_path( values["out_time"], step_data.get_config("output_path", ""), step_data.get_config("job_name", "")) if step_data.get_config("separate_rendering", False): output2 = resources.get_out_path( values["out_time"], step_data.get_config("output_path", ""), step_data.get_config("job_name", "") + "_0") args2 = ["ffmpeg", "-loglevel", "8", "-y"] for i in range(0, len(images)): args2.extend(("-loop", "1", "-t", str(round(audio_l[i], 2)), "-i", images[i])) args2.extend(("-i", output, "-c:a", "copy")) filter = "" for i in range(0, len(images) - 1): filter += f"[{i + 1}]format=yuva444p,fade=d={values['sequence'].get('transitions', 0.8)}:t=in:alpha=1,setpts=PTS-STARTPTS+{_sum_audio_l(audio_l, i)}/TB[f{i}];" for j in range(0, len(images) - 1): if j == 0: filter += "[0][f0]overlay[bg1];" elif j == len(images) - 2: filter += f"[bg{j}][f{j}]overlay,format=yuv420p[v]" else: filter += f"[bg{j}][f{j}]overlay[bg{j + 1}];" if len(images) > 2: args2.extend(("-filter_complex", filter, "-map", "[v]", "-map", str(len(images)) + ":a")) else: args2.extend(("-pix_fmt", "yuv420p")) if step_data.get_config("h264_nvenc", False): args2.extend(("-c:v", "h264_nvenc")) args2.extend(("-s", "1920x1080", output2)) subprocess.run(args2, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=True) values["sequence"] = output2 except subprocess.CalledProcessError as e: raise FFmpegError(e.returncode, e.output.decode("utf-8")) from e