Создание видеофайла из SoftwareBitmap или Direct3DSurface без MediaComposition в UWP C# - PullRequest
4 голосов
/ 02 марта 2020

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

        }

1 Ответ

0 голосов
/ 10 марта 2020

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

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

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

# MediaCapture.AddVideoEffectAsyn c

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.

# Эффекты для анализа кадров камеры

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

Спасибо.

...