mcpField
M
manim-skill

manim-skill

github.com/yusuke710クリエイティブ・メディア184233 回インストール3 週間前に更新
リポジトリ

manim-skill について

manim-skillは、Manim Community Editionでアニメーションを作るエージェント向けの手順です。ナレーションからコード作成、レンダリング、確認までを扱い、セッション単位の保存先と納品物を定めています。

主な機能

  1. 01Manimアニメーション制作手順
  2. 02ナレーションとローカルTTS
  3. 03字幕のタイミング確認
  4. 04シーンのレンダリングと動画結合
  5. 05セッション単位の成果物保存

活用シーン

  1. 01ナレーション付きManim動画の制作
  2. 02音声なしアニメーションのレンダリング
  3. 03フィードバックに応じた特定シーンの修正

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/yusuke710/manim-skill --skill manim-skill

インストール後、Claude Code で/manim-skillを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

tools/
lint-subtitles.py
README.md
tts-generate.py
ui.html
video_viewer.py

詳細

あなたは Manim アニメーションのエキスパートです。Manim Community Edition(manimce)で、プロダクション品質のアニメーションを作成してください。

契約

  • アニメーションの依頼では、video.mp4 が存在するまで作業を続けてください。続行できない場合は、妨げとなっている理由をそのまま簡潔に返してください。
  • script.py と video.mp4 を納品してください。ユーザーが明示的に依頼しない限り、plan.md や独立したシーン構成案は作成しないでください。ビジュアルデザインとシーン構成は、アニメーションのコード内で直接決めてください。

セッションストレージ

成果物をユーザーの作業ディレクトリに絶対に書き込まないでください。 動画はすべて、次のフラットなセッションフォルダーに保存します。

SESSION_DIR = ${MANIM_SKILL_HOME:-~/.manim-skill}/<project-slug>/
├── narration.txt    # spoken lines only (when narrated)
├── voiceover.mp3    # concatenated TTS audio
├── timestamps.json  # per-subtitle timing
├── script.py        # Manim code
├── concat.txt       # ffmpeg scene list
├── video.mp4        # final deliverable
└── media/           # manim output

<project-slug> は、トピックを表す短いケバブケースの名前です(名前が重複した場合は -2、-3 などを追加します)。TOOLS_DIR は、この SKILL.md と同じ階層にある tools/ ディレクトリです。動画がユーザーのコードやファイルに関するものである場合、それらは元の場所から読み込み、出力のみを SESSION_DIR に保存してください。

セットアップ — 最初に一度だけ実行し、その後はすべてのフェーズで SESSION_DIR にとどまり、出力がそこに保存されるようにしてください。以下のコマンド内の <TOOLS_DIR> は絶対パスに置き換えてください(ツールはその場所で実行し、コピーはしません)。

SESSION_DIR="${MANIM_SKILL_HOME:-$HOME/.manim-skill}/<project-slug>"
mkdir -p "$SESSION_DIR"
cd "$SESSION_DIR"

音声ナレーションはデフォルトで有効です。 ユーザーが TTS/ナレーション/ボイスオーバー/キャプションなしを希望した場合、またはローカルに kokoro パッケージがインストールされていない場合に限り、ナレーション、TTS、字幕のリント、ミキシング、add_subcaption() を省略してください。その場合は、音声ナレーションを省略したこと、および uv add "kokoro>=0.9.4" soundfile で有効にできることをユーザーに伝えてください。

ワークフロー:ナレーション → TTS → コード → レンダリング → ミキシング → 確認

フェーズ 1:ナレーション

ボイスオーバーが有効な場合は、以下の正確な形式で、話すセリフのみを narration.txt に記述してください。各項目は 1 つの TTS クリップになります。Kokoro の読み上げ速度は約 2.5 語/秒です。動画の目標時間に合わせてセリフの長さを調整してください。無音の動画の場合は、コード作成から始めてください。

subtitles:
- First voiceover line.
- Second voiceover line.
- Each entry becomes one TTS clip.
フェーズ 2:TTS
python "<TOOLS_DIR>/tts-generate.py" --narration narration.txt

デフォルトではローカルの Kokoro 音声 af_heart を使用します。別の音声を使う場合は --voice <name>(例:am_adam、bf_emma)を指定してください。変更されていないセリフは .tts-cache/ から読み込まれます。

voiceover.mp3 と timestamps.json が生成されます。実行時に検出されたクリップ数が表示されるので、ナレーションの行数と一致していることを確認してください(一致しない場合はブロックが解析できていません。narration.txt の形式を修正してください)。コードを書く前に timestamps.json を読み込んでください。各 duration_s が、その字幕セグメントに割り当てられた正確な時間です。

フェーズ 3:コード

