import os
import subprocess
from moviepy.editor import VideoFileClip
from scipy.io import wavfile
import numpy as np

# Define video file extensions and the output folder
video_extensions = ['.mp4', '.mkv', '.wmv', '.avi']
output_folder = 'Output'

def calculate_loudness(audio_data):
    if audio_data.ndim == 1:
        volume = audio_data ** 2
    else:
        volume = np.mean(audio_data ** 2, axis=1)
    return np.sqrt(volume)

def find_loudest_moments(audio_filename, num_moments, duration, segment_half_duration):
    rate, audio_data = wavfile.read(audio_filename)
    if audio_data.ndim == 2:
        audio_data = np.mean(audio_data, axis=1)
    volume = calculate_loudness(audio_data.astype('float32'))

    moments = []
    for _ in range(num_moments):
        index = np.argmax(volume)
        moment = index / rate
        # Ensure the segment is within the video bounds
        start_time = max(moment - segment_half_duration, 0)
        end_time = min(moment + segment_half_duration, duration)
        if end_time - start_time >= segment_half_duration * 2:
            moments.append(moment)
            window_start = max(0, index - int(rate * 5))
            window_end = min(len(volume), index + int(rate * 5))
            volume[window_start:window_end] = 0
    return moments

def extract_segments(video_path, audio_path, moments, segment_duration):
    if not os.path.exists(output_folder):
        os.makedirs(output_folder)

    base_name = os.path.splitext(os.path.basename(video_path))[0]
    half_duration = segment_duration / 2

    for i, moment in enumerate(moments):
        start_time = max(moment - half_duration, 0)
        end_time = min(moment + half_duration, VideoFileClip(video_path).duration)
        actual_duration = end_time - start_time
        output_filename = f"{base_name}moment{i + 1}.mp4"
        output_path = os.path.join(output_folder, output_filename)
        command = [
            "ffmpeg",
            "-y",  # Automatic overwrite of output files without asking
            "-i", video_path,  # Input video file
            "-ss", str(start_time),  # Start time for segment
            "-t", str(actual_duration),  # Adjusted duration of segment
            "-c", "copy",  # Copy the video and audio streams without re-encoding
            output_path  # Output file
        ]
        subprocess.run(command, check=True, stderr=subprocess.PIPE)

def process_video_files(num_moments, segment_duration):
    segment_half_duration = segment_duration / 2
    for root, _, files in os.walk('.'):
        for file in files:
            if file.lower().endswith(tuple(video_extensions)):
                video_path = os.path.join(root, file)
                print(f"Processing video {video_path}…")

                audio_path = 'temp_audio.wav'
                video_clip = VideoFileClip(video_path)
                video_clip.audio.write_audiofile(audio_path, codec='pcm_s16le', fps=44100, nbytes=2, buffersize=2000)
                
                moments = find_loudest_moments(audio_path, num_moments, video_clip.duration, segment_half_duration)
                video_clip.close()  # Close the video clip to free up resources

                extract_segments(video_path, audio_path, moments, segment_duration)
                
                os.remove(audio_path)  # Delete the temporary audio file

                print(f"Finished processing video {video_path}")

if __name__ == "__main__":
    num_moments = int(input("Combien de moments forts souhaiteriez-vous extraire de chaque vidéo ? "))
    segment_duration = float(input("Quelle est la durée (en secondes) de chaque segment vidéo à extraire ? "))
    process_video_files(num_moments, segment_duration)
    print("All videos have been processed.")