Created
April 20, 2025 18:57
-
-
Save me-suzy/7cfc6ca157f90e5e05d7e0ae90858dab to your computer and use it in GitHub Desktop.
Pasul 3. Combina si compreseaza toate video-urile si imaginile intr-un singur video - final 20 aprilie 25.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import os | |
import sys | |
from moviepy.editor import VideoFileClip, ImageClip, AudioFileClip, concatenate_videoclips, concatenate_audioclips | |
import re | |
import gc | |
import shutil | |
def get_video_info(clip): | |
return { | |
'durată': f"{clip.duration:.2f} secunde", | |
'dimensiune': f"{os.path.getsize(clip.filename)/(1024*1024):.1f} MB", | |
'rezoluție': f"{clip.size[0]}x{clip.size[1]}", | |
'fps': f"{clip.fps}" | |
} | |
def process_video_compression(video_clip, output_file, target_bitrate, original_size): | |
try: | |
video_clip.write_videofile( | |
output_file, | |
fps=video_clip.fps, | |
codec='libx264', | |
audio_codec='aac', | |
temp_audiofile='temp-audio.m4a', | |
remove_temp=True, | |
bitrate=f"{target_bitrate/1000:.0f}k", | |
preset="medium", | |
threads=4, | |
audio_bitrate="192k", | |
ffmpeg_params=[ | |
"-crf", "18", | |
"-movflags", "+faststart", | |
"-profile:v", "high", | |
"-level", "4.1", | |
"-pix_fmt", "yuv420p", | |
"-tune", "film", | |
"-maxrate", f"{target_bitrate*1.5/1000:.0f}k", | |
"-bufsize", f"{target_bitrate*2/1000:.0f}k", | |
"-max_muxing_queue_size", "9999" | |
] | |
) | |
final_size = os.path.getsize(output_file) | |
compression_ratio = (1 - final_size/original_size) * 100 | |
print("\n=== Rezultate Compresie ===") | |
print(f"Dimensiune originală: {original_size/(1024*1024):.1f} MB") | |
print(f"Dimensiune după compresie: {final_size/(1024*1024):.1f} MB") | |
print(f"Rata de compresie: {compression_ratio:.1f}%") | |
return True | |
except Exception as e: | |
print(f"\n❌ Eroare la compresie: {str(e)}") | |
return False | |
finally: | |
if os.path.exists('temp-audio.m4a'): | |
os.remove('temp-audio.m4a') | |
gc.collect() | |
def process_file_individually(file_path, output_dir, index, target_size=None): | |
"""Procesează fiecare fișier separat, păstrând dimensiunea originală sau ajustând-o cu padding""" | |
temp_output = os.path.join(output_dir, f"temp_processed_{index}.mp4") | |
try: | |
if file_path.lower().endswith(('.mp4')): | |
clip = VideoFileClip(file_path) | |
original_fps = clip.fps | |
else: | |
img = ImageClip(file_path) | |
original_fps = 24 | |
clip = img.set_duration(5).set_fps(original_fps) | |
if target_size: | |
clip = clip.resize(newsize=target_size) if clip.size != target_size else clip | |
if clip.size != target_size: | |
clip = clip.on_color(size=target_size, color=(0, 0, 0), pos='center') | |
clip.write_videofile( | |
temp_output, | |
fps=original_fps, | |
codec='libx264', | |
audio_codec='aac', | |
preset="medium", | |
ffmpeg_params=[ | |
"-crf", "18", | |
"-max_muxing_queue_size", "9999" | |
] | |
) | |
clip.close() | |
gc.collect() | |
return temp_output, original_fps | |
except Exception as e: | |
print(f"\n❌ Eroare la procesarea fișierului: {str(e)}") | |
return None, None | |
def combine_and_compress_media(input_directory, output_file, audio_files=None, image_duration=5): | |
try: | |
media_files = [ | |
f for f in os.listdir(input_directory) | |
if f.lower().endswith(('.mp4', '.jpg', '.jpeg', '.png')) | |
] | |
if not media_files: | |
print("❌ Nu s-au găsit fișiere media în director!") | |
return False | |
media_files.sort(key=lambda s: [ | |
int(t) if t.isdigit() else t.lower() | |
for t in re.split('([0-9]+)', s) | |
]) | |
print("\nFișiere găsite:", ", ".join(media_files)) | |
# Definim un director temporar personalizat | |
temp_dir = os.path.join(input_directory, "Temp") | |
if not os.path.exists(temp_dir): | |
os.makedirs(temp_dir) # Creăm directorul dacă nu există | |
print(f"Director temporar: {temp_dir}") | |
processed_files = [] | |
total_size = 0 | |
resolutions = [] | |
fps_values = [] | |
for file in media_files: | |
full_path = os.path.join(input_directory, file) | |
if file.lower().endswith(('.mp4')): | |
clip = VideoFileClip(full_path) | |
resolutions.append(clip.size) | |
fps_values.append(clip.fps) | |
clip.close() | |
else: | |
img = ImageClip(full_path) | |
resolutions.append(img.size) | |
fps_values.append(24) | |
img.close() | |
gc.collect() | |
target_width = max([res[0] for res in resolutions]) | |
target_height = max([res[1] for res in resolutions]) | |
target_size = (target_width, target_height) | |
target_fps = max(fps_values) | |
print(f"\nRezoluție țintă: {target_size}, FPS țintă: {target_fps}") | |
for idx, file in enumerate(media_files): | |
print(f"\nProcesez: {file}") | |
full_path = os.path.join(input_directory, file) | |
total_size += os.path.getsize(full_path) | |
temp_file, fps = process_file_individually(full_path, temp_dir, idx, target_size=target_size) | |
if temp_file: | |
processed_files.append(temp_file) | |
else: | |
print(f"Eroare la procesarea {file}, continui cu următorul...") | |
if not processed_files: | |
print("Nu s-au putut procesa fișierele media!") | |
return False | |
concat_file = os.path.join(temp_dir, "concat_list.txt") | |
with open(concat_file, 'w') as f: | |
for file in processed_files: | |
f.write(f"file '{file}'\n") | |
temp_combined = os.path.join(temp_dir, "combined_video.mp4") | |
os.system(f'ffmpeg -f concat -safe 0 -i "{concat_file}" -c copy "{temp_combined}"') | |
if not os.path.exists(temp_combined): | |
print("❌ Nu s-a putut crea fișierul combinat!") | |
return False | |
has_audio = False | |
video_to_compress = VideoFileClip(temp_combined) | |
if audio_files: | |
valid_audio = [a for a in audio_files if a and os.path.exists(a)] | |
if valid_audio: | |
print("🎵 Adaug fișiere audio pe fundal...") | |
has_audio = True | |
audio_clips = [] | |
current_duration = 0 | |
while current_duration < video_to_compress.duration: | |
for audio_file in valid_audio: | |
if current_duration >= video_to_compress.duration: | |
break | |
audio = AudioFileClip(audio_file) | |
remaining = video_to_compress.duration - current_duration | |
if audio.duration > remaining: | |
audio = audio.subclip(0, remaining) | |
audio_clips.append(audio) | |
current_duration += audio.duration | |
if audio_clips: | |
final_audio = concatenate_audioclips(audio_clips) | |
video_to_compress = video_to_compress.set_audio(final_audio) | |
print("📦 Comprim video-ul final...") | |
success = process_video_compression(video_to_compress, output_file, 5000*1000, total_size) | |
video_to_compress.close() | |
return success | |
except Exception as e: | |
print(f"❌ Eroare: {str(e)}") | |
return False | |
finally: | |
try: | |
# Nu ștergem directorul Temp, dar putem șterge fișierele temporare create | |
for file in os.listdir(temp_dir): | |
file_path = os.path.join(temp_dir, file) | |
if os.path.isfile(file_path): | |
os.remove(file_path) | |
except: | |
pass | |
gc.collect() | |
def main(): | |
INPUT_PATH = r"g:\Dubai Nou\METRO DUBAI" | |
AUDIO_FILES = [ | |
r"G:\Muzica\Andorra - A Song For Harmony (Original Mix) (320kbps).mp3", | |
r"G:\Muzica\Andorra - A Song For Harmony (Original Mix) (320kbps).mp3" | |
] | |
# Pentru a salva fără audio, setează: | |
# AUDIO_FILES = [ | |
# r"", | |
# r"" | |
# ] | |
AUDIO_FILES = [af for af in AUDIO_FILES if af] | |
output_file = os.path.join(INPUT_PATH, "FISIER-SALVAT.mp4") | |
success = combine_and_compress_media(INPUT_PATH, output_file, AUDIO_FILES, image_duration=5) | |
if success: | |
print("\n✅ Procesul s-a finalizat cu succes!") | |
else: | |
print("\n❌ Procesul a eșuat!") | |
if __name__ == "__main__": | |
gc.collect() | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment