I am working on WPF application running on .NET 6. Recently I encountered really strange behaviour with MediaElement control.
I have the backend service able to stream files, for instance videos. I want to embed a video player within the frontend (WPF) application with the streaming capability. I have already achieved this with libvlcsharp although it doesn't meet all the requirements (mainly performance) and is being left out as side/additional feature. I want to be able to stream multiple videos at the same time (in the same window as well) similar to youtube/instagram reels. For that purpose I decided to go with MediaElement control. I succesfully embeded multiple MediaElements but there are some issues.
I have confirmed that MediaElement doesn't work properly while on low bandwidth connection. While I am on my optic fiber 900+ Mbps connection everything works fine, the videos are being streamed with no issues. While on lower bandwidth (tested on two cellular networks with <20 Mbps) the Player is not loading/buffering/starting at all.
I could not find any related documentation. I believe it is not related to the file format and file size as I tested the same files on both networks. Files ranging from a few KB to a few GB.
User control:
<UserControl x:Class="Peernet.Browser.WPF.Controls.EmbededPluginsControl">
<Grid>
<MediaElement Grid.Row="0" Name="Player" LoadedBehavior="Manual" UnloadedBehavior="Stop" Stretch="Fill" />
</Grid>
</UserControl>
Code behind:
public partial class EmbededPluginsControl : UserControl
{
public static readonly DependencyProperty FileProperty =
DependencyProperty.Register("File", typeof(ApiFile),
typeof(EmbededPluginsControl), null);
public EmbededPluginsControl()
{
InitializeComponent();
Loaded += EmbededPluginsControl_Loaded;
}
private void EmbededPluginsControl_Loaded(object sender, RoutedEventArgs e)
{
var settings = App.ServiceProvider.GetService(typeof(ISettingsManager)) as ISettingsManager;
Player.Source = GetFileSource(settings, File);
}
public ApiFile File
{
get => (ApiFile)GetValue(FileProperty);
set => SetValue(FileProperty, value);
}
public static Uri GetFileSource(ISettingsManager settingsManager, ApiFile file)
{
var parameters = new Dictionary<string, string>
{
["hash"] = Convert.ToHexString(file.Hash),
["node"] = Convert.ToHexString(file.NodeId),
["format"] = "14",
["k"] = settingsManager.ApiKey
};
var uriBase = $"{settingsManager.ApiUrl}/file/view";
var requestMessage = HttpHelper.PrepareMessage(uriBase, HttpMethod.Get, parameters, null);
return requestMessage.RequestUri;
}
}
By default all Players are stopped, there is no issue such as that I try to run all at once and it is killing the network or something. There are buttons dedicated for Player as simple as:
<Image x:Name="PlayButton" Height="20" Width="20" MouseDown="OnMouseDownPlayMedia" Margin="5">
<Image.Style>
<Style TargetType="{x:Type Image}">
<Setter Property="Source" Value="{StaticResource PlayImage}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Source" Value="{StaticResource PlayImage_MouseOver}" />
</Trigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
and
void OnMouseDownPlayMedia(object sender, MouseButtonEventArgs args)
{
Player.Play();
}
I also don't manipulate programatically the Player stream, buffering, etc.
Do I have to reset the stream while connection drops or something? I am running out of ideas.