はじめに:
前回までで、動画の再生・操作・区間指定・ジョブ管理が整いました。
でも、それらがすべて揃っていても「出力できないなら意味がない」のです。
この回では、ffmpeg を C# から制御することで、ユーザーが指定した分割区間を高速かつ無劣化でMP4に書き出す機能を作っていきます。
もちろん、Copilotへのプロンプトだけで実装しています。
ffmpeg の基本コマンドを生成AIに聞いてみた
筆者がCopilotに出した指示:
💬「C#からffmpeg.exeを呼び出して、指定区間だけをMP4で出力したい」
💬「入力ファイル、開始時間、出力ファイル名、ffmpegのコーデック指定を加えて」
Copilotから提案されたコマンド構文は:
ffmpeg -y -ss [開始時間] -i "input.mp4" -to [継続時間] -c:v copy -c:a aac "output.mp4"
このコマンドは無劣化で映像をコピーしつつ、音声を AAC でエンコードする最適な構成になっています。
💡
-ss
は開始時間、-to
は抽出する「継続時間」なので、終了時間 - 開始時間
で算出しています。
書き出し処理の C# 実装コード(BtnExportAll_Click)
private void BtnExportAll_Click(object sender, EventArgs e)
{
string input = txtVideoPath.Text;
string dir = txtOutputPath.Text;
if (!File.Exists(input) || !Directory.Exists(dir))
{
MessageBox.Show("動画ファイルまたは出力先フォルダが見つかりません。");
return;
}
string ffmpegPath = EnsureFfmpegPath();
if (string.IsNullOrEmpty(ffmpegPath))
{
MessageBox.Show("ffmpeg.exe が準備できませんでした。");
return;
}
var validJobs = dgvJobs.Rows
.Cast<DataGridViewRow>()
.Where(row =>
TimeSpan.TryParse(row.Cells[0]?.Value?.ToString(), out var start) &&
TimeSpan.TryParse(row.Cells[1]?.Value?.ToString(), out var end) &&
!string.IsNullOrWhiteSpace(row.Cells[2]?.Value?.ToString()) &&
end > start
).ToList();
if (!validJobs.Any())
{
MessageBox.Show("有効なジョブがありません。");
return;
}
progressBarExport.Visible = true;
progressBarExport.Maximum = validJobs.Count;
progressBarExport.Value = 0;
foreach (var row in validJobs)
{
string startStr = row.Cells[0].Value.ToString();
string endStr = row.Cells[1].Value.ToString();
string name = row.Cells[2].Value.ToString();
TimeSpan start = TimeSpan.Parse(startStr);
TimeSpan end = TimeSpan.Parse(endStr);
string output = Path.Combine(dir, name + ".mp4");
string args = $"-y -ss {start} -i \"{input}\" -to {end - start} -c:v copy -c:a aac \"{output}\"";
using (var proc = new Process())
{
proc.StartInfo = new ProcessStartInfo
{
FileName = ffmpegPath,
Arguments = args,
UseShellExecute = false,
CreateNoWindow = true
};
proc.Start();
proc.WaitForExit();
}
progressBarExport.Value++;
progressBarExport.Refresh();
}
progressBarExport.Visible = false;
MessageBox.Show("出力が完了しました");
}
出力先フォルダの選択機能(Copilotに追加実装してもらった)
private void BtnSelectOutput_Click(object sender, EventArgs e)
{
using (var fbd = new FolderBrowserDialog())
{
if (fbd.ShowDialog() == DialogResult.OK)
txtOutputPath.Text = fbd.SelectedPath;
}
}
Copilotに「保存先を選ぶ機能を追加したい」と伝えるだけで、即座に適切な FolderBrowserDialog
を使ったコードが返ってきます。
ffmpeg.exe の自動取得機能
最初から ffmpeg を導入しているユーザーばかりではないため、「ffmpeg.exe が見つからないなら自動で取得してくれないか?」とCopilotに頼んでみました。
返ってきたコード(概要):
string url = "https://www.gyan.dev/ffmpeg/builds/ffmpeg-release-essentials.zip";
WebClient.DownloadFile(url, zipPath);
ZipFile.ExtractToDirectory(zipPath, ffmpegDir);
Directory.EnumerateFiles(ffmpegDir, "ffmpeg.exe", ...);
このコードは、ZIPで一式ダウンロードして、ffmpeg.exe
を探し出し、コピーして配置するところまで行います。
結果、ユーザーの操作なしにffmpegが準備されるという煩わしい処理の自動化が実現しました。
もちろん using (...) {}
に置き換えることで、C# 7.3 に対応済みです。
出力処理の視覚化:プログレスバーとの連動
ユーザーが複数ジョブを登録して一括出力する際、進捗が見えないと不安になるものです。
そこでプログレスバーを追加しました。
progressBarExport.Visible = true;
progressBarExport.Maximum = validJobs.Count;
progressBarExport.Value = 0;
foreach (var row in validJobs)
{
...
progressBarExport.Value++;
progressBarExport.Refresh();
}
生成AIには:
💬「出力が終わるたびに進捗バーを進めてほしい」
とだけ伝えれば、必要な処理と表示制御を一括で返してくれます。
出力処理の高速化と安全性
Copilotからの助言:
- ✅
-c:v copy
を使うことで映像は無変換で高速書き出し可能 - ✅
-c:a aac
により音声だけ適正エンコード - ✅
-y
オプションで上書き確認を省略 - ✅
UseShellExecute = false
にして GUIを開かないように
これらは全部、Copilotが「おすすめ構成はこちらです」とコードに含めてくれたもの。信頼感あります。
まとめ:書き出し処理もCopilotにとっては“得意分野”
この回で得られた学び:
機能 | 実装方法 | AIとの連携 |
---|---|---|
ffmpeg呼び出し |
ProcessStartInfo + 引数構築 |
プロンプトで構文と実行制御を一式生成 |
自動取得 | WebClient + Zip解凍 + 探索 | CopilotがURLと展開処理を提案 |
プログレスバー | 有効ジョブ数と連動 | AIが進捗管理まで視野に入れる |
C# 7.3 対応 | using (...) {} |
AIが文法まで合わせてくれる |
ffmpeg連携は「ツールの機能性に直結する」領域ですが、生成AIが最も得意とする分野でもありました。
コマンド構文も、エラーハンドリングも、実行制御も、Copilotが完璧に組み立ててくれます。
次回:【エラー対策編】
どんなアプリでもトラブルはつきもの。
次回では、以下のような問題にどう対応したかをご紹介:
- C#バージョンが古くて
using var
が使えない - VLCのDLLが見つからず起動しない
- ffmpeg の展開先に
ffmpeg.exe
がない - ジョブの終了時間が開始時間より前になっている