Spaces:
Running
on
Zero
Running
on
Zero
# ============================ | |
# get_footage.py (unchanged) | |
# ============================ | |
# (contenu identique à la précédente version – pas de modification) | |
# ============================ | |
# edit_video.py (révision => musique optionnelle et volume paramétrable) | |
# ============================ | |
"""Assemble la voix IA et, si fourni, la musique de fond. | |
Appel : | |
edit_video( | |
video_path="./assets/video_music/video_silent.mp4", | |
audio_path="./assets/audio/voice.mp3", | |
music_path=None, # ou chemin .mp3 / .wav | |
output_path="./assets/output/final_video.mp4", | |
music_volume=0.10, # volume musique (0‑1) | |
) | |
""" | |
from moviepy import VideoFileClip, AudioFileClip, CompositeAudioClip | |
import os | |
def edit_video( | |
video_path: str, | |
audio_path: str, | |
music_path: str | None, | |
output_path: str, | |
*, | |
music_volume: float = 0.10, | |
): | |
video_clip = VideoFileClip(video_path) | |
voice_clip = AudioFileClip(audio_path) | |
tracks = [voice_clip] | |
if music_path and os.path.isfile(music_path): | |
try: | |
music_clip = ( | |
AudioFileClip(music_path) | |
.with_volume_scaled(music_volume) | |
.with_duration(video_clip.duration) | |
) | |
tracks.insert(0, music_clip) | |
except Exception as err: | |
print(f"⚠️ Musique ignorée : {err}") | |
final_audio = CompositeAudioClip(tracks).with_duration(video_clip.duration) | |
final_clip = video_clip.with_audio(final_audio) | |
final_clip.write_videofile( | |
output_path, | |
codec="libx264", | |
audio_codec="aac", | |
fps=30, | |
threads=4, | |
preset="medium", | |
ffmpeg_params=["-pix_fmt", "yuv420p"], | |
) | |
print(f"✅ Vidéo générée : {output_path}") | |
video_clip.close() | |
voice_clip.close() | |
if "music_clip" in locals(): | |
music_clip.close() | |
final_audio.close() | |
final_clip.close() | |