Blenderスクリプトでカメラアニメーション(2026):コード例付きの完全ガイド

Blenderスクリプトでカメラアニメーション(2026):コード例付きの完全ガイド

Blenderでカメラを手作業でアニメーションさせるのは、なかなか大変です。きれいなドリーショットを頭に描いて、キーフレームを1つずつ置いていっても、なぜか最終的にガタついた動きや散らかったタイムラインになってしまうことがあります。この種のドリフトは、他に使えるはずの時間をすぐに食ってしまいます。

そこで登場するのがスクリプトです。

BlenderのPython APIは、カメラ位置、回転、視野角、パス移動を直接制御できます。そしてそれがコードである以上、キー フレームをスクラブして「ほんの少しズレているもの」を探し回る代わりに、数秒で微調整して再実行できます。

このガイドでは、その実践的な部分を扱います:カメラを追加する方法、移動タイプを定義する方法、スプラインに沿ってアニメーションする方法、そして動く被写体を追跡する方法。読み終わる頃には、今後のプロジェクトにそのまま持ち込める小さなツールキットが手に入るはずです。

なぜスクリプトでカメラ移動なのか?

建築パースのウォークスルー、プロダクトショーケース、あるいは何十もの似たショットを含むカットシーンのようなものを制作している場合、各ショットを手で個別にキーフレーム設定するのは退屈で面倒です。スクリプトなら、オブジェクトの周りの完全なオービット、ラッ クフォーカスの一連、またはなめらかなクレーン移動を数秒で生成でき、しかも必要に応じてそのまま再現できます。

人間の手でキーフレームを打つと、微妙な不一致も入りがちです。例えば、テイク2ではパンの加速が少しだけ違っていたり、ズームが数フレーム分オーバーしていたり。スクリプトは数学的な精度を強制します。各ショットは、指定したイージングカーブと速度に対してまったく同じ動作になります。

スタジオでもフリーランサーでも、時間はお金です。スクリプト化されたカメラは、手作業の微調整に伴う往復を大幅に減らします。ディレクターが「カメラを10%速くして」「5度高くして」と言っても、全面的な作り直しの再キー フレームは不要で、変数の変更だけで済みます。

スクリプトは生きたドキュメントです:カメラのロジックをパラメータ化された関数で包むことで、タイミング、距離、イージングを非破壊的に調整でき、過去の作業を壊すことなく改善できます。

ここで挙げた理由すべてを考慮すれば、将来のあなたは確実に何時間も得をするでしょう!

1. カメラを追加する

まず最初に、Blenderの bpy モジュールを使ってプログラム的にカメラを作成・管理する方法を理解しておくのが重要です:

import bpy

def add_camera(name="ScriptedCamera", location=(0, -10, 5)):
    bpy.ops.object.camera_add(location=location)
    camera = bpy.context.active_object
    camera.name = name
    return camera

def remove_camera(name):
    obj = bpy.data.objects.get(name)
    if obj and obj.type == 'CAMERA':
        bpy.data.objects.remove(obj, do_unlink=True)

def list_cameras():
    return [obj for obj in bpy.data.objects if obj.type == 'CAMERA']

cam = add_camera(name="MainCam", location=(0, -10, 2))
bpy.context.scene.camera = cam 

print("Cameras in scene:", [c.name for c in list_cameras()])

add_camera() は Blender の bpy.ops.object.camera_add() オペレーターを使って、新しいカメラを3Dシーンに指定した (X, Y, Z) の位置に挿入します。この例ではデフォルトが (0, -10, 5) です。作成後に、追加されたばかりのオブジェクトを bpy.context.active_object で取得し、カスタム名を割り当て、呼び出し側が後で参照できるように返します。

remove_camera()bpy.data.objects 内で名前を使ってオブジェクトを探し、削除前にそれが実際にカメラであることを確認します。do_unlink=True を指定することで、そのオブジェクトがシーンから完全に削除され、単に非表示にするだけではなく、所属するコレクションからも確実に外されます。

