「SVGアニメーション GIF 変換」で検索すると、多数のオンライン変換サービスが見つかります。しかし、これらのサービスのほぼ100%はアニメーションSVGに対応していません。実際に試すと、以下のような問題が発生します:
- 真っ黒な静止画GIFが出力される
- 最初のフレームだけが静止画として出力される
- エラーで変換自体が失敗する
- アニメーションが完全に無視される
私も最初は既存サービスで済ませようと思っていましたが、動くSVGアニメーションを正しくGIFアニメーションに変換できるツールが存在しないことに気づきました。
なぜSVGアニメーションのGIF変換は難しいのか
技術的な壁
SVGアニメーションには複数の実装方法があります:
- CSS Animation (
@keyframes
+animation
) - SMIL (
<animate>
,<animateTransform>
) - 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を変換する際、以下の課題がありました:
- タイミングの検出:
.45s
のような省略記法への対応 - 個別制御: 各要素を独立して制御する必要性
- 同期の維持: すべての要素の動きを正確に同期
解決方法:要素ごとの個別タイミング制御
// 各要素のアニメーション情報を保存
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月)