Консольное шаблонное приложение MediaCapture не может записать видео - PullRequest
1 голос
/ 31 мая 2019

Я пытаюсь использовать MediaCapture в минимальном консольном приложении C # UWP для захвата видео.Инициализация MediaCapture с InitializeAsync () работает, но на самом деле запуск записи завершается неудачно с кодом ошибки 0xc00d3e82 / MF_E_INVALID_STATE_TRANSITION.

Я установил шаблоны консольного приложения C # UWP в Visual Studio 2017 для работы на минимальном приложении (графический интерфейс пользователяв этом случае нет необходимости, таким образом, консольное приложение), которое будет захватывать видео с помощью MediaCapture.Минимальная цель - сборка Windows 1803, так как это минимум, необходимый для консольных приложений C # UWP.

Я пытался запустить методы, требующие ожидания, с ConfigureAwait(false), но, похоже, это не имеет никакого значения.

Что касается возможностей, так как консольные приложения UWP не будут отображать запросы разрешений для получения доступа к камере, микрофону и т. Д., Я предоставляю их вручную через настройки приложения перед его запуском.Я считаю, что все необходимые возможности включены в манифест, так как приложение работает при некоторых обстоятельствах (см. Абзац после блока кода).

Минимальный воспроизводимый пример, должен собираться и работать с шаблоном консольного приложения C # UWP:

using System;
using System.Threading.Tasks;
using Windows.Devices.Enumeration;
using Windows.Media.Capture;
using Windows.Media.MediaProperties;
using Windows.Storage;

namespace MinimalMediaCaptureConsoleTest
{
    class Program
    {
        private static void MediaCapture_Failed(MediaCapture sender, MediaCaptureFailedEventArgs errorEventArgs)
        {
            Console.WriteLine("Media capture failed: error message: '" + errorEventArgs.Message + "', code: " + errorEventArgs.Code.ToString("X"));
        }
        static void Main(string[] args)
        {
            Task t = MainAsync(args);
            t.Wait();
            Task.Delay(2000).Wait(); // give time to see result before exiting
        }
        static async Task MainAsync(string[] args)
        {
            var videoDevices = await DeviceInformation.FindAllAsync(DeviceClass.VideoCapture);
            var cameraDevice = videoDevices[0];
            if (cameraDevice == null)
            {
                Console.WriteLine("No camera device found!");
                return;
            }

            MediaCapture mc = new MediaCapture();
            MediaCaptureInitializationSettings mcSettings = new MediaCaptureInitializationSettings
            {
                AudioDeviceId = "",
                VideoDeviceId = cameraDevice.Id,
                StreamingCaptureMode = StreamingCaptureMode.Video,
                PhotoCaptureSource = PhotoCaptureSource.VideoPreview
            };
            mc.Failed += MediaCapture_Failed;
            try
            {
                await mc.InitializeAsync(mcSettings);

            } catch (UnauthorizedAccessException e)
            {
                Console.WriteLine("No access to the camera: " + e);
            }

            LowLagMediaRecording mediaRecording = null;
            var myVideos = await Windows.Storage.StorageLibrary.GetLibraryAsync(Windows.Storage.KnownLibraryId.Videos);
            StorageFile file = await myVideos.SaveFolder.CreateFileAsync("mytestvid.mp4", CreationCollisionOption.GenerateUniqueName);
            mediaRecording = await mc.PrepareLowLagRecordToStorageFileAsync(
                      MediaEncodingProfile.CreateMp4(VideoEncodingQuality.Auto), file);

            await mediaRecording.StartAsync();
            Console.WriteLine("Started recording, press enter to stop");
            Console.ReadLine();
            await mediaRecording.StopAsync();
        }
    }
}

Код запускается в отдельной асинхронной задаче, запускаемой из Main () консольного приложения, однако я также попытался сделать саму Main асинхронной задачей и запустить код MediaCapture непосредственно оттуда, безразница в поведении.

Интересно, что если я запускаю приложение с помощью отладчика Visual Studio или присоединяю отладчик к процессу перед попыткой записи видео, захват видео работает просто отлично.Однако при запуске из командной строки / Powershell или из меню «Пуск» вызов метода StartAsync () экземпляра LowLagMediaRecording приведет к вышеупомянутому коду ошибки 0xc00d3e82 / MF_E_INVALID_STATE_TRANSITION, и видео не будет записано.

Любые идеи о том, что проблема при запуске безотладчик и как его исправить очень ценятся.

1 Ответ

0 голосов
/ 04 июня 2019

Есть ли какая-то особая причина, по которой это должно быть приложение UWP? (могут быть определенные проблемы / сложности с приложениями консоли UWP и фоновой записью) Если UWP не важен, вы также можете использовать MediaCapture в консольном приложении Win32, которое кажется более подходящим (и более простым решением) в этой ситуации. для C # обратитесь к - https://github.com/microsoft/WindowsVisionSkillsPreview/blob/master/samples/SentimentAnalyzerCustomSkill/cs/Apps/FaceSentimentAnalysisApp_.NETCore3.0/FaceSentimentAnalysisApp_.NETCore3.0.csproj

Примечание. Этот образец C # делает больше, чем просто Windows MediaCapture. Тем не менее, вы можете игнорировать другие вещи и ссылаться только на конфигурацию проекта в образце и использовать тот же код C #, который вы используете в настоящее время. Для этого вам потребуется предварительный просмотр .Net Core 3.0 и Visual Studio 2019.
Следующие строки из приведенного выше файла .csproj имеют значение: C: \ Program Files (x86) \ Справочные сборки \ Microsoft \ Framework.NETCore \ v4.5 \ System.Runtime.WindowsRuntime.dll

<Reference Include="Windows">
  <HintPath>C:\Program Files (x86)\Windows Kits\10\UnionMetadata\Facade\Windows.WinMD</HintPath>
  <IsWinMDFile>true</IsWinMDFile>
</Reference>

<Reference Include="Windows.Foundation.FoundationContract">
  <HintPath>C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Foundation.FoundationContract\3.0.0.0\Windows.Foundation.FoundationContract.winmd</HintPath>
  <IsWinMDFile>true</IsWinMDFile>
</Reference>

<Reference Include="Windows.Foundation.UniversalApiContract">
  <HintPath>C:\Program Files (x86)\Windows Kits\10\References\10.0.17763.0\Windows.Foundation.UniversalApiContract\7.0.0.0\Windows.Foundation.UniversalApiContract.winmd</HintPath>
  <IsWinMDFile>true</IsWinMDFile>
</Reference>

В качестве альтернативы для C ++ см. - https://github.com/microsoft/Windows-Camera/tree/master/Samples/WMCConsole_winrtcpp

...