@chromize

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

C#のProcessからバックグラウンドでffmpegを起動し、画像から映像を生成したい。

解決したいこと

C#kからバックグラウンドプロセスでffmpegを操作し画像から動画を作成したい。

概要

C#(WPF),OpencvSharpで動画編集ツールを作成しています。
編集した動画をエクスポートする際にOpencvsharpのVideoWriter機能ではいくつかの設定ができないことが判明しています。
以下、設定したいができない項目になります。

・走査方式(インターレース/プログレッシブ)
・ビットレートの方式(可変/固定)

そこでffmpegを用いてエンコードを外部化しようと考えています。
検証のために試作のソフトを作成してみたのですが、うまく動かなかったため
アドバイスをいただきたいと思います。

発生している問題・エラー

[image2 @ 0000025ef07eba80] Could not find codec parameters for stream 0 (Video: mjpeg, none(bt470bg/unknown/unknown)): unspecified size
Consider increasing the value for the 'analyzeduration' (0) and 'probesize' (5000000) options
Input #0, image2, from 'pipe:.bmp':
  Duration: 00:00:00.04, start: 0.000000, bitrate: N/A
  Stream #0:0: Video: mjpeg, none(bt470bg/unknown/unknown), 25 fps, 25 tbr, 25 tbn, 25 tbc
[NULL @ 0000025ef07ee7c0] Unable to find a suitable output format for 'C:/Users/dice-/DiCE'
C:/Users/dice-/DiCE: Invalid argument
1
例外がスローされました: 'System.IO.IOException' (mscorlib.dll の中)
型 'System.IO.IOException' のハンドルされていない例外が mscorlib.dll で発生しました
パイプは終了しました。

該当するソースコード

    public void Video(int bitrate = 12000, double fps = 29.97, string outputfilename = "C:/Users/XXXX/PC/Desktop/sample_gorilla_movie.mp4")
    {
        Process proc = new Process();

        proc.StartInfo.FileName = @"C:\Program Files\Shotcut\ffmpeg.exe";
        proc.StartInfo.Arguments = string.Format("-i pipe:.bmp -maxrate {0}k -r {1} -an -y {2}",
            bitrate, fps, outputfilename);
        proc.StartInfo.UseShellExecute = false;
        proc.StartInfo.RedirectStandardInput = true;
        proc.StartInfo.RedirectStandardOutput = true;
        proc.StartInfo.CreateNoWindow = true;
        proc.Start();

        for (int i = 0; i < 100; i++)
        {
            using (var ms = new MemoryStream())
            {
                using (var img = Image.FromFile(@"C:\Users\XXXX\PC\Desktop\sample_gorilla.jpg"))
                {
                    Debug.WriteLine(i.ToString());
                    img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
                    ms.WriteTo(proc.StandardInput.BaseStream);//ここでi = 1のときエラーが発生する。
                }
            }
        }
        proc.Close();
    }

自分で試したこと

ffmpegのオプションが足りていないのか?と思い
コーデックを追加してあげたりエラーにある
analyzedurationやprobesizeも設定してあげましたが特に変化はありませんでした。

そもそもこのアプローチが間違っている可能性もあるので
様々な観点でアドバイス頂けたらと思います。よろしくお願いします。

1 likes

1Answer

ffmpegは殆ど触ってないので、的外れになるかもしれませんが、

  • pipe:.bmp を指定してImageFormat.Jpegを書き込むのは問題ないのでしょうか?
  • パイプ経由ではなく連番の画像ファイルを出力してエンコードした場合は上手くいくのでしょうか?

ffmpeg側のエラーメッセージを見たりして、とにかく原因を絞っていくしかなさそうな気がします。
Unable to find a suitable output format
Could not find codec parameters for stream 0
このへんの文字列も検索してみたりすると、解決のヒントになりそうな気がします。

1Like

Comments

  1. @chromize

    Questioner

    回答ありがとうございます。
    原因ですが、どうやらoutputfilenameに日本語が含まれているとffmpeg側で不正な入力値と判断されてしまいprocessが途中で落ちていました。outputfilenameを英字のみにしてあげたところ動作しました。

    ご指摘についてですがImageFormat.JpegではなくImageFormat.Bmpにしたら画質が向上したのでそちらで実装をすすめています。ご指摘ありがとうございました!
  2. @chromize

    Questioner

    >パイプ経由ではなく連番の画像ファイルを出力してエンコードした場合は上手くいくので>しょうか?

    これについてはうまくいきますが動画の尺が数時間に及ぶのでリソースを考えるとあまり現実的ではないと判断し今回の実装では手法として無にしておりました。

Your answer might help someone💌