当前位置:首页>python>Python实现mp4嵌入图片

Python实现mp4嵌入图片

  • 2026-09-02 19:24:01
Python实现mp4嵌入图片
嵌入单张图片
# complete_script.pyimport osfrom moviepy import VideoFileClip, AudioFileClip, ImageClipdef mp4_to_mp3_to_mp4(mp4_path, image_path, final_video_path="final_output.mp4"):    """    一键处理:MP4 -> 提取音频 -> 与图片合成 -> 新MP4    """    print("="*30)    print("开始处理...")    print("="*30)    # 1. 提取音频    mp3_path = os.path.splitext(mp4_path)[0] + ".mp3"    try:        print("[1/3] 提取音频...")        with VideoFileClip(mp4_path) as video:            audio = video.audio            audio.write_audiofile(mp3_path, codec='mp3', bitrate='320k')            print(f"✅ 音频提取完成: {mp3_path}")    except Exception as e:        print(f"❌ 音频提取失败: {e}")        return    # 2. 合成视频    try:        print("\n[2/3] 合成视频...")        with AudioFileClip(mp3_path) as audio_clip:            duration = audio_clip.duration            image_clip = ImageClip(image_path).with_duration(duration)            final_clip = image_clip.with_audio(audio_clip)            final_clip.write_videofile(final_video_path, fps=24, codec='libx264', audio_codec='aac')            print(f"✅ 视频合成完成: {final_video_path}")    except Exception as e:        print(f"❌ 视频合成失败: {e}")        return    finally:        # 3. 清理临时文件(可选)        # 如果你不想保留中间的 MP3 文件,可以取消下一行的注释        # os.remove(mp3_path)        print("\n[3/3] 清理完成")    print("="*30)    print("🎉 所有操作成功完成!")    print("="*30)# 使用示例if __name__ == '__main__':    # 请将下面的路径替换为你自己的文件路径    video = "我的视频.mp4"    image = "我的图片.jpg"    mp4_to_mp3_to_mp4(video, image)
嵌入多张图片实现切换播放
# slideshow_transition_final.pyimport osfrom moviepy import VideoFileClip, AudioFileClip, ImageClip, concatenate_videoclips, vfx, CompositeVideoClip, ColorClipdef extract_audio_from_mp4(mp4_path, mp3_path=None):    if mp3_path is None:        mp3_path = os.path.splitext(mp4_path)[0] + ".mp3"    print(f"[1/3] 正在从视频提取音频: {mp4_path}")    try:        with VideoFileClip(mp4_path) as video:            if video.audio is None:                print("❌ 视频中没有音频轨道")                return None            video.audio.write_audiofile(mp3_path, codec='mp3', bitrate='320k')            print(f"✅ 音频提取成功: {mp3_path}")            return mp3_path    except Exception as e:        print(f"❌ 音频提取失败: {e}")        return Nonedef resize_image_keep_aspect(img_clip, target_size, bg_color=(0, 0, 0)):    w, h = img_clip.size    target_w, target_h = target_size    scale = min(target_w / w, target_h / h)    new_w = int(w * scale)    new_h = int(h * scale)    img_resized = img_clip.resized(new_size=(new_w, new_h))    bg_clip = ColorClip(size=target_size, color=bg_color, duration=img_clip.duration)    # 新版 moviepy 正确居中写法    x_pos = (target_w - new_w) // 2    y_pos = (target_h - new_h) // 2    final_clip = CompositeVideoClip(        [bg_clip, img_resized.with_position((x_pos, y_pos))]    )    return final_clipdef create_slideshow_with_transitions(image_paths, output_video_path, audio_path,                                      duration_per_image=3, transition_duration=0.5,                                      target_size=(1920, 1080), bg_color=(0, 0, 0)):    print(f"\n[2/3] 开始创建带转场效果的幻灯片,共 {len(image_paths)} 张图片")    print(f"   每张图片展示 {duration_per_image} 秒,转场时长 {transition_duration} 秒")    print(f"   目标分辨率: {target_size},背景色: {bg_color}")    try:        with AudioFileClip(audio_path) as audio_clip:            total_audio_duration = audio_clip.duration            clips = []            for i, img_path in enumerate(image_paths):                if not os.path.exists(img_path):                    print(f"⚠️ 警告: 图片不存在,跳过 {img_path}")                    continue                img_clip = ImageClip(img_path).with_duration(duration_per_image)                img_clip = resize_image_keep_aspect(img_clip, target_size, bg_color)                fade_in_duration = min(transition_duration, duration_per_image / 2)                fade_out_duration = min(transition_duration, duration_per_image / 2)                img_clip = img_clip.with_effects([                    vfx.FadeIn(fade_in_duration),                    vfx.FadeOut(fade_out_duration)                ])                clips.append(img_clip)                print(f"   已加载图片 {i+1}: {os.path.basename(img_path)}")            if not clips:                print("❌ 没有有效图片")                return None            video_clip = concatenate_videoclips(clips, method="compose")            if video_clip.duration > total_audio_duration:                video_clip = video_clip.subclipped(0, total_audio_duration)            elif video_clip.duration < total_audio_duration:                loops_needed = int(total_audio_duration / video_clip.duration) + 1                looped_clips = [video_clip] * loops_needed                video_clip = concatenate_videoclips(looped_clips, method="compose")                video_clip = video_clip.subclipped(0, total_audio_duration)            video_clip = video_clip.with_audio(audio_clip)            print(f"\n[3/3] 正在渲染最终视频...")            video_clip.write_videofile(                output_video_path,                codec='libx264',                audio_codec='aac',                fps=24,                threads=4            )            print(f"✅ 视频生成成功: {output_video_path}")            return output_video_path    except Exception as e:        print(f"❌ 视频合成失败: {e}")        return None# --- 使用示例 ---if __name__ == '__main__':    input_mp4 = "input.mp4"    output_video = "output_slideshow_final.mp4"    image_folder = "images"    audio_file = extract_audio_from_mp4(input_mp4)    if audio_file is None:        print("程序终止,音频提取失败")        exit()    image_extensions = ('.jpg', '.jpeg', '.png', '.bmp', '.tiff')    image_files = []    if os.path.isdir(image_folder):        for file in sorted(os.listdir(image_folder)):            if file.lower().endswith(image_extensions):                image_files.append(os.path.join(image_folder, file))    create_slideshow_with_transitions(        image_paths=image_files,        output_video_path=output_video,        audio_path=audio_file,        duration_per_image=3,        transition_duration=0.5,        target_size=(1920, 1080),        bg_color=(0, 0, 0)    )

最新文章

随机文章