list_cameras() は、現在の Blender のシーン内のすべてのオブジェクトを反復処理し、型が 'CAMERA' のものだけを含むフィルタ済みリストを返します。これは、ある時点で存在するカメラをまとめて把握するためのシンプルなユーティリティです。

bpy.context.scene.camera を設定することで、Blenderがレンダリングに使うカメラを指定できます。シーン内には複数のカメラを用意でき、マーカーを使って特定のフレームで切り替えることも可能です。マルチアングルのシーケンスでは非常に役に立ちます。

スクリプトタブでこのスクリプトを実行すると、ビューポートに2つ目のカメラが追加されるのが確認できます:

Two cameras in a Blender scene

2. カメラ移動タイプ

シーンにカメラがあるなら、次はそれを動かす番です。ほとんどのシネマティックなカメラ移動は、カメラオブジェクトへの単純な変換(トランスフォーム)に対応します:

import bpy
import math

def zoom(camera, start_fov=50, end_fov=20, start_frame=1, end_frame=60):
    cam_data = camera.data
    cam_data.lens = start_fov
    cam_data.keyframe_insert(data_path="lens", frame=start_frame)
    cam_data.lens = end_fov
    cam_data.keyframe_insert(data_path="lens", frame=end_frame)

def pan(camera, start_angle=0, end_angle=45, start_frame=1, end_frame=60):
    camera.rotation_euler.z = math.radians(start_angle)
    camera.keyframe_insert(data_path="rotation_euler", frame=start_frame)
    camera.rotation_euler.z = math.radians(end_angle)
    camera.keyframe_insert(data_path="rotation_euler", frame=end_frame)

def tilt(camera, start_angle=0, end_angle=20, start_frame=1, end_frame=60):
    camera.rotation_euler.x = math.radians(90 + start_angle)
    camera.keyframe_insert(data_path="rotation_euler", frame=start_frame)
    camera.rotation_euler.x = math.radians(90 + end_angle)
    camera.keyframe_insert(data_path="rotation_euler", frame=end_frame)

def truck(camera, start_x=0, end_x=5, start_frame=1, end_frame=60):
    camera.location.x = start_x
    camera.keyframe_insert(data_path="location", frame=start_frame)
    camera.location.x = end_x
    camera.keyframe_insert(data_path="location", frame=end_frame)

cam = bpy.context.scene.camera
zoom(cam, start_fov=50, end_fov=25, start_frame=1, end_frame=90)
pan(cam, start_angle=0, end_angle=30, start_frame=90, end_frame=150)

zoom 関数は、Blender上でフレームの範囲にわたってカメラの焦点距離をアニメーションし、光学ズームのような効果をシミュレートします。開始時の視野角(field of view)を cam_data.lens に設定して開始フレームでキーフレームを挿入し、その後終了時の視野角に設定して終了フレームでもう1つキーフレームを挿入します。

pan は、2つの角度の間でカメラを水平方向にZ軸回りに回転させます。Blenderが必要とするため、両方の角度を度からラジアンに変換し、開始フレームでZ回転を設定して、終了フレームで終了角度を設定します。これにより、左右にスイープする動きが生成されます。

tiltpan と同じように動作しますが、作用するのはX軸です。垂直方向(上下)のカメラ移動を作るためです。変換の前に角度に90度のオフセットが入るのは、Blenderのデフォルトのカメラ向きがX軸方向に下を向いているためです。したがって90°は「まっすぐ前を見る」ことを意味し、それに対するチルトが適用されます。

truck は、回転ではなく物理的にカメラをX軸方向に左または右へ移動します。開始フレームと終了フレームでカメラのX位置にキーフレームを設定することで、シーン上を横方向にスライドさせます。

他にもカメラ移動のタイプはいろいろありますが、ここまででイメージは掴めたはずです。

