Создание видеофайла из SoftwareBitmap или Direct3DSurface без MediaComposition в UWP C #

Я пытаюсь записать видео с камеры при использовании 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);
            }

        }

person NicholasUrfe    schedule 02.03.2020    source источник
comment
Похоже, единственный способ конвертировать SoftwareBitmap в видеофайл на платформе uwp. Но MediaComposition часто использовался для обрезки видео, он не мог обрабатывать реальный таймфрейм. Я не понимаю, почему вам просто нужно использовать MediaFrameReader для захвата видео?   -  person Nico Zhu - MSFT    schedule 03.03.2020
comment
Привет и спасибо за ответ. Мне нужно вызвать MediaFrameReader для выполнения нескольких задач, таких как получение метки времени каждого кадра.   -  person NicholasUrfe    schedule 04.03.2020


Ответы (1)


Я пытаюсь записать видео с камеры при использовании MediaFrameReader. В моем приложении мне нужен экземпляр MediaFrameReader для обработки каждого кадра по отдельности.

Создайте собственный видеоэффект и добавьте его в объект MediaCapture, чтобы реализовать свое требование. Использование настраиваемого видеоэффекта позволит нам обрабатывать кадры в контексте объекта MediaCapture без использования MediaFrameReader, таким образом снимаются все ограничения MediaFrameReader, о которых вы упомянули.

Кроме того, он также имеет ряд встроенных эффектов, которые позволяют нам анализировать кадры камеры. Для получения дополнительной информации, пожалуйста, ознакомьтесь со следующими статьями:

# MediaCapture.AddVideoEffectAsync

https://docs.microsoft.com/en-us/uwp/api/windows.media.capture.mediacapture.addvideoeffectasync.

# Пользовательские видеоэффекты

https://docs.microsoft.com/en-us/windows/uwp/audio-video-camera/custom-video-effects.

#Effects для анализа кадров камеры

https://docs.microsoft.com/en-us/windows/uwp/audio-video-camera/scene-analysis-for-media-capture.

Спасибо.

person Amy Peng - MSFT    schedule 10.03.2020
comment
Спасибо за ответ. Я попробовал ваш подход и столкнулся с двумя проблемами: 1. Использование функции AddVideoEffectAsync значительно замедлило работу приложения. 2. Мне не удалось извлечь временные метки кадра, поскольку я мог использовать MediaFrameReader. В конце концов, я смог найти решение с помощью MediaFrameReader. Я обновлю свой пост, когда у меня будет на это время. Тем не менее, спасибо за ваше предложение, - person NicholasUrfe; 14.04.2020