1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

エンドロールムービーをprocessingで作る #1 【連番画像作成・アニメーション】

Last updated at Posted at 2021-09-26

Processingffmpegを用いて簡単な結婚式風エンドロールムービーを作成しました。
Processingで連番の画像を作成し、ffmpegによりその連番画像を動画に変換しています。
動画作成方法を数回に分けて紹介していきたいと思います。

2021/10/3
本プログラム紹介の#2を作成いたしました。そちらでは文字スクロール・画像表示を紹介しております。

動作環境

Windows 10
Processing 3.5.3

今回作成した動画

out_3.gif

動画の作成方法

Processingでのプログラミングと、ffmpegでの動画作成に分けて説明を行います。

Processingプログラミング内容説明

今回の動画を作成するにあたって使用した関数など、プログラミング内容を説明していきます。

連番画像の作成

連番画像の作成は**saveFrame()**という関数を使用して行います。試しに以下の文を実行するとframesフォルダが作成され、その中に00001、00002、00003… と、saveFrame()引数の#に対応した桁数の連番画像が作成されます。
saveFrame()実行中は画像が際限なく作成されて動きがカクカクするので、動作確認時などはコメントアウトしておくことをお勧めします。

int FR = 50;  //1秒間あたりのフレーム数(fps)
int cnt = 0;

void setup() {
  size(1600, 900);
  frameRate(FR);
}

void draw() {
  strokeWeight(3.0);
  strokeCap(ROUND);
  line(0,0, cnt, cnt);
  cnt++;
  if(cnt <= 200){
    saveFrame( "frames/#####.png" ); // framesフォルダに作成した画像を保存
  }
}

フォントの変更

フォントの変更は**loadFont()**という関数を使用します。ただし、この関数を使用する前にprocessingで表示可能なフォーマットにフォントを変換する必要があります。
まずは、「ツール」→「フォント作成...」を選択します。
loadfont1.png
ポップアップウィンドウが表示されるので、使用したいフォントを選択して「OK」をクリックします。
loadfont2.png
以上でフォントを使用する準備が完了です。こちらも必要なフォントをインストールして、試しに以下の文を実行するとフォントの異なる文字列が表示されます。

String str = "Hello world";

void setup() {
  size(1600, 900);
}

void draw() {
  //テキスト表示用
  PFont font;
  float strX;
  float strY;
  float strSize;
  int strAlign;

  font = loadFont("CourierNewPS-BoldItalicMT-48.vlw");  // 任意のフォントを読み込み
  textFont(font);
  strX = width/2;     //文字列x座標
  strY = height/2;    //文字列y座標
  strSize = 48;       //文字列サイズ設定
  strAlign = CENTER;  //文字列中央寄せ
  
  textSize(strSize);     //文字列のサイズ
  textAlign(strAlign);   //文字列配置
  text(str, strX, strY); //文字列描画
  
  font = loadFont("Dialog.bolditalic-48.vlw");  // 任意のフォントを読み込み
  textFont(font);
  strX = width/2 + 100;
  strY = height/2 + 100;
  strSize = 60;
  strAlign = CENTER;  //文字列中央寄せ
  
  textSize(strSize);    //文字列のサイズ
  textAlign(strAlign);  //文字列配置
  text(str, strX, strY); 
}

loadfont3.png

図形の透過

透過を行うことでアニメーションに動きを付けます。**fill()**を使用すれば図形や文字の塗りつぶし色の指定に加えて、透過の設定も行えます。詳細は以下の通りです。
fill( int colorVal , float alpha )
colorVal:色情報
alpha : 透明度指定 0(透明) – 255(不透明)

ここでは、alphaの値を時間によって変化させていくことでフェードイン・フェードアウトを行っています。

int FR = 50;  //1秒間あたりのフレーム数(fps)
int cnt = 0;
String str = "Hello world";
float startTime = 5 * FR;     //文字列の表示時間(sec)
float endTime = 8 * FR;       //終了時間(sec)
int addVal = -1;              //減衰値
float cntAlpha;               //透過時間計算用
float cntAlphaMax = 3.0 * FR; //アニメーション時間(sec)

