Created
April 20, 2025 18:55
-
-
Save me-suzy/d96e2b6013c48b9bb65ab31f32c1d8ab to your computer and use it in GitHub Desktop.
Pasul 3. Combina si compreseaza toate video-urile si imaginile intr-un singur video - final (dureaza mult)
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): | |
print(f"\n🔧 Încep compresia fișierului final: {output_file}") | |
print(f"Durata videoclipului: {video_clip.duration:.2f} secunde") | |
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="96k", | |
ffmpeg_params=[ | |
"-crf", "28", | |
"-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}%") | |
# Verificăm fișierul final | |
final_clip = VideoFileClip(output_file) | |
print(f"Verificare fișier final: Durata video = {final_clip.duration:.2f} secunde") | |
if final_clip.audio: | |
print(f"Verificare audio: Durata audio = {final_clip.audio.duration:.2f} secunde") | |
final_clip.close() | |
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, target_fps=24): | |
"""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") | |
print(f"\n📂 Procesez fișierul: {file_path}") | |
print(f"Salvez temporar în: {temp_output}") | |
try: | |
if file_path.lower().endswith(('.mp4')): | |
clip = VideoFileClip(file_path) | |
original_fps = clip.fps | |
print(f"Fișier video detectat. Rezoluție: {clip.size}, FPS: {original_fps}, Durată: {clip.duration:.2f} secunde") | |
else: | |
img = ImageClip(file_path) | |
original_fps = target_fps | |
clip = img.set_duration(5).set_fps(original_fps) | |
print(f"Fișier imagine detectat. Rezoluție: {clip.size}, Durată setată: 5 secunde") | |
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') | |
print(f"Ajustez clipul la rezoluția țintă {target_size} cu padding") | |
# Forțăm FPS-ul să fie uniform pentru toate fișierele | |
clip = clip.set_fps(target_fps) | |
print(f"Setez FPS-ul la: {target_fps}") | |
clip.write_videofile( | |
temp_output, | |
fps=target_fps, | |
codec='libx264', | |
audio_codec='aac', | |
preset="medium", | |
ffmpeg_params=[ | |
"-crf", "18", | |
"-max_muxing_queue_size", "9999" | |
] | |
) | |
# Verificăm fișierul temporar | |
temp_clip = VideoFileClip(temp_output) | |
print(f"Fișier temporar creat: {temp_output}") | |
print(f"Durata fișierului temporar: {temp_clip.duration:.2f} secunde") | |
print(f"Rezoluție fișier temporar: {temp_clip.size}") | |
temp_clip.close() | |
clip.close() | |
gc.collect() | |
return temp_output, target_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("\n📋 Fișiere găsite:", ", ".join(media_files)) | |
print(f"Număr total de fișiere: {len(media_files)}") | |
temp_dir = os.path.join(input_directory, "Temp") | |
if not os.path.exists(temp_dir): | |
os.makedirs(temp_dir) | |
print(f"📁 Director temporar: {temp_dir}") | |
processed_files = [] | |
total_size = 0 | |
resolutions = [] | |
fps_values = [] | |
print("\n🔍 Analizez fișierele media...") | |
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) | |
print(f"Fișier: {file}, Rezoluție: {clip.size}, FPS: {clip.fps}, Durată: {clip.duration:.2f} secunde") | |
clip.close() | |
else: | |
img = ImageClip(full_path) | |
resolutions.append(img.size) | |
fps_values.append(24) | |
print(f"Fișier: {file}, Rezoluție: {img.size}, FPS: 24 (imagine), Durată: 5 secunde") | |
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"\n🎯 Rezoluție țintă: {target_size}, FPS țintă: {target_fps}") | |
for idx, file in enumerate(media_files): | |
print(f"\n📦 Procesez fișierul {idx+1}/{len(media_files)}: {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, target_fps=target_fps) | |
if temp_file: | |
processed_files.append(temp_file) | |
print(f"✅ Fișier procesat cu succes: {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 | |
print(f"\n🔗 Încep combinarea fișierelor temporare...") | |
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") | |
print(f"Fișier de concatenare creat: {concat_file}") | |
temp_combined = os.path.join(temp_dir, "combined_video.mp4") | |
print(f"Combin fișierele în: {temp_combined}") | |
os.system(f'ffmpeg -f concat -safe 0 -i "{concat_file}" -c:v libx264 -c:a aac -r {target_fps} "{temp_combined}"') | |
# Am înlocuit -c copy cu o re-encodare pentru a evita desincronizările | |
if not os.path.exists(temp_combined): | |
print("❌ Nu s-a putut crea fișierul combinat!") | |
return False | |
print(f"✅ Fișier combinat creat: {temp_combined}") | |
combined_clip = VideoFileClip(temp_combined) | |
print(f"Durata fișierului combinat: {combined_clip.duration:.2f} secunde") | |
combined_clip.close() | |
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 | |
print(f"Durata totală a videoclipului: {video_to_compress.duration:.2f} secunde") | |
while current_duration < video_to_compress.duration: | |
for audio_file in valid_audio: | |
if current_duration >= video_to_compress.duration: | |
break | |
print(f"Procesez fișier audio: {audio_file}") | |
audio = AudioFileClip(audio_file) | |
remaining = video_to_compress.duration - current_duration | |
if audio.duration > remaining: | |
audio = audio.subclip(0, remaining) | |
print(f"Decupez audio la {remaining:.2f} secunde") | |
audio_clips.append(audio) | |
current_duration += audio.duration | |
print(f"Durata audio cumulată: {current_duration:.2f} secunde") | |
if audio_clips: | |
final_audio = concatenate_audioclips(audio_clips) | |
print(f"Durata audio final: {final_audio.duration:.2f} secunde") | |
video_to_compress = video_to_compress.set_audio(final_audio) | |
print("✅ Audio adăugat cu succes") | |
target_bitrate = 1000 * 1000 # 1 Mbps | |
success = process_video_compression(video_to_compress, output_file, target_bitrate, total_size) | |
video_to_compress.close() | |
return success | |
except Exception as e: | |
print(f"❌ Eroare generală: {str(e)}") | |
return False | |
finally: | |
try: | |
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" | |
] | |
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