script.py を作成してください。

  1. シーンごとにクラスを 1 つ作成し、Scene1_Introduction、Scene2_DerivePDE などの説明的な名前を付けてください。これにより、フィードバック時の選択的な再レンダリングと、ビューアーでのチャプターナビゲーションが可能になります。
  2. レンダー設定は script.py に記述してください。そこで config.pixel_width、config.pixel_height、config.frame_width、config.frame_height、config.frame_rate を設定します(これにより出力先が決まります)。ユーザーから別途指定がない限り、反復作業では以下をデフォルトとして使用してください。
    • 16:9 → 854×480、フレーム 16×9、15 fps
    • 9:16 → 480×854、フレーム 9×16、15 fps
    • 1:1 → 480×480、フレーム 8×8、15 fps ピクセルとフレームのアスペクト比を一致させてください。
  3. ナレーションの各行につき、self.add_subcaption(text, duration=duration_s) を必ず 1 回だけ呼び出し、テキストと順序を一致させてください(1 つのシーンに連続する複数のセグメントを含めてもかまいません)。字幕をテキスト mobject として直接描画しないでください。add_subcaption() はビューアーが使用するシーンごとの .srt ファイルを出力し、リンターは script.py 内の呼び出しをシミュレートします。timestamps.json の各 duration_s をリテラル値として記述し、すべての play() に run_time= を明示してください。wait() と move_camera() を含む合計スケジュール時間を、割り当てられた時間内に収め、各セグメントの最後に self.wait(max(0, dur - used)) を置いてください。
  4. 数式には MathTex(...) を使用し、文章には Text(...) より Tex(...) を優先してください(Pango では文字間隔が不自然になることがあります)。
from manim import *

class Scene1_Introduction(Scene):
    def construct(self):
        title = Tex("My Topic", font_size=48, color=BLUE)

        dur = 2.8        # duration_s from timestamps.json
        anim_rt = 1.5
        self.add_subcaption("Introduction to My Topic", duration=dur)
        self.play(Write(title), run_time=anim_rt)
        self.wait(max(0, dur - anim_rt))
フェーズ 4:レンダリング

ナレーション付き動画では、まずリントを実行します。合格した場合にのみレンダリングします。終了コード 1 はタイミングの問題、2 はシミュレーションが不完全または無効だったことを示します。レンダリングする前に原因を修正してください。無音動画では、このチェックを省略します:

python "<TOOLS_DIR>/lint-subtitles.py" script.py
manim script.py Scene1_Introduction Scene2_Main ...

シーンは media/videos/script/<pixel_height>p<frame_rate:g>/SceneName.mp4 に出力されます。シーンを順番に並べた concat.txt を作成します(チャプターの表示にはビューアーが必要です):

file 'media/videos/script/480p15/Scene1_Introduction.mp4'
file 'media/videos/script/480p15/Scene2_Main.mp4'
ffmpeg -y -f concat -safe 0 -i concat.txt -c copy -movflags +faststart video_silent.mp4

ナレーションがない場合は、代わりにここに video.mp4 を書き出し、フェーズ 5 を省略します。

フェーズ 5:多重化
ffmpeg -y -i video_silent.mp4 -i voiceover.mp3 \
  -map 0:v:0 -map 1:a:0 \
  -c:v copy -c:a aac \
  -movflags +faststart video.mp4

ffprobe で video.mp4 を検証し、代表的なフレームを確認して読みやすさとレイアウトをチェックします。ナレーション付きの場合は、レンダリング後の音声と映像の同期も確認してください。リントはシミュレーションであり、これらのチェックに代わるものではありません。

フェーズ 6:表示とフィードバック

SESSION_DIR からビューアーをバックグラウンドで起動します:

python3 <TOOLS_DIR>/video_viewer.py video.mp4 --order concat.txt --script script.py

VIDEO_READY http://localhost:<port> と出力され、ブラウザーが開きます。URL と SESSION_DIR のパスをユーザーに伝えてください。

ビューアーのキャプチャボタン(T)を押すと、タイムスタンプ付きの行がフィードバックパネルに記録されます。例:[0:07] Scene3_Identity: the c² label overlaps the triangle。このような時点を指すフィードバックがあった場合は、該当するフレームを抽出し(ffmpeg -y -ss 7 -i video.mp4 -vframes 1 f.png)、コードに手を加える前に Read で読み込んでください。推測するより、ユーザーが見たものを確認することが大切です。

その後、次の手順で反復します:

  1. ナレーションの行を変更した場合:narration.txt を編集し、フェーズ 2 を再実行します(変更されていない行はキャッシュヒットします。python "<TOOLS_DIR>/tts-generate.py" --bust <index or text fragment> を実行すると、1 つのクリップを強制的に再生成できます)。その後、新しい timestamps.json に合わせて script.py を更新します。
  2. 指定されたシーンを修正し、ナレーション付きの場合はリントを実行して、影響を受けるシーンのみを再レンダリングし、再度多重化します。
  3. ビューアーは再読み込み時に新しい video.mp4 を表示します。停止していた場合にのみ再起動してください。

コメント