void setup() {
  size(1600, 900);
  frameRate(FR);
}

void draw() {
  //テキスト表示用
  PFont font;
  float strX;
  float strY;
  float strSize;
  int strAlign;
  
  background(0, 0, 0);  // 背景色を黒色に設定
  
  if((float)cnt <= (float)cntAlphaMax){
    addVal = 1;    //フェードイン
  }else if((float)cnt >= (float)(startTime - cntAlphaMax)){
    addVal = -1;    //フェードアウト
  }
  
  cntAlpha += addVal;
  if( cntAlpha < 0 ){
    cntAlpha = 0;
  } else if( cntAlpha > cntAlphaMax ){
    cntAlpha = cntAlphaMax;
  }  
  int alpha = (int)map(cntAlpha,0,cntAlphaMax,0,255);  //透過率
  fill(255, alpha);

  font = loadFont("CourierNewPS-BoldItalicMT-48.vlw");  // 任意のフォントを読み込み
  textFont(font);
  strX = width/2;
  strY = height/2;
  strSize = 48;
  strAlign = CENTER;  //文字列中央寄せ
  
  textSize(strSize);    //文字列のサイズ
  textAlign(strAlign);  //文字列配置
  text(str, strX, strY); 
  
  font = loadFont("Dialog.bolditalic-48.vlw");  // 任意のフォントを読み込み
  textFont(font);
  strX = width/2 + 100;
  strY = height/2 + 100;
  strSize = 60;
  strAlign = CENTER;  //文字列中央寄せ
  
  textSize(strSize);    //文字列のサイズ
  textAlign(strAlign);  //文字列配置
  text(str, strX, strY); 
  
  if(cnt <= endTime){
    saveFrame( "frames/#####.png" );
  }
  
  cnt++;
}

out.gif

プログラミング全文

//--------------グローバル変数--------------//
int cnt = 0;
int flag = 1;
int flagMax = 2;
PFont fontDefault;  //デフォルトのフォント設定用
int FR = 50;  //1秒間あたりのフレーム数(fps)

//テキストアニメーション用
float openingStartTime = 5 * FR;     //オープニングの表示時間(sec)
float openingStrTime = 8 * FR;     //オープニングメッセージの表示時間(sec)
int addVal = -1;              //減衰値
float cntAlpha;               //透過時間計算用
float cntAlphaMax = 1.0 * FR; //アニメーション時間(sec)

//ラインアニメーション用
float lineLen = 0;     //線の長さ
int addValLine = -1;   //減衰値
float cntLine;         //線描画時間計算用
int lineMin = 100 ;    //スタートポジション
float lineMax = 1600 - lineMin;  //エンドポジション
float cntLineMax = 1.0 * FR;     //アニメーション時間(sec)

void setup() {
  size(1600, 900);
  fontDefault = createFont("Serif.bold", 50);
  textFont(fontDefault);
  frameRate(FR);
}

