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