Я пытаюсь записать видео с камеры при использовании MediaFrameReader. Для моего приложения мне нужен экземпляр MediaFrameReader для обработки каждого кадра индивидуально. Я попытался дополнительно применить LowLagMediaRecording, чтобы просто сохранить поток камеры в файл, но кажется, что вы не можете использовать оба метода одновременно. Это означало, что я застрял в MediaFrameReader только там, где я могу получить доступ к каждому кадру в методе Frame_Arhibited.
Я попробовал несколько подходов и нашел два рабочих решения с классом MediaComposition, создающим объекты MediaClip. Вы можете либо сохранить каждый кадр как файл JPEG, либо отрендерить все изображения в видеофайл. Этот процесс очень медленный, так как вам постоянно нужен доступ к жесткому диску. Или вы можете создать объект MediaStreamSample из Direct3DSurface кадра. Таким образом, вы можете сохранить данные в ОЗУ (сначала в ОЗУ графического процессора, а затем в ОЗУ) вместо жесткого диска, который теоретически намного быстрее. Проблема в том, что для вызова метода RenderToFileAsync класса MediaComposition необходимо, чтобы все MediaClips уже были добавлены во внутренний список. Это приводит к превышению объема ОЗУ уже через довольно короткое время записи. После сбора данных в течение примерно 5 минут Windows уже создала файл подкачки размером 70 ГБ, который изначально не учитывает причину выбора этого пути.
Я также попробовал стороннюю библиотеку OpenCvSharp, чтобы сохранить обработанные кадры как видео. Я делал это ранее на Python без каких-либо проблем. Однако в UWP я не могу взаимодействовать с файловой системой без объекта StorageFile. Итак, все, что я получаю от OpenCvSharp, - это исключение UnauthorizedAccessException, когда я пытаюсь сохранить визуализированное видео в файловой системе.
Итак, подведем итоги: мне нужен способ рендеринга данных кадров моей камеры в видео, пока данные все еще поступают, поэтому я могу избавиться от каждого кадра после его обработки, как это сделала бы реализация OpenCV на Python . Я очень благодарен за каждый намек. Вот части моего кода, чтобы лучше понять контекст:
private void ColorFrameArrived(MediaFrameReader sender, MediaFrameArrivedEventArgs args)
{
MediaFrameReference colorFrame = sender.TryAcquireLatestFrame();
if (colorFrame != null)
{
if (currentMode == StreamingMode)
{
colorRenderer.Draw(colorFrame, true);
}
if (currentMode == RecordingMode)
{
MediaStreamSample sample = MediaStreamSample.CreateFromDirect3D11Surface(colorFrame.VideoMediaFrame.Direct3DSurface, new TimeSpan(0, 0, 0, 0, 33));
ColorComposition.Clips.Add(MediaClip.CreateFromSurface(sample.Direct3D11Surface, new TimeSpan(0, 0, 0, 0, 33)));
}
}
}
private async Task CreateVideo(MediaComposition composition, string outputFileName)
{
try
{
await mediaFrameReaderColor.StopAsync();
mediaFrameReaderColor.FrameArrived -= ColorFrameArrived;
mediaFrameReaderColor.Dispose();
StorageFolder folder = await documentsFolder.GetFolderAsync(directory);
StorageFile vid = await folder.CreateFileAsync(outputFileName + ".mp4", CreationCollisionOption.GenerateUniqueName);
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
await composition.RenderToFileAsync(vid, MediaTrimmingPreference.Precise);
stopwatch.Stop();
Debug.WriteLine("Video rendered: " + stopwatch.ElapsedMilliseconds);
composition.Clips.Clear();
composition = null;
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
}
}
MediaComposition
часто использовался для обрезки видео, он не мог обрабатывать реальный таймфрейм. Я не понимаю, почему вам просто нужно использовать MediaFrameReader для захвата видео? - person Nico Zhu - MSFT   schedule 03.03.2020MediaFrameReader
для выполнения нескольких задач, таких как получение метки времени каждого кадра. - person NicholasUrfe   schedule 04.03.2020