void draw() {
  //テキスト表示用
  PFont font;
  String str;
  float strX;
  float strY;
  float strSize;
  int strAlign;
  
  //ライン表示用
  float lineX1;
  float lineY1;
  float lineX2;
  float lineY2;

  int alphaSub;
  float lineLenSub;
  
  background(0, 0, 0);
  
  switch(flag){
    case 1:    // オープニング画面
//--------------文字のアニメーション表示用--------------//
      if((float)cnt <= (float)cntAlphaMax){
        addVal = 1;    //フェードイン
      }else if((float)cnt >= (float)(openingStartTime - cntAlphaMax)){
        addVal = -1;    //フェードアウト
      }

//--------------ラインアニメーション表示用--------------//
      if(cnt <= cntLineMax){
        addValLine = 1;    //フェードイン
      }else if(cnt >= openingStartTime - cntLineMax){
        addValLine = -1;    //フェードアウト
      }    
    
//--------------オープニングタイトル--------------//
//--------------ラインアニメーション--------------//
      //上側の線
      lineLenSub = lineAnimation();
      stroke(255);
      lineX1 = lineMin;
      lineY1 = height/2 - 90;
      lineX2 = lineLenSub;
      lineY2 = lineY1;
      lineDraw(lineX1, lineY1, lineX2, lineY2);

      //下側の線
      lineLenSub = lineAnimation();
      stroke(255);
      lineX1 = lineMax - lineLenSub + 100;
      lineY1 = height/2 + 90;
      lineX2 = lineMax;
      lineY2 = lineY1;
      lineDraw(lineX1, lineY1, lineX2, lineY2);

      //線を隠すために透明な長方形を線の上に描画
      fill(0);
      noStroke();
      rect(width/2 - 300, height/2 - 100, 600, 20);


//--------------1行目--------------//
      font = loadFont("CourierNewPS-BoldItalicMT-48.vlw");
      textFont(font);
      str = "26  September  2021";
      strSize = 48;
      strX = width/2;
      strY = height/2 - 80;
      strAlign = CENTER;

      alphaSub = strAnimation();
      fill(255, alphaSub);
      textDraw(str, strSize, strAlign, strX, strY);

//--------------2行目--------------//
      font = loadFont("CourierNewPS-BoldItalicMT-48.vlw");
      textFont(font);
      str = "Thanks For Guests";
      strSize = 100;
      strX = width/2;
      strY = height/2 + 30;
      strAlign = CENTER;      
      textDraw(str, strSize, strAlign, strX, strY);
      
      //表示時間計算用
      if(cnt >= openingStartTime){
         flag = 2;
         cnt = 0;
      }
      break;
  }
  cnt ++;
  
  if(flag != flagMax){
    saveFrame( "frames/#####.png" );
  }
}

private float lineAnimation(){
  //cntLineから線の長さを計算する
  cntLine += addValLine;
  if( cntLine < 0 ){
    cntLine = 0;
  } else if( cntLine > cntLineMax ){
    cntLine = cntLineMax;
  }  
  lineLen = (float)map(cntLine,0,cntLineMax,lineMin,lineMax);
  return lineLen;
}

private void lineDraw(float x1, float y1, float x2, float y2){
  strokeWeight(3.0);
  strokeCap(ROUND);
  line(x1, y1, x2, y2);  
}

private int strAnimation(){
  //cntAlphaからアルファ値を計算する
  cntAlpha += addVal;
  if( cntAlpha < 0 ){
    cntAlpha = 0;
  } else if( cntAlpha > cntAlphaMax ){
    cntAlpha = cntAlphaMax;
  }  
  int alpha = (int)map(cntAlpha,0,cntAlphaMax,0,255);  //透過率
  return alpha;
}

private void textDraw(String str, float s, int a, float x, float y){
  textSize(s);    //文字列のサイズ
  textAlign(a);  //文字列中央寄せ
  text(str, x, y); 
}

ffmpegでの動画作成

ffmpegはコマンドラインでアプリケーションです。まずは以下を参考にインストールして、コマンドラインで使用できるように設定を行います。

後は以下を参考にして連番画像から動画を出力することができれば成功です。

ffmpeg -framerate 50 -i %05d.png -vcodec libx264 -pix_fmt yuv420p -r 50 out.mp4

参考

・saveFrame()
http://www.musashinodenpa.com/p5/index.php?pos=1373

・frameRate()
http://www.musashinodenpa.com/p5/index.php?pos=162

・loadFont()
https://r-dimension.xsrv.jp/classes_j/system_font/

・fill()
http://mslabo.sakura.ne.jp/WordPress/make/processing%E3%80%80%E9%80%86%E5%BC%95%E3%81%8D%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/%E5%9B%B3%E5%BD%A2%E3%82%84%E6%96%87%E5%AD%97%E3%82%92%E9%80%8F%E6%98%8E%E3%81%AB%E3%81%99%E3%82%8B%E3%81%AB%E3%81%AF/

・ffmpegインストール
https://qiita.com/SatoshiGachiFujimoto/items/0da89db99d8a5dae3e9c

・ffmpeg使用方法
https://qiita.com/livlea/items/a94df4667c0eb37d859f

1
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?