「SVGアニメーション GIF 変換」で検索すると、多数のオンライン変換サービスが見つかります。しかし、これらのサービスのほぼ100%はアニメーションSVGに対応していません。実際に試すと、以下のような問題が発生します:

  • 真っ黒な静止画GIFが出力される
  • 最初のフレームだけが静止画として出力される
  • エラーで変換自体が失敗する
  • アニメーションが完全に無視される

私も最初は既存サービスで済ませようと思っていましたが、動くSVGアニメーションを正しくGIFアニメーションに変換できるツールが存在しないことに気づきました。

なぜSVGアニメーションのGIF変換は難しいのか

技術的な壁

SVGアニメーションには複数の実装方法があります:

  1. CSS Animation (@keyframes + animation)
  2. SMIL (<animate>, <animateTransform>)
  3. JavaScript制御(動的な属性変更)

特に問題となるのが、animation-delayを使った順番アニメーションです。複数の要素が時間差で動き始める場合、各要素のタイミングを正確に把握し、フレームごとに再現する必要があります。

既存ツールが対応できない理由

既存のオンライン変換サービスの内部処理:
1. SVGファイルを単一の静止画として読み込む
2. ImageMagickやlibrsvgで処理
3. 静止画GIFとして出力

→ アニメーション情報が完全に無視される

解決策:Seleniumを使った完全なアニメーション再現

開発したツールの革新的なアプローチ

私が開発したツールは、以下の手法でこの問題を解決しました:

def convert_svg_to_gif(self, settings: ConversionSettings):
    # 1. ブラウザ(Chrome)でSVGを実際に表示
    driver = webdriver.Chrome(service=service, options=options)
    
    # 2. JavaScriptでアニメーションを制御
    driver.execute_script("""
        // 特定の時間にアニメーションを固定
        setAnimationTime(progress);
    """)
    
    # 3. 各時点でスクリーンショット
    driver.save_screenshot(frame_file)
    
    # 4. フレームをGIFに結合
    images[0].save(gif_path, save_all=True, append_images=images[1:])

最も困難だった課題:順番アニメーションの正確な再現

問題の具体例

<!-- 4つの要素が0.15秒ずつ遅れて動き始める -->
<rect class="spinner_LWk7" />  <!-- delay: 0s -->
<rect class="spinner_yOMU" />  <!-- delay: 0.15s -->
<rect class="spinner_KS4S" />  <!-- delay: 0.3s -->
<rect class="spinner_zVee" />  <!-- delay: 0.45s -->

このようなSVGを変換する際、以下の課題がありました:

  1. タイミングの検出: .45sのような省略記法への対応
  2. 個別制御: 各要素を独立して制御する必要性
  3. 同期の維持: すべての要素の動きを正確に同期

解決方法:要素ごとの個別タイミング制御

// 各要素のアニメーション情報を保存
const animationInfo = new Map();

// 要素ごとにanimation-delayを適用
animationInfo.forEach((info, el) => {
    const elementStartTime = info.delay;
    const elementDuration = info.duration;
    
    if (currentTime >= elementStartTime) {
        // この要素の経過時間を計算
        const elementTime = currentTime - elementStartTime;
        
        // 負のdelayでアニメーションを特定位置に設定
        el.style.animationDelay = `-${elementTime}s`;
        el.style.animationPlayState = 'paused';
    }
});

もう一つの大きな壁:フレーム数の保持問題

Pillowライブラリの最適化による問題

GIF生成で標準的に使用されるPillowライブラリには、自動最適化機能があります。これが予期しない問題を引き起こしました:

# 問題のあるコード
images[0].save(
    'output.gif',
    save_all=True,
    append_images=images[1:],
    optimize=True  # これが原因!
)

# 結果:33フレーム → 22フレームに勝手に削減される

解決策:フレーム重複防止の工夫

# 解決策1: 最適化を無効化
optimize=False

# 解決策2: 各フレームに微小な差異を追加
for i, frame_file in enumerate(frames):
    img = Image.open(frame_file)
    pixels = img.load()
    width, height = img.size
    
    # 右下の1ピクセルを微調整(視覚的には認識不可能)
    if width > 1 and height > 1:
        r, g, b = pixels[width-1, height-1]
        pixels[width-1, height-1] = (r, g, (b + i) % 256)

予想外の困難

最初は「参考コードもあるし、少し改変するだけ楽だろう」と考えていました。しかし実際は:

  • 順番アニメーション対応: (最も時間がかかった)
  • フレーム保持問題の解決:
  • UI改善とバグ修正:

やってみると時間差で動き出すはずのアニメーションが同時に動きだし、別タイミングで動かすのが特に大変でした。

ツールの実装における技術的工夫

MVCアーキテクチャの採用

保守性を考慮し、Model-View-Controllerパターンで実装:

# Model: ビジネスロジック
class ConversionModel:
    def detect_animation_info(self, svg_content: str) -> tuple:
        """SVGからアニメーション情報を抽出"""
        # 正規表現でduration, delayを検出
        
    def convert_svg_to_gif(self, settings: ConversionSettings):
        """実際の変換処理"""

# View: UI
class ConversionView(tk.Tk):
    def _create_widgets(self):
        """tkinterでGUI構築"""

# Controller: 仲介役
class ConversionController:
    def start_conversion(self, settings):
        """非同期で変換を実行"""

パフォーマンス最適化

# 高速化のための設定
options = webdriver.ChromeOptions()
options.add_argument("--headless")  # ヘッドレスモード
options.add_argument("--disable-gpu")  # GPU無効化
options.add_argument("--force-device-scale-factor=2")  # 高解像度

# 並列処理でUIの応答性を維持
thread = threading.Thread(
    target=self.model.convert_svg_to_gif,
    args=(settings,)
)
thread.daemon = True
thread.start()

使用方法と実行結果

インストール

# 必要なライブラリ
pip install pillow selenium webdriver-manager

# ツールの実行
python svg2gif-converter.py

変換例

  • 入力: blocks-scale-black-36.svg(1.65秒、4要素の順番アニメーション)
  • 出力: 完全に動作するGIFアニメーション(33フレーム、適切なタイミング)

他の変換ツールとの比較

ツール/サービス 静止SVG アニメーションSVG animation-delay対応 フレーム制御
CloudConvert
Convertio
SVG to GIF (オンライン)
ImageMagick 部分的 限定的
本ツール

まとめ:

SVGアニメーションは素晴らしい技術ですが、すべての環境で動作するわけではありません:

  • メールクライアントではSVGアニメーションが動かない
  • 一部のSNSではSVGがサポートされない
  • PowerPointなどのプレゼンツールではGIFの方が扱いやすい

既存のツールでは不可能だった「動的SVGの動的GIF変換」を実現したこのツールは、
ぶっちゃけSVGの方が楽なんですが、GIFしかわからないからGIFでくれと言ってきた開発者のニーズに応えるために作成されました。
今どき、SVGファイル渡して、表示されないって言ってくるってどんな開発者だよ!


GitHubリポジトリ: svg2gif-converter

ライセンス: MIT License

バージョン: v1.1.2(2025年9月)