6
0

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 1 year has passed since last update.

クソアプリAdvent Calendar 2021

Day 21

FFmpegを用いて音入り動画を作成できる無料アプリ

Last updated at Posted at 2021-12-22

9VAeきゅうべえ Windows / Linux /Android 版の欠点

フリーソフト9VAeきゅうべえは、下のような動画が簡単につくれるベクトルアニメーションアプリです。2Dグラフィックス作成機能があり、音も入れられます。

(new-sample).gif

しかし音入りの MP4動画を作ることは、Windows / Linux /Android 版ではできませんでした。(Mac / iPhone / iPad版は可能。上はアニメGIF)

今回、FFmpegで音入りアニメーション動画を作成する方法を見つけましたので紹介します。この方法をつかって、9VAeきゅうべえは、どのOSでも動画出力できるようになりました。

9VAe きゅうべえの音声の仕様

  • 9VAeには、効果音、音楽の2トラックがあり、2つの音を同時に鳴らすことができます。
  • 音が鳴っているトラックで別の音を鳴らすと前の音は停止します。
  • 音の開始時間はキーフレームからわかります。
  • 9VAeは音のファイルを指定時刻に鳴らすだけで、音を修正する機能はありません。

音声トラック.gif

FFmpeg の機能

  • FFmpeg は連番画像から動画を作成する機能があります。
  • 動画に音を入れる機能があります。
  • 動画や音をカットしたり、つないだりする機能があります。
  • オプションの説明

ただ、その記述方法がわかりにくく、試行錯誤を繰り返しました。結局、理解したこと。

  • 動画に音声を合成するときに、時間を指定して、そこに音を入れる機能はないみたい。途中から音を鳴らしたい場合は、音の前に無音をいれる。短い音をいれる場合、音の後ろに無音をいれなければならない。
  • そのため、鳴らす音の長さを正確にはかる必要がある。
  • 映像に2トラックの音をいれることもできるはずだが、うまくならなかった。結局、効果音トラック、音楽トラックの音を合成してひとつの音にした。

今回、FFmpegで使用した機能は以下です。いろんなOSで同じように動作します。

機能 命令
連番画像から映像作成 -vcodec mpeg4 -pix_fmt yuv420p
指定した時間の無音作成 -f lavfi -i aevalsrc
指定した時間で音をカット -t 秒
2つの音をつなぐ -filter_complex concat
作成した音の時間を取得 関数を自作
2トラックの音を重ねる -filter_complex
映像に音を追加する -c:v copy -c:a copy

これらの機能をつかって、効果音トラック、音楽トラックの音を無音をはさんで順番につなげていき、最後に、2つのトラックを合成して1トラックにし、映像に入れます。具体例を示します。

連番画像から映像作成

ffmpeg -y -r 1秒のフレーム数 -i %04d.jpg -b 6000k -vcodec mpeg4 -pix_fmt yuv420p video.mp4 

%04d.jpg は連番画像(%04d は、0001,0002,0003...)9VAeから指定したフレームレート、画像サイズで出力します。なお、画像サイズを奇数にするとスマホで再生できないようです。
video.mp4 は出力ファイル名
-y は同名ファイルがあったときの上書き指定

指定した時間(秒)の無音作成

ffmpeg -f lavfi -i aevalsrc=0:d=-ac 2 -strict -2  -c:a aac -ab 256k  out.m4a

秒は小数可能
-strict -2 がないとエラーになるときがある

指定した時間(秒)で音をカット

ffmpeg -i in.wav -t-c:a aac -ab 256k out.m4a

in.wav が 指定した時間より短い場合、out.m4a は、指定した時間より短い音になる。out.m4a の時間を調べ、必要なら、無音を追加しなければならない。
-ab 256k はビットレート指定で CD音質

2つの音をつなぎ、指定した時間(秒)で音をカット

ffmpeg -i in.m4a -i in.wav -t-filter_complex concat=n=2:v=0:a=1   -ab 256k out.m4a

in.m4a の後ろに in.wav をつなぐ

2トラックの音を重ねる

ffmpeg -y -i trk1.m4a -i trk2.m4a -filter_complex "[0:a][1:a]amix=inputs=2[a]" -map "[a]" -ab 256k out.m4a

2つの音、trk1.m4a trk2.m4a を重ねて1トラックの音 out.m4a にする

映像に音をつける

ffmpeg -y -i video.mp4 -i add.m4a -c:v copy -c:a copy out.mp4

映像 video.mp4 に 音 add.m4a をつける

音 m4a の時間(msec)を取得

以下のようなプログラムを自作しました。エラーの場合、負の値が返ります。

#include <stdio.h>

#define CHis(a,b,c,d) ((a)==hd[4] && (b)==hd[5] && (c)==hd[6] && (d)==hd[7])
#define Int3(a) *(a)*0x10000   + *((a)+1)*0x100   + *((a)+2)
#define Int4(a) *(a)*0x1000000 + *((a)+1)*0x10000 + *((a)+2)*0x100 + *((a)+3)
//m4a 形式の音の再生時間(msec)を取得する
long AcGetM4aMsec(char *fileName)
{
    FILE *fp; int bb,cc; long ret=-1;
    unsigned char hd[8],work[1024]; 

    // ファイルオープン
    fp = fopen(fileName, "rb");
    for(;fp;){
        // 先頭フレームのヘッダ8Byteを読み込む
        if(fread(hd, 1, 8, fp) != 8) break;
        bb = Int4(hd);//チャンクサイズ
        bb-=8;
        if(CHis('m','o','o','v')){//メタデータ発見
            for(;bb>0;){
                if(fread(hd, 1, 8, fp) != 8) break; 
                bb-=8;
                cc = Int4(hd);//チャンクサイズ
                bb-=cc;
                for(;cc>0;cc-=1024){
                    if(fread(work, 1, cc>1024?1024:cc, fp) < 1024) break;
                }
                if(CHis('m','v','h','d')){//時間情報が入っている
                    int version=work[0];
                    int flags = Int3(work+1);
                    int creatTime = Int4(work+4);
                    int modifTime = Int4(work+8);
                    int timeScale = Int4(work+12);//秒60 の場合60
                    int duration  = Int4(work+16);//duration/timeScale=秒
                    ret = (long)((double)duration*1000/timeScale);
                    goto exit;
                }
            }
            continue;
        }
        for(;bb>0;bb-=1024){//データ読み飛ばし
            if(fread(work, 1, bb>1024?1024:bb, fp) < 1024) break;
        }
    }
exit:
    if(fp) fclose(fp);
    return ret;
}

6
0
0

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
6
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?