LoginSignup
5

More than 1 year has passed since last update.

posted at

updated at

C#で動画を作ってみた話

はじめに

C#の知識が.Net Framework 3.5あたりで止まっているので、ちょっとまずいなと思っている黒髭和熊です。
まぁ、作るのには困らないんですけどね・・・

さて、今回ですが、Youtubeで動画を公開しているのですが、その動画のオープニングを作りたいなぁと思っていました。
で、昔から使ってるキャラクタを動かしたいなと思ったんですが、簡単にできないかなー?と思ったんです。
面倒なので、描いた絵をプログラムで動かせば思い通りにできるんじゃないか?ということで調べて作りました。

動画はこれ。
ちなみに、作った動画をDavinci Resolveで音をつけたりフェードアウトさせています。

そんなお話です。

使ったもの

概要

動画のオープニングだけじゃなくて、ほかの動画も作ることを考えています。
なので、アニメーションを行う部分は抽象化し、動画にする部分は共通の処理にしています。
ですが、そこはあまり重要ではないので触れません。(知りたい人がいれば書きます)
今回使用したAForgeをどう使っているかを紹介できればと思っています。

クラス図はこんな感じです。
Form1で管理して、描画は別のクラス、といった感じになります。
image.png

実際の画面はこんな感じ。
image.png

さて、処理についてですが、作ったプログラムに沿った形で説明していきます。
AForgeの使用方法にあまり関係ないところがありますが、クラス図と比較しながら見ていただければと思います。

AbstructAnimationクラスを実装したChannelOpeningクラスをForm1に登録します。
ChannelOpeningクラスあオープニング動画の描画を行うクラスになります。

Form1.cs
        private VideoFileWriter videoWriter = null;

        private Thread thread = null;
        private Bitmap bmp = null;

        private AbstractAnimation currentAnime = null;

    // ・・・省略・・・

        private void Form1_Load(object sender, EventArgs e)
        {
            this.SetStyle(ControlStyles.ResizeRedraw, true);
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);

            cmbAnime.Items.Add(new AnimeTest(this));
            cmbAnime.Items.Add(new IngressHyperion(this));
            cmbAnime.Items.Add(new ChannelOpening(this));

            cmbAnime.SelectedIndex = 0;
        }

実行はボタンのクリックで開始します。
このタイミングで、AForge.Video.FFMPEG.VideoFileWriterのインスタンスを生成します。

Form1.cs
        private void btnExecute_Click(object sender, EventArgs e)
        {
    // ・・・省略・・・
               bmp = new Bitmap(AnimationConfig.bmpWidth, AnimationConfig.bmpHeight);

                // アニメーション初期化
                currentAnime.Initalize();

                if (AnimationConfig.isWriteMode == true)
                {
                    var text = txtLength.Text;
                    var movieLength = AnimationConfig.movieLength;
                    AnimationConfig.movieLength = movieLength;
                    AnimationConfig.writeFrameCnt = 0;
                    videoWriter = new VideoFileWriter();
                    videoWriter.Open(@"C:\data\test4.mp4", bmp.Width, bmp.Height, AnimationConfig.framerate, VideoCodec.MPEG4);
                }

VideoFileWriter.Open()メソッドで保存するファイル名や動画のサイズ、フォーマットを指定します。
ここで気を付けるべきはフォーマット。
AVIで保存すると結構大きなファイルになります。
フォーマットはVideoCodec列挙型で定義されています。
定義内容は公式ドキュメントのVideoCodec Enumerationを見てもらえばわかります。
私はVideoCodec.MPEG4を選択しています。
フレームレートはAnimationConfigクラスで60を指定しており、その値を利用しています。

ボタンを押したタイミングでスレッドを作成し、描画用メソッドdraw()を呼び出しています。
その中でChannelOpeningクラスの描画した内容をVideoFileWriterのWriteVideoFrameメソッドで書き込んでいます。

Form1.cs

    // ・・・省略・・・

                thread = new Thread((ThreadStart)delegate ()
                {
                    long tm = 0;
                    long frm = 0;
                    while (thread != null)
                    {
                        tm = DateTime.Now.Ticks;
                        draw();

    // ・・・省略・・・

        private void draw()
        {
            using (Graphics g = Graphics.FromImage(bmp))
            {
                currentAnime.OnDraw(g);

                if (AnimationConfig.isWriteMode == true && videoWriter != null)
                {
                    videoWriter.WriteVideoFrame(bmp);
                }
            }
        }

書き込みはすごく簡単で、VideoFileWriter.WriteVideoFrame()メソッドに作成したビットマップを渡すだけです。
書き込みが終わったら、Close()メソッドで、VideoFileWriterを閉じればOKです。

Form1.cs
    videoWriter.Close();

終わりに

ざっくりですが、C#で動画を作ってみた話を紹介しました。
Magick.NETも試したのですが、私の実装が悪かったせいか、動画を作れないことがあったので断念。
AForge.NETはそんなこともなく割と簡単に使えたので採用しました。
音もやればできるみたいですが、まぁ、音はDavinci Resolve使ったほうが楽だったので^^;

実際のコードはたぶんGithubに公開すると思います。
いつになるかわかりませんがw

Githubにリポジトリ作りました。
こちらになります。

あ、最後に。
よかったら私のYoutubeのチャンネルも見てみてください。
そのうちこの記事の内容も動画にしようと思っています。

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
What you can do with signing up
5