Hello,
In UWP app, I want to play video and update the video file's property (Tags).
The following code works well for the C:\ local video file.
But, it throws error for video file from NAS (Network drive, I use synology): \MyNAS\video\Test\20201125_032706.mp4
MainPage.xaml
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="auto"></RowDefinition>
<RowDefinition></RowDefinition>
</Grid.RowDefinitions>
<StackPanel Orientation="Horizontal" Grid.Row="0">
<Button Content="Open" Click="OpenButton_Click"></Button>
<Button Content="Close and Update" Click="CloseUpdateButton_Click"></Button>
</StackPanel>
<MediaPlayerElement x:Name="mpPlayer"
AutoPlay="False"
AreTransportControlsEnabled="True"
Grid.Row="1"
Stretch="Uniform"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
>
</MediaPlayerElement>
</Grid>
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
mpPlayer.MediaPlayer.MediaEnded += MediaPlayer_MediaEnded;
mpPlayer.MediaPlayer.MediaOpened += MediaPlayer_MediaOpened;
mpPlayer.MediaPlayer.CurrentStateChanged += MediaPlayer_CurrentStateChanged;
}
async void Log(string msg)
{
System.Diagnostics.Debug.WriteLine(msg);
}
async private void MediaPlayer_CurrentStateChanged(Windows.Media.Playback.MediaPlayer sender, object args)
{
Log($"\n{DateTime.Now} - Media StateChanged - {sender.PlaybackSession.PlaybackState.ToString()}");
//=> Only paused called twice when closed.
}
async private void MediaPlayer_MediaOpened(Windows.Media.Playback.MediaPlayer sender, object args)
{
Log($"\n{DateTime.Now} - Media Opened");
}
async private void MediaPlayer_MediaEnded(Windows.Media.Playback.MediaPlayer sender, object args)
{
Log($"\n{DateTime.Now} - Media Ended");
}
StorageFile file;
async private void OpenButton_Click(object sender, RoutedEventArgs e)
{
var picker = new Windows.Storage.Pickers.FileOpenPicker();
picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;
picker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
picker.FileTypeFilter.Add(".mp4");
file = await picker.PickSingleFileAsync();
if (file != null)
{
// Application now has read/write access to the picked file
mpPlayer.Source = MediaSource.CreateFromStorageFile(file);
mpPlayer.MediaPlayer.Play();
}
}
async private void CloseUpdateButton_Click(object sender, RoutedEventArgs e)
{
try
{
mpPlayer.MediaPlayer.Pause();
mpPlayer.MediaPlayer.Source = null;
//mpPlayer.Source = EmptyVideo; //Sometimes work.
await Task.Delay(500);
VideoProperties vdPt = await file.Properties.GetVideoPropertiesAsync();
string[] keywords = new string[] { "Test", "Video", "Tags", "Update" };
vdPt.Keywords.Clear();
foreach (var tag in keywords) //Tags
{
vdPt.Keywords.Add(tag);
}
await vdPt.SavePropertiesAsync();
}
catch (Exception ex)
{
Log($"\n{DateTime.Now}\n {ex.Message}");
}
}
}
The code works well if I copy the video file into local drive (under C:\Temp) and tested. But it doesn't work from the video file from NAS drive, such as my Synology network drive over home wifi, \MyNAS\video\Test\20201125_032706.mp4.
And, it throws error:
"3/27/2021 4:52:35 PM - Media StateChanged - None
Exception thrown: 'System.IO.FileLoadException' in System.Private.CoreLib.dll
3/27/2021 4:52:36 PM
The process cannot access the file because it is being used by another process. (Exception from HRESULT: 0x80070020)"
Try to force to release the file played, I put extra code
await Task.Delay(500), but it doesn't work. Even I put 10 seconds or 1 minutes, it doesn't work well.
Also, I try to bind emptyVideo to release previous video, it sometimes work, but not always. Mostly no.
- Is there a way to force to release the video file from NAS?
- If NOT, is there a way to know or get notified via event when the file is released?
- If 1 and 2 is not possible, is there a way to check if the file is being used by another process programmatically?
Or, am I using wrong control? Or, is the code opening video is wrong?
Any comment helps,
Thank you!