File size: 4,794 Bytes
dde1cc7 4e1d9aa 08ba1a2 dde1cc7 4e1d9aa dde1cc7 4e1d9aa dde1cc7 08ba1a2 dde1cc7 08ba1a2 dde1cc7 08ba1a2 65e5d85 dde1cc7 65e5d85 08ba1a2 a9a2850 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 | import ffmpeg
import random
import string
from datetime import datetime
import os
# Define target resolution
target_width = 1080
target_height = 1920
def concatenate_videos(files_timestamps):
processed_streams = []
for file_info in files_timestamps:
file_path = file_info["path"]
start_time = file_info["start"]
end_time = file_info["end"]
try:
if end_time == "":
# Create input stream from start_time to end of video
stream = ffmpeg.input(file_path, ss=start_time)
else:
time_obj = datetime.strptime(start_time, "%M:%S.%f")
start_time = time_obj.minute * 60 + time_obj.second + time_obj.microsecond / 1_000_000
time_obj = datetime.strptime(end_time, "%M:%S.%f")
end_time = time_obj.minute * 60 + time_obj.second + time_obj.microsecond / 1_000_000
# Create input stream with trimming
stream = ffmpeg.input(file_path, ss=start_time, t=end_time - start_time)
video = stream.video
audio = stream.audio
# Get video metadata to calculate aspect ratio
probe = ffmpeg.probe(file_path)
video_stream = next(s for s in probe['streams'] if s['codec_type'] == 'video')
video_width = int(video_stream['width'])
video_height = int(video_stream['height'])
video_aspect = video_width / video_height
target_aspect = target_width / target_height
print(f"Processing {file_path}: resolution={video_width}x{video_height}, aspect={video_aspect:.2f}, trimmed from {start_time}s to {end_time}s")
# Scale the video to fit within target resolution while preserving aspect ratio
if abs(video_aspect - target_aspect) > 0.01: # Allow small tolerance
if video_aspect > target_aspect:
# Video is wider: scale to target height, ensure width <= target_width
video = video.filter('scale', f'min({target_width},iw*({target_height}/ih))', target_height, force_original_aspect_ratio='decrease')
# Pad to target resolution, align to left for right-side padding
video = video.filter('pad', target_width, target_height, 0, '(oh-ih)/2', color='black')
else:
# Video is taller: scale to target width, ensure height <= target_height
video = video.filter('scale', target_width, f'min({target_height},ih*({target_width}/iw))', force_original_aspect_ratio='decrease')
# Pad to target resolution, center vertically
video = video.filter('pad', target_width, target_height, '(ow-iw)/2', '(oh-ih)/2', color='black')
else:
# Aspect ratio matches: scale directly to target resolution
video = video.filter('scale', target_width, target_height, force_original_aspect_ratio='decrease')
# Ensure consistent frame rate
video = video.filter('fps', fps=30)
print(f"After scaling {file_path}: target resolution={target_width}x{target_height}")
processed_streams.append(video)
processed_streams.append(audio)
except ffmpeg.Error as e:
print(f"Error processing {file_path}: {e.stderr.decode()}")
continue
except StopIteration:
print(f"Error: No video stream found in {file_path}")
continue
except Exception as e:
print(f"Unexpected error processing {file_path}: {str(e)}")
continue
# Check if we have valid streams to concatenate
if not processed_streams:
print("Error: No valid streams to concatenate")
exit(1)
# Concatenate all video and audio streams
joined = ffmpeg.concat(*processed_streams, v=1, a=1).node
# Output the final video
output_dir = "edited_videos"
if not os.path.exists(output_dir):
os.makedirs(output_dir)
print(f"Created directory: {output_dir}")
try:
# Generate a random string for the filename
random_string = ''.join(random.choices(string.ascii_lowercase + string.digits, k=8))
file_name = f"{output_dir}/video_edited_{random_string}.mp4" # Use .mp4 for compatibility
# Perform the concatenation using ffmpeg
ffmpeg.output(joined[0], joined[1], file_name, **{'c:v': 'libx264', 'c:a': 'aac'}, preset='fast').run(overwrite_output=True)
print("Video concatenation successful")
return file_name
except ffmpeg.Error as e:
print(f"Error during concatenation: {e}")
return None
|