Я пытаюсь записать видео с камеры при использовании MediaFrameReader. Для моего приложения мне нужен экземпляр MediaFrameReader для обработки каждого кадра в отдельности. Я попытался применить LowLagMediaRecording дополнительно, чтобы просто сохранить поток камеры в файл, но кажется, что вы не можете использовать оба метода одновременно. Это означало, что я застрял в MediaFrameReader только там, где я могу получить доступ к каждому кадру в методе Frame_Arrived.
Я попробовал несколько подходов и нашел два рабочих решения с классом MediaComposition, создающих объекты MediaClip. Вы можете сохранить каждый кадр в виде JPEG-файла и, наконец, отобразить все изображения в видеофайл. Этот процесс очень медленный, так как вам постоянно требуется доступ к жесткому диску. Или вы можете создать объект MediaStreamSample из Direct3DSurface фрейма. Таким образом, вы можете сохранить данные в ОЗУ (сначала в ОЗУ графического процессора, если оно заполнено, затем ОЗУ), а не на жестком диске, который теоретически намного быстрее. Проблема в том, что для вызова RenderToFileAsyn c -метода класса MediaComposition требуется, чтобы все MediaClips уже были добавлены во внутренний список. Это приводит к превышению оперативной памяти после уже довольно короткого времени записи. После сбора данных в течение примерно 5 минут windows уже создал файл подкачки объемом 70 ГБ, который в первую очередь не определяет причину выбора этого пути.
Я также попытался использовать стороннюю библиотеку OpenCvSharp, чтобы сохранить обработанные кадры как видео. Я сделал это ранее в python без проблем. В UWP, однако, я не могу взаимодействовать с файловой системой без объекта StorageFile. Итак, все, что я получаю от OpenCvSharp, - это UnauthorizedAccessException, когда я пытаюсь сохранить визуализированное видео в файловую систему.
Итак, подведем итог: мне нужен способ визуализации данных кадров моей камеры в видео, в то время как данные все еще поступают, поэтому я могу распоряжаться каждым кадром после его обработки, как это сделала бы реализация python OpenCV. Я очень благодарен за каждый намек. Вот части моего кода, чтобы лучше понять контекст:
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);
}
}