• 在Silverlight中使用SmoothStreamingMediaElement创建Smooth Streaming播放器


      我在“IIS 7 Smooth Streaming技术在Silverlight 3中的应用 ”一文中详细介绍了有关IIS 7、Smooth Streaming技术以及如何在Silverlight中使用MediaElement控件播放Smooth Streaming视频的内容,在继续本文之前,如果你对什么是Smooth Streaming还存在疑问,你可以先去看看我的那篇文章,也算作是一个入门吧。

      在本文中,我将向大家介绍一个新控件——SmoothStreamingMediaElement,也被称之为SSME,它是IIS Smooth Streaming Player Development Kit工具包中的一个Silverlight控件,是在原MediaElement控件基础上的功能加强,主要增加了对Smooth Streaming视频源的直接支持以及一些相关事件。大家可以去微软的官方站点上下载该工具包,目前已经出到Beta2版了。

      在上一文中我向大家介绍了如何利用现有的MediaElement控件来支持Smooth Streaming视频的播放,事实上这种方法具有很大的局限性,例如控制播放进度、添加视频播放时的tracing事件等等。SmoothStreamingMediaElement控件作为MediaElement控件的一个加强版本,正好弥补了这方面的不足,同时,该控件也支持普通视频文件的播放。你当然还记得Smooth Streaming官方站点上的那个Big Buck Bunny演示影片,或许你也想知道它是怎么实现的,不要着急,在接下来的一系列文章中将会花点篇幅来向大家介绍,今天我们主要看看如何使用SSME控件,因为Big Buck Bunny的核心控件就是SSME。

    需要些什么

      1. 既然是开发一个Silverlight工程,那么首先Visual Studio和Silverlight Tool kits是肯定需要的,这点我就不详细介绍了,相信大家的这个环境都是具备的,如果不具备,可以去微软官网上找相关的资源。

      2. IIS Smooth Streaming Player Development Kit。目前的版本应该是Beta2版,下载后安装,你会发现Microsoft.Web.Media.SmoothStreaming.dll,这个正是我们所需要的。

      3. 另外就是一些开发Silverlight所要具备的知识了,如果你从未开发过Silverlight程序并且对Silverlight一无所知,那么我建议你不要继续往下看了。

    如何开始

      现在我们应该就可以着手开始我们的工程了。首先在Visual Studio中创建一个Silverlight工程,如下图。

    2010-1-21 13-58-19

       然后将Microsoft.Web.Media.SmoothStreaming.dll拷贝到你Silverlight工程的Bin\Debug\目录下(注意在Visual Studio中创建Silverlight项目时会同时创建一个用来进行测试的Web项目,不用将该文件复制到Web项目的Bin目录下),将该类库引用到Silverlight工程中。

      然后我们需要将SSME控件添加到MainPage.xaml页面上,有两种方法,第一种方法是在Visual Studio的工具箱中单击右键-“选择项”,在弹出的对话框中选择“Silverlight组建”选项卡,然后点击“浏览”,找到Microsoft.Web.Media.SmoothStreaming.dll文件,确定并关闭对话框,这时控件SSME会出现在Visual Studio的工具箱中,你可以直接将该控件拖放到页面上。这和在Visual Studio中添加普通的ASP.NET自定义控件是一样的。

    2010-1-21 14-05-50
      另一种方法是在页面中手动注册并引用控件。打开MainPage.xaml,在页面的头部添加下图所示的内容,Visual Studio的智能感知可以帮助你快速找到你要引用的命名空间。然后你在页面上就可以直接使用SSME命名空间下的控件了,其中就包含了SmoothStreamingMediaElement控件。

    image

    熟悉下SSME控件的常用属性和事件

      有必要先向大家介绍下SSME控件中一些常用的属性和事件,由于该控件没有包含在任何一个版本的Silverlight标准类库中,目前还只是一个测试版,所以微软官方提供的资料很少,在msdn上虽然能够见到它的身影,但是几乎没有任何示例和相关解释,读者可以查看一下它都包含哪些东西,http://msdn.microsoft.com/en-us/library/microsoft.web.media.smoothstreaming.smoothstreamingmediaelement_members.aspx。在这里我给出一些常用的属性和方法,如果你对MediaElement控件很熟悉,那么非常好,你可以毫不费力地过渡到SSME上,因为SSME几乎支持了MediaElement控件的全部属性和方法。

      AutoPlay:与MediaElement不同,除非你显示指定AutoPlay的值为True,否则即使SSME已经成功打开的视频源也不会自动播放视频。

      Source:播放普通视频文件时的地址。

      SmoothStreamingSource:播放Smooth Streaming视频文件时的地址。

      VideoPlaybackTrack.Bitrate:通过该值可以得到SSME当前播放影片的比特率,如果SSME当前播放的是Smooth Streaming格式的影片,那么比特率会随网络带宽动态发生变化。

      VideoDownloadTrack.Bitrate:同样的,通过该值可以得到当前下载影片的比特率。

      RenderedFramesPerSecond:通过该值可以得到当前播放影片的帧率(即每秒播放多少帧)。

      PlaybackTrackChanged:当播放影片的比特率发生变化时触发。

      DownloadTrackChanged:当下载影片的比特率发生变化时触发。

      细心的读者是否已经发现,我们通过上面给出的这些属性和事件,加上Silverlight里的路径动画,是不是就可以构造一个类似于Big Buck Bunny的播放器呢?先别着急,我们还是先熟悉熟悉SSME吧,我打算在下一篇文章中再来介绍那个让人找摸不透的播放器呢。

    继续完善我们的SSME播放器

      接着进行我们的工程。知道如何在工程中加入SSME了,下面你可以试着将这段代码复制到你的MainPage.xaml页面中。 

    <UserControl x:Class="SmoothStreamingPlayer.MainPage"
        xmlns
    ="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d
    ="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:SSME
    ="clr-namespace:Microsoft.Web.Media.SmoothStreaming;assembly=Microsoft.Web.Media.SmoothStreaming"
        mc:Ignorable
    ="d" d:DesignWidth="640" d:DesignHeight="480">
     
    <Grid x:Name="LayoutRoot">
           
    <Grid.RowDefinitions>
               
    <RowDefinition Height="0.90*"></RowDefinition>
               
    <RowDefinition Height="0.05*"></RowDefinition>
               
    <RowDefinition Height="0.05*"></RowDefinition>
           
    </Grid.RowDefinitions>
           
    <SSME:SmoothStreamingMediaElement AutoPlay="True" x:Name="SmoothPlayer" SmoothStreamingSource="http://localhost:77/Wildlife.ism/manifest" Grid.Row="0"/>
       
    </Grid>
    </UserControl>

      注意SmoothStreamingSource的值应当指定为一个你事先已经准备好的Smooth Streaming视频源,如果这个视频源不在本地,你可能需要添加跨域访问的代码,有关如何创建Smooth Streaming视频源以及如何架设Smooth Streaming视频服务,请参考“IIS 7 Smooth Streaming技术在Silverlight 3中的应用”一文。

      好了,按下F5,启动工程直接查看效果,你会发现浏览器中除了一块黑色外并没有播放你所指定的影片,怎么回事啊?难道视频地址给错了?首先请确保你所给出的地址可以通过浏览器直接访问,得出的结果应该类似于下面这样的画面:

    2010-1-21 14-59-08

      如果不能通过浏览器直接访问,那你就要检查你的视频服务了,或许你需要通过Expression Encoder重新转换视频并发布到IIS 7上。如果可以通过浏览器直接访问,那么恭喜你,你所看到的黑色画面是正常的。还记得我在上一文中说过调试Smooth Streaming播放器时只能通过IIS 7,而不能直接通过Visual Studio或者Blend吗?所以你不得不在你机器的IIS 7上部署一个Web站点,然后将用来进行测试的Web工程中的所有文件复制到Web站点中,然后通过浏览器进行访问。

      如果一切顺利的话,你应该可以在你的浏览器中看到影片了,仔细观察影片,你会看到一开始的时候画面是比较模糊的,但是SSME可以根据网络带宽动态调整画面质量,随着影片的播放,你会发现画面越来越清晰了。如果你仍然看不到影片,可能会有几个原因,首先还是视频服务的问题,你需要重新去确认视频服务是否可用并能正常访问;然后是权限的问题,你可以试着将浏览器地址中的localhost改为你的机器名,然后重新刷新浏览器,或者修改Silverlight工程中SSME的SmoothStreamingSource的地址,将其中的localhost改为你的机器名(如果你使用的是本地的视频源),如果视频源和Web站点都在同一台机器上,你应该同时使用localhost或是机器名。下面是在我本地看到的影片的播放效果:

    2010-1-21 15-10-09

     

    添加播放控制部分

      当然,一个像样的播放器是需要有播放控制面板的,我打算在我们的SSME播放器上添加一个播放进度条、音量控制、开始/暂停按钮、停止按钮。添加控件后的xaml代码如下:

    <UserControl
        
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
        xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d
    ="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:SSME
    ="clr-namespace:Microsoft.Web.Media.SmoothStreaming;assembly=Microsoft.Web.Media.SmoothStreaming"
        mc:Ignorable
    ="d" xmlns:dataInput="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.Input" x:Class="SmoothStreamingPlayer.MainPage"
        d:DesignWidth
    ="640" d:DesignHeight="480">
        
    <Grid x:Name="LayoutRoot">
            
    <Grid.RowDefinitions>
                
    <RowDefinition Height="0.90*"/>
                
    <RowDefinition Height="0.05*"/>
                
    <RowDefinition Height="0.05*"/>
            
    </Grid.RowDefinitions>
            
    <SSME:SmoothStreamingMediaElement AutoPlay="True" x:Name="SmoothPlayer" Grid.Row="0"/>
            
    <Slider x:Name="playSlider" Grid.Row="1" Cursor="Hand" Maximum="100"/>
            
    <ToggleButton x:Name="playToogleButton" Grid.Row="2" HorizontalAlignment="Left" Margin="8,0,0,4" Width="33" Content="暂停" Height="20" Cursor="Hand"/>
            
    <Slider Margin="115,4,0,8" Grid.Row="2" HorizontalAlignment="Left" Width="65" x:Name="volumeSlider" Cursor="Hand" Maximum="1" Value="{Binding Path=Volume, ElementName=SmoothPlayer, Mode=TwoWay}" />
            
    <dataInput:Label HorizontalAlignment="Left" Margin="87,3,0,5" Width="29" Grid.Row="2" Content="音量"/>
            
    <Button x:Name="stopButton" HorizontalAlignment="Left" Margin="45,0,0,4" Grid.Row="2" Content="停止" Width="33" Height="20" Cursor="Hand"/>
        
    </Grid>
    </UserControl>

       SSME的SmoothStreamingSource改到后台去指定了,为的是方便在Blend中打开Silverlight工程,因为Blend会默认在页面打开的时候自动加载视频并生成缩略图,由于我们指定的播放地址不是普通地址,视频加载的时候Blend会报错,导致页面无法在Blend中打开。

      UI界面已经完成了,尽管比较难看!说老实话,我也不是美工出身,对界面这方面也不是很在行。下面的工作就是让这些控件能够发挥作用,我将我的代码给出来,大家可以做个参考。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Net;
    using System.Windows;
    using System.Windows.Controls;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Animation;
    using System.Windows.Shapes;
    using System.Windows.Controls.Primitives;

    namespace SmoothStreamingPlayer
    {
        
    public partial class MainPage : UserControl
        {
            
    private const string VIDEOSOURCE = "http://localhost:77/Wildlife.ism/manifest";
            
    private TimeSpan _duration;

            
    public MainPage()
            {
                InitializeComponent();
                InitialPlayer();
            }

            
    //初始化属性和事件
            private void InitialPlayer()
            {
                
    this.SmoothPlayer.SmoothStreamingSource = new Uri(VIDEOSOURCE);
                
    //this.SmoothPlayer.Source = new Uri(VIDEOSOURCE);

                
    this.playToogleButton.Click += new RoutedEventHandler(playToogleButton_Click);
                
    this.stopButton.Click += new RoutedEventHandler(stopButton_Click);
                
    this.playSlider.ValueChanged += new RoutedPropertyChangedEventHandler<double>(playSlider_ValueChanged);

                
    this.SmoothPlayer.MediaOpened += new RoutedEventHandler(SmoothPlayer_MediaOpened);
                
    this.SmoothPlayer.MediaEnded += new RoutedEventHandler(SmoothPlayer_MediaEnded);
                
    this.SmoothPlayer.MarkerReached += new TimelineMarkerRoutedEventHandler(SmoothPlayer_MarkerReached);
            }

            
    //拖动播放进度条
            void playSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
            {
                
    double time = _duration.TotalSeconds / playSlider.Maximum * playSlider.Value;
                
    this.SmoothPlayer.Position = new TimeSpan(00, (int)time);
            }

            
    //停止播放
            void stopButton_Click(object sender, RoutedEventArgs e)
            {
                
    this.SmoothPlayer.Stop();
                playSlider.Value 
    = 0;
                playToogleButton.IsChecked 
    = true;
                playToogleButton.Content 
    = "播放";
            }

            
    //播放/暂停
            void playToogleButton_Click(object sender, RoutedEventArgs e)
            {
                ToggleButton button 
    = (ToggleButton)sender;
                
    if (button.IsChecked == true && this.SmoothPlayer.CanPause)
                {
                    
    this.SmoothPlayer.Pause();
                    
    this.playToogleButton.Content = "播放";
                }
                
    if (button.IsChecked == false)
                {
                    
    this.SmoothPlayer.Play();
                    
    this.playToogleButton.Content = "暂停";
                }
            }

            
    //控制播放进度条
            void SmoothPlayer_MarkerReached(object sender, TimelineMarkerRoutedEventArgs e)
            {
                
    this.Dispatcher.BeginInvoke(delegate()
                {
                    
    double time = e.Marker.Time.TotalSeconds;
                    
    double seconds = this.SmoothPlayer.NaturalDuration.TimeSpan.TotalSeconds;
                    
    if (seconds <= 0)
                    {
                        
    return;
                    }
                    
    double marker = (time * playSlider.Maximum / seconds);
                    playSlider.Value 
    = marker;
                });
            }

            
    //影片播放完后停止播放器并重置进度条
            void SmoothPlayer_MediaEnded(object sender, RoutedEventArgs e)
            {
                
    this.SmoothPlayer.Stop();
                playSlider.Value 
    = 0;
                playToogleButton.IsChecked 
    = true;
                playToogleButton.Content 
    = "播放";
            }

            
    //影片打开后初始化进度条
            void SmoothPlayer_MediaOpened(object sender, RoutedEventArgs e)
            {
                _duration 
    = this.SmoothPlayer.NaturalDuration.HasTimeSpan ? this.SmoothPlayer.NaturalDuration.TimeSpan : TimeSpan.FromMilliseconds(0);
                
    this.SmoothPlayer.Volume = 0.8;

                playSlider.Minimum 
    = 0;
                playSlider.Maximum 
    = 10;
                
    for (int i = (int)playSlider.Minimum; i < (int)playSlider.Maximum; i++)
                {
                    TimelineMarker marker 
    = new TimelineMarker();
                    
    double time = _duration.TotalSeconds / playSlider.Maximum * i;
                    marker.Time 
    = new TimeSpan(00, (int)time);
                    marker.Text 
    = string.Empty;
                    marker.Type 
    = string.Empty;
                    
    this.SmoothPlayer.Markers.Add(marker);
                }
            }
        }
    }

       其中播放进度条的控制使用了TimelineMarker,由于我要播放的影片是Win7自带的一个高清视频演示文件,播放时长比较短,所以我将Maximum的值设得比较小,你可以根据影片的长短来设定该值。另外,我在程序中将播放地址hard-code到代码里了,你完全可以通过页面上的InitParams参数将播放地址传进来,也或者你可以将播放参数写到playlist里作为xml传进来。

      好了,一切搞定!现在你可以在浏览器中预览SSME播放器啦,下面是在我机器上看到的效果。

    2010-1-21 16-29-00

    结语

      使用SSME可以非常方便地支持Smooth Streaming视频的播放,Silverlight程序员几乎不用做任何额外的工作就可以让自己的Silverlight播放器支持Smooth Streaming视频流,同时,你可以在程序中做出判断以决定让SSME播放普通的视频还是Smooth Streaming视频。接下来的内容我将向大家介绍如何利用SSME并结合FrameRateGraph、BitrateGraph等控件实现一个完整的Big Buck Bunny播放器。

  • 相关阅读:
    生活中残忍的真相
    @ControllerAdvice 拦截异常并统一处理
    自律的人生
    50建议
    公众号自动发送红包
    增加记忆力方式
    MySQL行转列与列转行
    微人生的活法
    人生三出戏
    很重要的一点是 关注并坚持去做那些短期看不到效果,但对你影响深远的事情。
  • 原文地址:https://www.cnblogs.com/jaxu/p/1653314.html
Copyright © 2020-2023  润新知