播放器在加載一個新視頻的時候,通常會把當前畫面清空,然後開始渲染新視頻內容,但是播放器在加載到渲染的過程中需要一定的時間,雖然時間不長,但是在視頻切換的過程中用戶還是能看到屏幕會出現黑屏的情況。所以理想的解決辦法是,播放器在加載過程中不清空畫面,依舊保留上一個視頻的最後一幀。但是這種方案需要對播放器進行底層改造,這個對於不熟悉音視頻開發的人來說是一個很大的挑戰,所以本文基於WPF的MediaElement實現視頻的無縫切換,本方案不需要對播放器底層進行任何改動,不過會造成CPU和資源佔用的提升。
本方案的核心思路就是在播放視頻後就立刻創建一個新的MediaElement對象,並且設置好下一個視頻資源,等到當前視頻播放完成的時候,先讓新的MediaElement對象先進行Play加載資源,加載完成的時候再把這個MediaElement對象添加到界面上去,添加完成以後,移除之前的MediaElement,並且釋放相關資源,同時重複開頭的步驟。代碼如下:
public partial class MainWindow : Window
{
string dir = @"C:\Users\w9433\Desktop\";
string[] videos = {"1.mp4","12.mp4","13.mp4"};
int index;
MediaElement mNowMediaElement;
MediaElement mNextMediaElement;
public MainWindow()
{
InitializeComponent();
Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
mNowMediaElement = new MediaElement();
mNowMediaElement.MediaEnded += Player_MediaEnded;
mNowMediaElement.MediaOpened += Player_MediaOpened;
mNowMediaElement.LoadedBehavior = MediaState.Manual;
mNowMediaElement.UnloadedBehavior = MediaState.Manual;
mNowMediaElement.Stretch = Stretch.Uniform;
string path = dir + videos[index % videos.Length];
mNowMediaElement.Source = new Uri(path, UriKind.Absolute);
ContentView.Children.Add(mNowMediaElement);//這裏的ContentView就是一個根佈局 我這裏在xaml用的Canvas
mNextMediaElement = ReadyVideo();
mNowMediaElement.Play();
}
private void Player_MediaOpened(object sender, EventArgs e)
{
if (sender == mNextMediaElement) {
ContentView.Children.Add(mNextMediaElement);
}
}
private void Player_MediaEnded(object sender, EventArgs e)
{
mNextMediaElement.Play();
}
private MediaElement ReadyVideo()
{
MediaElement mNextMediaElement = new MediaElement();
mNextMediaElement.MediaEnded += Player_MediaEnded;
mNextMediaElement.MediaOpened += Player_MediaOpened;
mNextMediaElement.LoadedBehavior = MediaState.Manual;
mNextMediaElement.UnloadedBehavior = MediaState.Manual;
mNextMediaElement.Stretch = Stretch.Uniform;
mNextMediaElement.Loaded += MNextMediaElement_Loaded;
index++;
string path = dir + videos[index % videos.Length];
Console.WriteLine("下一個播放的視頻爲:" + path);
mNextMediaElement.Source = new Uri(path, UriKind.Absolute);
return mNextMediaElement;
}
private void MNextMediaElement_Loaded(object sender, RoutedEventArgs e)
{
mNowMediaElement.Stop();
mNowMediaElement.Close();
ContentView.Children.Remove(mNowMediaElement);
mNowMediaElement = mNextMediaElement;
mNextMediaElement = ReadyVideo();
}
}