例として、Blenderの現在のコンテキストからアクティブなシーンカメラを取得し、そこに2つのカメラ移動を順番に連結します。まず、スクリプトがフレーム1〜90の間でレンズを50mmから25mmへズームインします。

zoom start

zoom end

次に、ズームが完了したら、フレーム90〜150の間でカメラを右に30度パンします。2つのアニメーションはフレーム90を共通の遷移点として共有するため、ある動きが次の動きへきれいに引き継がれます。

pan

各関数は、該当するデータパスにキーフレームを挿入し、Blenderがそれらの間を自動的に補間します。アニメーションをよりシネマティックにするには、キーフレーム後にグラフエディターで結果のFカーブの補間モードを BEZIEREASE_IN_OUT に設定するか、fcurve.keyframe_points[i].interpolation を使ってプログラム的に変更できます。

3. スプラインパスを定義する

直線的な移動では、シネマティックさがあまり出ません。クレーンアークやフライスルーのような滑らかなカメラモーションでは、カメラをBézierまたはNURBSスプラインパスに沿って動かしたくなることがあります。ここでも、スクリプトが大いに役立ちます:

import bpy

def create_camera_path(points, camera):
    curve_data = bpy.data.curves.new(name="CameraPath", type='CURVE')
    curve_data.dimensions = '3D'
    curve_data.use_path = True
    curve_data.path_duration = bpy.context.scene.frame_end

    spline = curve_data.splines.new('BEZIER')
    spline.bezier_points.add(len(points) - 1)

    for i, pt in enumerate(points):
        bp = spline.bezier_points[i]
        bp.co = pt
        bp.handle_left_type = 'AUTO'
        bp.handle_right_type = 'AUTO'

    path_obj = bpy.data.objects.new("CameraPath", curve_data)
    bpy.context.scene.collection.objects.link(path_obj)

    constraint = camera.constraints.new(type='FOLLOW_PATH')
    constraint.target = path_obj
    constraint.use_curve_follow = True

    constraint.offset = 0
    constraint.keyframe_insert(data_path="offset", frame=1)
    constraint.offset = -100
    constraint.keyframe_insert(data_path="offset",
                               frame=bpy.context.scene.frame_end)

    return path_obj

path_points = [
    (0, -8, 3),
    (-5, -5, 4),
    (-7, 0, 3),
    (-4, 5, 2),
    (0, 7, 2),
]

cam = bpy.context.scene.camera
create_camera_path(path_points, cam)

このコードスニペットでは、背後から右方向へ伸び、左へ回り込みながら前へスイープし、その後原点より少し手前かつ上に落ち着くカーブしたアークを描くための5つの3D座標を定義します。シーンのアクティブカメラを取得し、ポイントのリストとカメラの両方を create_camera_path に渡すことで、完全なセットアップをトリガーし、このアークに沿ってシーン全体を通してカメラが滑らかに飛ぶようになります。create_camera_path は、Blender上で滑らかな3Dカメラアニメーションパスを作成します。

スクリプトはまず、「CameraPath」という名前の新しいカーブオブジェクトを作成し、3D Bezierスプラインとして設定します。さらに、その総デュレーションをシーンの終了フレームに合わせます。

次に、提供されたポイントでスプラインを埋めます。各制御点のハンドルタイプを AUTO に設定することで、Blenderがそれらの間の滑らかなカーブを自動的に計算します。生成されたカーブはBlenderのオブジェクトに包まれ、アクティブシーンのコレクションにリンクされるため、表示されるようになります。

続いて、カメラに FOLLOW_PATH 制約を追加し、新しいカーブをターゲットとして指定します。これにより、カメラがそのカーブに沿って移動せざるを得なくなります。

最後に、スクリプトは制約の offset プロパティを2つのキーフレームでアニメーションします。フレーム1でオフセット0(パスの開始):

path start

そしてシーン最後のフレームでオフセット-100(パスの終了):

path end

FOLLOW_PATH 制約が、位置に関するすべての計算を処理します。use_curve_followTrue に設定すると、カメラの前方軸がカーブの接線と一致するため、自然に進行方向を向きます。

