3Blue1Brownのアニメーション制作方法[動画]
(youtube.com)- 3Blue1Brownのビジュアライゼーションは、Grant Sandersonが作った Pythonライブラリ Manim でコード化されており、動画ではBen Sparksとともに実際の制作フローをたどる
- Manimは、Grant個人の制作環境と、ドキュメント・テスト・Issue対応が強化された Manim Community に分かれており、入門者には通常コミュニティ版が向いている
- 作業はSublime TextとPythonターミナルを接続してコード片をすぐ実行し、checkpoint pasteで中間状態をキャッシュして反復的に試す方式に近い
- デモでは Lorenz attractor をSciPyで計算したあと、曲線、点、updater、3Dカメラ、残像効果を組み合わせ、近い初期条件が分岐していく過程を見せる
- 最終シーンは事前実行でエラーと長さを確認したうえでMP4にレンダリングし、その後編集ツールに取り込んでYouTube動画制作の工程へ進む
Manimの出発点と2つのバージョン
- 3Blue1Brownアニメーションの中核ツールは、Grant Sandersonが自ら作った Pythonライブラリ Manim である
- Manimはすべてのシーンをプログラムで構成し、3Blue1Brownの制作方式に合わせた カスタムツール として発展してきた
- Grantは学部課程を終えるころ、数学関数を変換としてよりよく可視化するためにPythonコードを書き始め、このコードがチャンネル最初の動画とともに始まった
- 動画が増えるにつれてツールが改善され、改善されたツールがさらに複雑な動画を可能にする流れが続いた
- 最近のホログラム動画の視覚効果は、2〜3年前ならはるかに難しかったはずだが、長年にわたる ワークフロー改善 によって制作の難度が下がった
Manim CommunityとGrantの個人版
- Grantは動画で使ったコードとManim本体をGitHubで公開してきた
- ただし動画制作とオープンソース管理を並行する中で、IssueやPull Requestへの対応は十分ではなかった
- コミュニティはより堅牢なツールを作るためにリポジトリをフォークし、このバージョンが Manim Community である
- IssueやPull Requestへの対応がより活発
- テストとドキュメントがより整っている
- 初めて始める人には一般的に推奨される
- 動画デモでは、Grantが直接使っているバージョンが用いられている
- ここ数年で、より インタラクティブ かつ高速に動作するよう改善されている
- ドキュメント化やテストを重視するユーザーには、コミュニティ版のほうが適している
コードを書いてすぐ確認する制作方式
- Manimの各シーンはPythonの class として書かれ、
constructメソッドの中にレンダリングするコードが入る - 円、四角形、テキストなどのオブジェクトを画面に追加し、
playメソッドでWriteやTransformのようなアニメーションを実行する - ほとんどのオブジェクトはデフォルトで画面中央に置かれ、
to_edgeやshiftのような操作で位置を変える - Grantの作業環境は、Sublime TextとPythonターミナルを併用する方式である
- コード行をコピーしてターミナルで実行すると、現在のシーンにすぐ反映される
- Sublimeのショートカットが、選択したコードをコピーして実行する過程を自動化する
- ターミナルが現在のシーンと接続されているため、修正結果を即座に確認できる
- 長いシーンでは、コード全体を毎回実行し直すのではなく、中間区間だけを繰り返し試せる機能が重要になる
- ホログラム動画の例は、4分30秒のMP4を作る長いPythonコードだった
- 長いシーンは多くのコンテキストとローカル変数を共有するため、1つのファイルに置く方式が有用だった
checkpoint pasteは、特定のコメント位置のシーン状態をキャッシュし、その状態へ戻したうえで選択したコードを実行する- この方式は、純粋なテキストファイルと Jupyter notebook の中間のようなワークフローに近い
Manimアニメーションの基本的な感覚
- Manimの重要な哲学の1つは、「何でも何にでも変換できる」という点である
- たとえば、
hello worldテキストの最初の文字Hを円に変換するシーンを作れる- 円をシーンに直接追加しなくても、変換先として定義しておける
- テキストは文字のグループなので、個々の文字を取り出して操作できる
Transformは基本的に滑らかな rate function を使う- デフォルトは
smoothで、cubic bezierベースの滑らかな動きに見える linearを使うと、開始と終了がより硬く感じられる- 数学的な時間進行をそのまま見せる必要がある場合には
linearが必要になる
- デフォルトは
- こうした細かな調整が、単に「動くシーン」と「見栄えのよいシーン」の差を生む
Writeのように3Blue1Brown動画でおなじみのアニメーションも、Manimの組み込み関数として呼び出せる
Lorenz attractorデモ
- デモの中心例は Lorenz attractor である
- 3次元微分方程式から現れる形である
- 3D空間内の点が時間とともにどのように変化するかを決定論的な規則で定める
- 初期条件を複数変えると、興味深い視覚的結果が得られる
- Grantは数学計算部分を作る際、ChatGPTにPython関数の作成を依頼した
- SciPyの
integrateと初期値問題のソルバー関数が使われた - 生成されたコードはMatplotlibでのレンダリングを前提としており、その後Manim向けに調整された
- SciPyの
- Lorenz方程式の状態は
x、y、z座標を持ち、各瞬間の導関数を計算する関数として表現される - 数値解の結果は時間値と
x、y、zの値として得られ、Grantはそれを扱いやすく包む wrapper を用意している- SciPy側の表現では
yを出力のように扱うため、やや紛らわしい場合がある - 状態配列と転置形式を、自分が使いやすい方式に合わせている
- SciPy側の表現では
- 初期条件を
(0, 0, 0)にするとすべての値が0になって適切ではなかったため、1つの座標を10に変えると興味深い点群が生成された - Manimでは、計算された点を曲線に変えるために
set_points_as_cornersを使う - 座標軸の座標系をManim座標系に変えるため、
coords_to_pointの短縮形であるc2pを使う - Pythonの
*構文は、iterableを関数の引数として展開して渡すときに使う- 例では、
x、y、z座標のリストを分離して関数に渡している
- 例では、
近い初期条件が分岐するシーン
- Lorenz attractorの可視化の核心は、互いに非常に近い初期条件が、最初は似た動きをしながら、後には分岐していく様子である
- Grantは初期条件のリストを作り、
z座標を小さなepsilonだけ異なるように設定した- 最初は2つの条件から始めた
- その後10個の条件に増やした
- 複数の曲線を入れるために
VGroupを使う- ベクトル化されたオブジェクトグループであるという情報を与えると、レンダリングをより速くできる
- 各曲線の終点には glow dot を付ける
GlowDotは、動く点を視覚的に見やすく見せるために作っておいたオブジェクトである- 各点にはupdaterが付いており、毎フレームごとに曲線の終点へ移動する
zipは、点と曲線、状態と色のように対応するリストを並列に走査するときに使う- 2つのリストの長さが異なる場合、短いほうが終わる地点で止まる
color_gradientで状態数と同じ数の色を作り、長さを合わせる
ShowCreationで曲線を描くときにデフォルトのsmoothingを使うと実際の時間進行が歪む可能性があるため、力学系をそのまま見せる部分では linear rate function を使う- 近い初期条件は序盤にはほぼ一緒に動くが、時間が経つとまったく別の位置にあるかのように広がる
- Lorenz attractorは、単純な点や周期ではなく特定の形に引き寄せられながらも、正確な位置は初期条件に敏感な strange attractor として扱われる
インタラクティブモードの回避コードとシーン効果
- デモ中に
globals().update(locals())のような「呪われた」コードが登場する - このコードは、ManimのIPython embed環境で関数が外側のスコープの変数を見られない問題を避けるための一時的な回避策である
- 通常のPythonスクリプトでは同じコードが正常に動作する
- Manimの埋め込みインタラクティブ環境では
NameErrorが発生する場合がある - ローカル変数をグローバル変数辞書に入れて問題を回避する
- 実際のライブラリコードならこの方式は不適切だが、シーン開発用の一時的なインタラクティブセッションではリスクは相対的に小さい
- よりよい方式は、関数が必要な変数を引数として明示的に受け取るようにすることだ
- 曲線を時間とともに消していくには
FadeOutを使えるplayのrun_timeをevolution timeに合わせると、曲線がその時間のあいだ徐々に透明になる
- 点の後ろに残像を残す効果は
TracingTailで実装する- 1つの点を追いかける尾を作れる
time_tracedを1秒から3秒に増やすと、より長い時間の尾が見える- 10個の点それぞれに尾を付けると、複数の軌道が広がる様子をより鮮明に見られる
3Dカメラと数式処理
- Manimのシーンは基本的に3D座標を持てるが、3Blue1Brownのほとんどのシーンは教育上の理由から2Dの黒板のように見える構成になっている
- Lorenz attractorには3Dが必要なので、3D軸を追加する
- 3D画面では奥行き感を保つため、カメラがゆっくり回転したり移動したりする効果が有用である
- Grantは現在のカメラ位置をクリップボードに保存するショートカットを使う
frame.animate.reorient(...)という形でカメラフレームを特定の位置へアニメーション化する
- 数式はLaTeXオブジェクトとしてシーンに追加できる
- MathPixを使うと、画面上の方程式をOCRで読み取ってLaTeXやSVGとして取得できる
- 3Dシーンで数式を画面に固定するには
fix_in_frameを使う
- LaTeX数式の特定の変数には色を付けられる
- 例では
x、y、zをそれぞれ別の色に指定している - テキストを数学的な構成要素に分けて強調したり変換したりする機能は、数学の説明に有用である
- 例では
- Manimには文字列を対応させて変換する特殊なtransformもある
A^2、B^2のような項が、次の行の同じ文字列位置へ自然に移動する- 文字列ベースのマッチングは、アナグラムのアニメーションのように文字を対応する位置へ送る効果も作れる
flash aroundやindicateのようなアニメーションで、数式の特定の文字や項を強調できる
レンダリングと実際の制作フロー
- シーンが気に入ったら、ManimコマンドでPythonファイルとシーン名を指定してレンダリングする
pre-runは、アニメーション全体を実際に使う前にざっと確認する段階である- 全体の長さを推定する
- 中間レンダリングの途中ではなく、事前にエラーを見つけるのに役立つ
Wはファイルに書き出すオプションで、Finder関連のオプションはmacOS Finderで結果ファイルを表示する用途に使われる- 最終結果はMP4ファイルとしてレンダリングされる
- Grantは通常4Kでレンダリングするため、より時間がかかる場合がある
- レンダリングされたファイルは、その後編集ツールに取り込んで編集する
- 以前のManimの使い方は、主にコマンドラインでシーンをレンダリングしてMP4を確認する反復だった
- その後、OpenGL実装へ切り替えていた時期と近いタイミングでインタラクティブシェルベースの作業フローが生まれ、コードをハイライトしてすぐ結果を見る方式へ変わった
- Grantの具体的なワークフローは、Sublime TextのスクリプトとTerminus拡張に依存している
- 他のテキストエディタでも似た動作をまねることはできる
- Visual Studio系の環境でも同じ形の流れを作れる
- 機能を探すときは、サンプルシーン、ライブラリの
animationフォルダ、過去動画のコードがある3b1b/videosGitHubリポジトリを活用できる - GrantはCopilotよりも、もっと単純な自動補完を好んでいる
- Manimでは、自分が望む動作をすでに分かっている場合が多い
- 要望を英語よりコードで表現するほうが、より自然に感じられる
1件のコメント
Hacker News のコメント
3B1B は本当にすごい仕事をしている
個人的に彼の YouTube 動画にはものすごく助けられたし、高校や工学部で数学をこういうふうに教えてくれたらいいのにと思う
https://sinerider.com/ も見る価値がある
Grant Sanderson の 3B1B の仕事を時々手伝っている友人が作ったゲームで、LineRider のようにトラックを作るが、それを数式で作るという優れた数学教育ゲーム
3B1B と SineRider はどちらも、関数合成について直感的に理解するうえで何より大きな影響を与えてくれた
リアルタイムでレンダリングエンジンのバグを見つけ、回避策まで見つけ出した場面が印象的だった
https://youtu.be/rbu7Zu5X1zI?feature=shared&t=693
それでも印象的な仕事ではある
場所と原因を把握し、ライブで回避策を思いついたということは、自分のツールを改善することに時間を投じているということで、たまにではなく積極的にやっているということだ
それでもやはり素晴らしいと思う
右下にあった Python 対話型 REPL がどう動いているのか気になった
追記: 完全にカスタムのワークフローのようだ: https://github.com/3b1b/videos?tab=readme-ov-file#workflow
何年も声だけ聞いて顔を見ていなかったあとで顔を見ると、突然不気味の谷のど真ん中に入ったような感じがして笑える
最近の動画いくつかでは、司会者、インタビュアー、ナレーターのように振る舞っていた
veratasium のように、制作者が代わりにいくつかの動画を担当する場合も妙に感じる
本当に大きな顔出しなら AvE だろう
当時、動画コメントのかなりの割合がチャンネル名とアイコンに関するもので、実際に彼の片目はああいう見た目をしている
とはいえ、こうしたニッチなチャンネルの中でも好みはかなり分かれるようだ
彼の声は本当に良い。落ち着いていて心地よいので、家事をしながら横で流していても何かを学べる
こういうクリエイターは評価されるに値する
最新のホログラム動画は、自分が見た YouTube 動画の中でも最も品質が高い部類に入る
このツールでブリッジングアルゴリズム[1] の解説動画を作ったら本当に良さそうだ
2016 年から Pol.is のようなツールを使う参加型民主主義プロセスで、このアルゴリズムが活用されるやり方のファンで、その基礎にある数学への理解を深めることに貢献したいと思っていた
Summer of Math Exposition[2] が開かれていた時に Manim を知っていたら、間違いなく飛び込んでいただろう
[1]: https://bridging.systems/
[2]: https://some.3b1b.co/
自分のウェブサイトはプロフィールにあるので、いつか作ることになったらソーシャルメディアでリンクを送ってほしい
Manim のリンク: https://github.com/3b1b/manim
彼の動画ごとにかかっている制作量がものすごくて驚く。YouTube の再生ボタンを受け取るにふさわしい
ブログと同じく、運がなければその努力のかなりの部分が無駄になる。だがブログには少なくとも露出の機会が何度もある。HN のトップに上がるかもしれないし、X や他の場所で広がるかもしれない。同じプラットフォーム内でも、普通は複数回のチャンスがある
逆に YouTube では、アルゴリズムが実質的に一度だけ判断する。すでに膨大な登録者がいない限り、動画をほぼランダムに数人へ見せ、その人たちが反応しなければそこで終わりだ