|
|
|
|
@ -69,7 +69,6 @@ def concat_copy(videos, out_path):
|
|
|
|
|
out_path,
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
print("Running FFmpeg concat...")
|
|
|
|
|
result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)
|
|
|
|
|
|
|
|
|
|
os.unlink(list_file)
|
|
|
|
|
@ -115,6 +114,7 @@ def concatenate_videos(videos_list, reencode_concate = False):
|
|
|
|
|
if not reencode_concate:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
print("Falling back to re-encoding due to concat failure.")
|
|
|
|
|
return encode_concatenate_videos(videos_list)
|
|
|
|
|
|
|
|
|
|
def copy_concatenate_videos(videos_list):
|
|
|
|
|
@ -134,7 +134,6 @@ def copy_concatenate_videos(videos_list):
|
|
|
|
|
success = concat_copy(videos_list, output_path)
|
|
|
|
|
|
|
|
|
|
if not success:
|
|
|
|
|
print("Falling back to re-encoding due to concat failure.")
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
# Remove originals
|
|
|
|
|
@ -147,7 +146,7 @@ def copy_concatenate_videos(videos_list):
|
|
|
|
|
return main_video
|
|
|
|
|
|
|
|
|
|
def encode_concatenate_videos(videos_list):
|
|
|
|
|
"""Your existing function to encode and concatenate videos."""
|
|
|
|
|
"""Encode and concatenate videos without ffmpeg spam in console."""
|
|
|
|
|
main_video = videos_list[0]
|
|
|
|
|
video_path = main_video["filepath"]
|
|
|
|
|
|
|
|
|
|
@ -163,17 +162,12 @@ def encode_concatenate_videos(videos_list):
|
|
|
|
|
target_width, target_height = get_target_resolution(videos_list)
|
|
|
|
|
target_bitrate_kbps = get_target_bitrate(target_width, target_height)
|
|
|
|
|
|
|
|
|
|
# Clamp target bitrate to not exceed source
|
|
|
|
|
if current_bitrate > 0:
|
|
|
|
|
target_bitrate_kbps = min(target_bitrate_kbps, current_bitrate)
|
|
|
|
|
|
|
|
|
|
# Max bitrate shouldn't exceed source either
|
|
|
|
|
if current_bitrate > 0:
|
|
|
|
|
max_bitrate_kbps = min(int(1.5 * target_bitrate_kbps), current_bitrate)
|
|
|
|
|
else:
|
|
|
|
|
max_bitrate_kbps = int(1.5 * target_bitrate_kbps)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fps_float = get_fps(video_path) or video_info.get('fps') or 30.0
|
|
|
|
|
if fps_float <= 0:
|
|
|
|
|
fps_float = 30.0
|
|
|
|
|
@ -184,14 +178,13 @@ def encode_concatenate_videos(videos_list):
|
|
|
|
|
print(f" Target Bitrate: {target_bitrate_kbps}k (max ~{max_bitrate_kbps}k)")
|
|
|
|
|
print(f" Keyframe Interval: {keyframe_interval}")
|
|
|
|
|
|
|
|
|
|
cmd = ["ffmpeg", "-y"] # Overwrite output if exists
|
|
|
|
|
cmd = ["ffmpeg", "-y"]
|
|
|
|
|
for v in videos_list:
|
|
|
|
|
cmd.extend(["-i", v["filepath"]])
|
|
|
|
|
|
|
|
|
|
filter_statements = []
|
|
|
|
|
concat_streams = []
|
|
|
|
|
n = len(videos_list)
|
|
|
|
|
|
|
|
|
|
unified_fps = 30
|
|
|
|
|
|
|
|
|
|
for i in range(n):
|
|
|
|
|
@ -200,10 +193,8 @@ def encode_concatenate_videos(videos_list):
|
|
|
|
|
)
|
|
|
|
|
concat_streams.append(f"[v{i}][{i}:a]")
|
|
|
|
|
|
|
|
|
|
# Example final: [v0][0:a][v1][1:a]concat=n=2:v=1:a=1[outv][outa]
|
|
|
|
|
concat_line = "".join(concat_streams) + f"concat=n={n}:v=1:a=1[outv][outa]"
|
|
|
|
|
filter_statements.append(concat_line)
|
|
|
|
|
|
|
|
|
|
filter_complex = ";".join(filter_statements)
|
|
|
|
|
|
|
|
|
|
cmd.extend([
|
|
|
|
|
@ -222,13 +213,12 @@ def encode_concatenate_videos(videos_list):
|
|
|
|
|
])
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
subprocess.run(cmd, check=True)
|
|
|
|
|
except:
|
|
|
|
|
subprocess.run(cmd, check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
|
|
|
|
except subprocess.CalledProcessError:
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
for video in videos_list:
|
|
|
|
|
os.remove(video["filepath"])
|
|
|
|
|
|
|
|
|
|
shutil.move(temp_path, output_path)
|
|
|
|
|
|
|
|
|
|
return main_video
|
|
|
|
|
return main_video
|
|
|
|
|
|