また、ハンドルタイプを AUTO から VECTOR に変えてシャープなコーナーを作ったり、FREE にしてBézierハンドルを完全に手動で制御することもできます。

4. 被写体を追跡する

動くキャラクターやオブジェクトを追いかけるカメラは、アクションショットや会話シーンでも欠かせません。Blenderの TRACK_TO 制約を使えば、コードでの設定がとても簡単です:

import bpy

def track_camera_to_subject(camera, subject_name, track_axis='TRACK_NEGATIVE_Z', up_axis='UP_Y'):

    subject = bpy.data.objects.get(subject_name)
    if subject is None:
        print(f"Subject '{subject_name}' not found.")
        return

    constraint = camera.constraints.new(type='TRACK_TO')
    constraint.target = subject
    constraint.track_axis = track_axis
    constraint.up_axis = up_axis
    return constraint

def add_damped_track(camera, subject_name):
    subject = bpy.data.objects.get(subject_name)
    if subject is None:
        return

    constraint = camera.constraints.new(type='DAMPED_TRACK')
    constraint.target = subject
    constraint.track_axis = 'TRACK_NEGATIVE_Z'
    return constraint

cam = bpy.context.scene.camera
track_camera_to_subject(cam, "Cube")

track_camera_to_subject は、名前でBlenderオブジェクトを検索し、指定したカメラに「Track To(追跡)」制約を追加して、その被写体を剛体のように指す状態にします。カメラがどの軸に沿って向くか、そしてどの軸を上方向として保つかを指定でき、デフォルトは追跡が負のZ軸、上方向がY軸です。指定された被写体がシーンに存在しない場合は警告を出して早期に終了し、存在する場合は新しい制約を設定して返します。

add_damped_track は同様のことを行いますが、「Damped Track(減衰トラック)」制約を使う点が異なります。これは、厳密に軸を固定した狙いよりも、より柔らかく自然な回転を生みます。成功時には制約を返しますが、追跡に使う軸は常に負のZ軸を使います。

このプログラムは、開いているBlenderシーンで現在アクティブになっているカメラを取得し、デフォルトの軸を使って track_camera_to_subject を呼び出し、デフォルトのCubeオブジェクトを指すようにします。

見ての通り、カメラを動かしても、視界はCubeオブジェクト中心のままです。移動前:

follow start

そしてカメラやCubeを移動した後:

follow end

TRACK_TO は剛性のロックを提供します。被写体がどこへ動いても、カメラは即座にその方向へ向き直ります。より有機的で、少し遅れて追従するような(ショルダーカムやハンディカム風シミュレーションでよくある)感触にしたい場合は、代わりに DAMPED_TRACK を使ってください。

もちろん、制約を重ねることもできます。例えば、スプラインパスに沿って移動しながら同時に被写体を追跡すれば、キャラクターの周りを回りつつ常にフレーミングを維持するような複雑なショットを作れます。

結論

BlenderのPython APIを使うことで、カメラアニメーションはエラーが起きやすい手作業のプロセスから、精密なシステムへと変わります。カメラをプログラム的に追加・管理する方法、ズーム、パン、チルト、トラックといった基本的な動きをキーフレーム化する方法、滑らかなスプラインパスに沿ってカメラを誘導する方法、そして追跡制約で動く被写体へロックする方法を見てきました。

本当の創造性の力が発揮されるのは、これらの技術をオブジェクトアニメーションと組み合わせたときです。Follow Path制約のカメラを、自身でもアニメーションしている被写体と組にすれば、前景と背景のズレを異なる速度で動かして奥行きを作るパララックスショットをスクリプトで生成できます。ドリー移動とは反対方向にズームのオフセットを取れば、コードだけでヒッチコック・ドリーズーム効果が得られます。さらに、軌道に対してTrack To制約をレイヤーすることで、複雑な「被写体追従」のクレーンショットまで自動的にアニメーションされます。