MediaTranscoder.PrepareFileTranscodeAsync UnauthorizedAccessException

У меня есть кнопка на странице со следующим методом для события нажатия кнопки:

StorageFile _sourceFile;    
private string _sourceToken;
private async void btnSelect_Click(object sender, RoutedEventArgs e)
{
    FileOpenPicker fop = new FileOpenPicker();
    fop.FileTypeFilter.Add(".mp4");

    StorageFile inFile = await fop.PickSingleFileAsync();
    _sourceToken = Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.Add(inFile);

    _sourceFile = await Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.GetFileAsync(_sourceToken);
    mediaElement.AutoPlay = false;
    IRandomAccessStream stream = await _outFile.OpenAsync(FileAccessMode.ReadWrite);
    mediaElement.SetSource(stream, _outFile.ContentType);

}

Если я нажму кнопку воспроизведения в MediaElement, выбранное видео будет воспроизводиться нормально.

У меня также есть еще одна кнопка, которая имеет следующий код в событии щелчка:

private async void btnExport_Click(object sender, RoutedEventArgs e)
{
    StorageFile outFile = await KnownFolders.VideosLibrary.CreateFileAsync("Outfie.mp4", CreationCollisionOption.ReplaceExisting);

    MediaEncodingProfile profile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD1080p);

    MediaTranscoder transcoder = new MediaTranscoder();

    PrepareTranscodeResult prepareOp = await transcoder.PrepareFileTranscodeAsync(_sourceFile, outFile, profile);

    if (prepareOp.CanTranscode)
    {
        var transcodeOp = prepareOp.TranscodeAsync();

        transcodeOp.Progress += new AsyncActionProgressHandler<double>(TranscodeProgress);
        transcodeOp.Completed += new AsyncActionWithProgressCompletedHandler<double>(TranscodeComplete);
    }
    else
    {
        switch (prepareOp.FailureReason)
        {
            case TranscodeFailureReason.CodecNotFound:
                System.Diagnostics.Debug.WriteLine("Codec not found.");
                break;
            case TranscodeFailureReason.InvalidProfile:
                System.Diagnostics.Debug.WriteLine("Invalid profile.");
                break;
            default:
                System.Diagnostics.Debug.WriteLine("Unknown failure.");
                break;
        }
    }
}

К сожалению, строка transcoder.PrepareFileTranscodeAsync выдает исключение UnauthorizedAccessException. Но если я использую следующее вместо _sourceFile, это работает:

StorageFile sourceFile = await KnownFolders.VideosLibrary.GetFileAsync("sourceFile.mp4");

Выдается ошибка:

System.UnauthorizedAccessException: «Доступ запрещен. (Исключение из HRESULT: 0x80070005 (E_ACCESSDENIED))'

Чтобы было ясно, я выбираю файлы ВНЕ перечисления KnownFolders, поэтому я использую Windows.Storage.AccessCache.StorageApplicationPermissions.FutureAccessList.

Кто-нибудь может объяснить, почему?

РЕДАКТИРОВАТЬ: если я изменю исходный файл на результат FileOpenPicker, тогда он сработает. Поэтому возникает вопрос, почему FutureAccessList не работает??

private async void btnExport_Click(object sender, RoutedEventArgs e)
{
    StorageFile outFile = await KnownFolders.VideosLibrary.CreateFileAsync("Outfie.mp4", CreationCollisionOption.ReplaceExisting);

    FileOpenPicker fop = new FileOpenPicker();
    fop.SuggestedStartLocation = PickerLocationId.ComputerFolder;
    fop.FileTypeFilter.Add(".mp4");

    StorageFile sourceFile = await fop.PickSingleFileAsync();

    MediaEncodingProfile profile = MediaEncodingProfile.CreateMp4(VideoEncodingQuality.HD1080p);

    MediaTranscoder transcoder = new MediaTranscoder();

    PrepareTranscodeResult prepareOp = await transcoder.PrepareFileTranscodeAsync(sourceFile, outFile, profile);

    if (prepareOp.CanTranscode)
    {
        var transcodeOp = prepareOp.TranscodeAsync();

        transcodeOp.Progress += new AsyncActionProgressHandler<double>(TranscodeProgress);
        transcodeOp.Completed += new AsyncActionWithProgressCompletedHandler<double>(TranscodeComplete);
    }
    else
    {
        switch (prepareOp.FailureReason)
        {
            case TranscodeFailureReason.CodecNotFound:
                System.Diagnostics.Debug.WriteLine("Codec not found.");
                break;
            case TranscodeFailureReason.InvalidProfile:
                System.Diagnostics.Debug.WriteLine("Invalid profile.");
                break;
            default:
                System.Diagnostics.Debug.WriteLine("Unknown failure.");
                break;
        }
    }
}

person Andrew Harris    schedule 23.04.2017    source источник


Ответы (2)


У вас есть доступ к файлу, в который вы пытаетесь записать? Может быть, он доступен только для чтения или создан другим пользователем, кроме вас? (Щелкните правой кнопкой мыши + Свойства на файле в проводнике, чтобы получить более четкое представление о правах доступа к файлу)

Кроме того, вы можете получить это исключение, если пытаетесь записать в папку, к которой у вас нет доступа.

Проверьте свои учетные данные, я предполагаю, что это что-то связанное с этим.

person Jonathan Perry    schedule 23.04.2017
comment
Согласитесь, определенно проблема с разрешениями, но обратите внимание на следующую строку: IRandomAccessStream stream = await _outFile.OpenAsync(FileAccessMode.ReadWrite); Что терпит неудачу, когда у меня нет разрешения в первую очередь. - person Andrew Harris; 23.04.2017
comment
Почему это не потерпит неудачу, если у вас нет разрешений? Вы запрашиваете доступ к чтению/записи файла, который вам не разрешено изменять. - person Jonathan Perry; 23.04.2017
comment
Я имел в виду, что у меня есть разрешения. Я бы не смог выполнить OpenAsync, требующий чтения/записи, если бы у меня не было разрешений. - person Andrew Harris; 23.04.2017
comment
@AndrewHarris Не могли бы вы опубликовать полное сообщение, вызванное исключением? - person Jonathan Perry; 23.04.2017
comment
Только что обновил вопрос, добавив дополнительную информацию. Кажется, FutureAccessList не сохраняет разрешения. - person Andrew Harris; 24.04.2017

Так что похоже на то, что я открывал исходный файл в режиме ReadWrite

IRandomAccessStream stream = await _outFile.OpenAsync(FileAccessMode.ReadWrite);

Был причиной проблем. Согласно этой странице

Используйте режим чтения/записи только тогда, когда вы готовы немедленно начать запись, чтобы избежать конфликтов с другими операциями.

Поэтому я перешел на это, и все работает хорошо

IRandomAccessStream stream = await _outFile.OpenAsync(FileAccessMode.Read);
person Andrew Harris    schedule 24.04.2017
comment
Спасибо за интерес :) - person Andrew Harris; 24.04.2017