Я пытаюсь использовать FFMpeg с System.IO.Process, чтобы преобразовать видеопоток с возможностью поиска в памяти в миниатюру. Пропускать миниатюру через stdout не проблема, но пиковать в видео сложно.
Мой текущий код копирует весь видеопоток в стандартный ввод, что очень медленно и не нужно, потому что ffmpeg, очевидно, не нужен весь файл, чтобы получить первый кадр. Запись потока в файловую систему и указание его пути в качестве входного аргумента также очень медленная, поскольку исходное видео может занимать несколько гигабайт.
Я пытался выполнить это с использованием существующих библиотек, таких как AForge, FFMpegCore, Xabe.FFMpeg, xFFMpeg. NET и Accord.FFMPEG.Video, но, к сожалению, они могут работать только с реальными файлами, а не с потоками, и мое входное видео недоступно в виде файла.
Потоковый объект, который предоставляет видео, полностью реализует функции поиска и чтения с произвольным доступом, точно так же, как файловый поток, поэтому буквально нет веских причин для того, чтобы это было невозможно, кроме ограничений API (или мои знания).
В качестве последнего средства я мог бы использовать драйвер файловой системы Dokan. NET, чтобы представить видеопоток как виртуальный файл, чтобы ffmpeg мог его прочитать, но это было бы чрезмерным перебором, и я ищу лучшее решение.
Ниже мой текущий код. Для простоты я эмулирую входной видеопоток с помощью FileStream.
var process = new Process();
process.StartInfo.FileName = "ffmpeg.exe";
process.StartInfo.Arguments = "-i - -ss 00:00:01 -vframes 1 -q:v 2 -c:v png -f image2pipe -";
process.StartInfo.RedirectStandardInput = true;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.Start();
var stream = File.OpenRead("test.mp4");
stream.CopyTo(process.StandardInput.BaseStream);
process.StandardInput.BaseStream.Flush();
process.StandardInput.BaseStream.Close();
var stream2 = File.Create("test.png");
var buffer = new byte[4096];
int read;
while((read = process.StandardOutput.BaseStream.Read(buffer, 0, buffer.Length)) > 0)
stream2.Write(buffer, 0, read);
РЕДАКТИРОВАТЬ: Может быть полезно уточнить, какие данные содержит входной поток. Это в основном видеофайл, который может быть в любом широко используемом формате (avi, mp4, mov, ts, mkv, wmv, ...). Расширение видео (как будто это файл) также известно.