Blenderで音に合わせてキーフレームを打つ(Blender API)
Blenderで音に合わせてキーフレームを打つ(Blender API)
Pythonで音声ファイル(wav)を読み込んで、それに合わせてBlenderにあるオブジェクトの大きさを変えてアニメーションさせたらきっとかっこいいと思ったので。(あとから知ったのだが、Blenderは音声からキーフレームに変える機能がついているらしい)
Blender APIとは
Blenderの操作をスクリプトから操作することができるもの。Pythonで使うことができる。いつか入門の記事を書きたい。 https://docs.blender.org/api/current/
Pythonからキーフレームを打つ
1フレームに位置のキーフレームを打ちたかったら、下のように書く。
import bpy obj = bpy.context.object # set the keyframe at frame 1 obj.location = 3.0, 4.0, 10.0 obj.keyframe_insert(data_path="location", frame=1)
メソッドの説明
keyframe_insert(data_path, index=-1, frame=bpy.context.scene.frame_current, group="") Insert a keyframe on the property given, adding fcurves and animation data when necessary.
Parameters:
data_path (string) – path to the property to key, analogous to the fcurve’s data path.
index (int) – array index of the property to key. Defaults to -1 which will key all indices or a single channel if the property is not an array.
frame (float) – The frame on which the keyframe is inserted, defaulting to the current frame.
group (str) – The name of the group the F-Curve should be added to if it doesn’t exist yet.
options –
Optional flags:
INSERTKEY_NEEDED Only insert keyframes where they’re needed in the relevant F-Curves.
INSERTKEY_VISUAL Insert keyframes based on ‘visual transforms’.
INSERTKEY_XYZ_TO_RGB Color for newly added transformation F-Curves (Location, Rotation, Scale)
and also Color is based on the transform axis.
Returns:
Success of keyframe insertion.
Return type:
boolean
Blenderにオブジェクトを追加する
Blender起動時にあるキューブを使ってもいいが、今回は新しくキューブを作って、それにアニメーションを適用させる。
1行目で生成し、2行目でシーンでアクティブにする。
bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0)) obj = bpy.context.scene.objects.active
wavから波形データをアニメーションに移す
以前の記事でやった配列を使ってキーフレームを打っていくだけ。取れるデータは大きいので、スケールの倍率は配列の中の最大値で割って正規化する。今回使った音声データは3分ほどあるので、最初の250フレームだけキーを打った。
import wave import numpy as np import logging file = "絶対パス" wf = wave.open(file, "r") buf = wf.readframes(wf.getnframes()) data = np.frombuffer(buf, dtype = "int16") frame = wf.getnframes() rate = wf.getframerate() vframe = int(rate / 24) vdata = [] for i in range(int(frame / vframe)): vdata.append(data[i * vframe * 2]) bpy.ops.mesh.primitive_cube_add(location=(0, 0, 0)) obj = bpy.context.scene.objects.active vdata_max = max(vdata) for i in range(250): obj.keyframe_insert( data_path='scale', frame=i) tmp = vdata[i] / vdata_max obj.scale = (tmp, tmp, tmp)
実行するとキーフレームが自動的に打たれる。