如何写动图合成脚本

wen 实用脚本 30

本文目录导读:

如何写动图合成脚本

  1. 方案一:使用Python + Pillow(最简单)
  2. 方案二:使用FFmpeg(性能更好)
  3. 方案三:进阶功能实现
  4. 完整脚本示例
  5. 使用建议

我来帮你编写动图合成脚本,这里提供Python和FFmpeg两种主流方案。

使用Python + Pillow(最简单)

from PIL import Image
import os
def create_gif_from_images(image_paths, output_path, duration=100, loop=0):
    """
    将多张图片合成为GIF动图
    参数:
        image_paths: 图片路径列表
        output_path: 输出GIF路径
        duration: 每帧持续时间(毫秒)
        loop: 循环次数(0为无限循环)
    """
    if not image_paths:
        raise ValueError("图片列表不能为空")
    # 打开所有图片
    frames = [Image.open(img_path) for img_path in image_paths]
    # 统一尺寸(可选)
    # target_size = frames[0].size
    # frames = [img.resize(target_size) for img in frames]
    # 保存为GIF
    frames[0].save(
        output_path,
        save_all=True,
        append_images=frames[1:],
        duration=duration,
        loop=loop
    )
    print(f"GIF已保存到: {output_path}")
# 使用示例
if __name__ == "__main__":
    # 方式1:指定图片列表
    images = ['frame1.png', 'frame2.png', 'frame3.png']
    create_gif_from_images(images, 'output.gif', duration=200)
    # 方式2:使用通配符匹配(需要清理列表)
    import glob
    images = sorted(glob.glob('frames/*.png'))  # 确保排序正确
    create_gif_from_images(images, 'animation.gif')

使用FFmpeg(性能更好)

从图片序列生成GIF

# 基础命令
ffmpeg -framerate 10 -i frames/frame_%04d.png output.gif
# 参数说明:
# -framerate: 帧率(fps)
# -i: 输入文件模式(%04d表示4位数字编号)
# 高级配置
ffmpeg -framerate 24 \
       -i input_%03d.png \
       -vf "fps=10,scale=640:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" \
       output.gif

从视频提取并合成GIF

# 从视频中截取片段转为GIF
ffmpeg -i input.mp4 -ss 00:00:05 -t 3 -vf "fps=10,scale=320:-1" output.gif
# 使用调色板优化质量
ffmpeg -i input.mp4 -vf "fps=15,scale=480:-1:flags=lanczos,palettegen" palette.png
ffmpeg -i input.mp4 -i palette.png -filter_complex "fps=15,scale=480:-1[x];[x][1:v]paletteuse" output.gif

Python调用FFmpeg

import subprocess
import os
def create_gif_with_ffmpeg(image_dir, output_path, fps=10, scale=480):
    """
    使用FFmpeg合成GIF
    参数:
        image_dir: 图片文件夹
        output_path: 输出路径
        fps: 帧率
        scale: 缩放宽度
    """
    cmd = [
        'ffmpeg',
        '-framerate', str(fps),
        '-i', os.path.join(image_dir, 'frame_%04d.png'),
        '-vf', f'fps={fps},scale={scale}:-1:flags=lanczos',
        '-y',  # 覆盖输出文件
        output_path
    ]
    try:
        subprocess.run(cmd, check=True)
        print(f"GIF已保存到: {output_path}")
    except subprocess.CalledProcessError as e:
        print(f"合成失败: {e}")
# 获取文件列表并排序
def get_sorted_images(dir_path, extensions=['.png', '.jpg', '.jpeg']):
    files = []
    for ext in extensions:
        files.extend([f for f in os.listdir(dir_path) if f.endswith(ext)])
    return sorted(files, key=lambda x: int(''.join(filter(str.isdigit, x)) or 0))
# 使用示例
if __name__ == "__main__":
    create_gif_with_ffmpeg('frames/', 'animation.gif')

进阶功能实现

添加文字水印

from PIL import Image, ImageDraw, ImageFont
def create_gif_with_text(images, output_path, text="Sample", duration=100):
    frames = []
    font = ImageFont.load_default()  # 或加载自定义字体
    for img_path in images:
        img = Image.open(img_path).convert('RGB')
        draw = ImageDraw.Draw(img)
        # 添加文字
        text_position = (10, 10)
        draw.text(text_position, text, fill=(255, 255, 255), font=font)
        frames.append(img)
    # 保存
    frames[0].save(output_path, save_all=True, 
                   append_images=frames[1:], 
                   duration=duration, loop=0)

调整GIF速度

def adjust_gif_speed(input_gif, output_gif, speed_factor=0.5):
    """
    调整GIF速度
    speed_factor: 速度因子(0.5=慢速,2.0=快速)
    """
    from PIL import ImageSequence
    gif = Image.open(input_gif)
    frames = []
    for frame in ImageSequence.Iterator(gif):
        frames.append(frame.copy())
    # 调整每帧持续时间
    durations = [frame.info.get('duration', 100) * speed_factor 
                 for frame in frames]
    frames[0].save(output_gif, save_all=True, 
                   append_images=frames[1:], 
                   duration=durations, loop=0)

完整脚本示例

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import argparse
import os
from PIL import Image
import glob
def create_gif(input_pattern, output, duration=100, reverse=False, loop=0):
    """
    完整的GIF合成工具
    """
    # 获取所有图片
    images = sorted(glob.glob(input_pattern))
    if not images:
        print(f"未找到匹配的图片: {input_pattern}")
        return
    # 可选:反转帧序列
    if reverse:
        images = images[::-1]
    # 加载图片
    frames = [Image.open(img) for img in images]
    # 统一尺寸
    if len(frames) > 1:
        target_size = frames[0].size
        frames = [img.resize(target_size) for img in frames]
    # 保存GIF
    frames[0].save(
        output,
        save_all=True,
        append_images=frames[1:],
        duration=duration,
        loop=loop,
        optimize=False
    )
    print(f"成功创建GIF: {output}")
    print(f"包含 {len(frames)} 帧")
    print(f"循环次数: {'无限' if loop == 0 else loop}")
def main():
    parser = argparse.ArgumentParser(description="GIF动图合成工具")
    parser.add_argument("-i", "--input", required=True, 
                       help="输入图片模式 (如: frames/*.png)")
    parser.add_argument("-o", "--output", default="output.gif", 
                       help="输出GIF文件名")
    parser.add_argument("-d", "--duration", type=int, default=200, 
                       help="每帧持续时间(毫秒)")
    parser.add_argument("-r", "--reverse", action="store_true", 
                       help="反转帧序列")
    parser.add_argument("-l", "--loop", type=int, default=0, 
                       help="循环次数 (0=无限)")
    args = parser.parse_args()
    create_gif(args.input, args.output, args.duration, 
               args.reverse, args.loop)
if __name__ == "__main__":
    main()

使用建议

  1. 图片命名:建议使用统一格式,如 frame_0001.png, frame_0002.png
  2. 尺寸控制:GIF文件大小与分辨率、颜色数直接相关
  3. 色彩优化:使用调色板(palette)可以减少文件大小
  4. 帧率选择:常见GIF帧率为10-15fps

需要我针对特定场景(如截屏合成、视频转GIF等)提供更详细的实现吗?

抱歉,评论功能暂时关闭!