65.9K
CodeProject 正在变化。 阅读更多。
Home

在 Silverlight 中播放带字幕的视频

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.17/5 (5投票s)

2009年2月10日

CPOL

3分钟阅读

viewsIcon

35886

downloadIcon

814

在 Silverlight 中播放带字幕的视频

引言

本文介绍如何在 Silverlight 中播放视频字幕。实现此功能非常容易。

背景

我需要在 Silverlight 视频中播放字幕。

我开始使用计时器实现此功能。我们可以将计时器间隔设置为 500 毫秒,计时器每 500 毫秒触发一次事件。我们可以编写逻辑来显示/隐藏字幕栏,从而实现我们的目标,但此方法存在问题。视频会缓冲,这会导致计时器与视频位置失去同步,因此此方法无法处理媒体缓冲的情况。

我找到了另一种实现方法。MediaElement 具有与当前加载的媒体元素关联的时间线标记集合。每次 MediaElement 打开新的媒体文件时,都会清除并重新填充该集合,并且仅在 MediaOpened 事件发生后才被认为是有效的。有关标记的更多信息,请访问以下链接:http://msdn.microsoft.com/en-us/library/system.windows.controls.mediaelement.markers(VS.95).aspx

读者应该了解 Silverlight 的基础知识和 MediaElement 控件,才能理解本文。

Using the Code

我没有将媒体文件添加到 Zip 文件中,因此在运行解决方案之前,您必须在 Web 项目的 ClientBin 文件夹中添加一个名为 "SUP015.wmv" 的 WMV 文件。

定义字幕类,该类应具有字幕的开始时间、字幕的结束时间和字幕的消息。

public class Title
{
    public string Id { get; set; }
    public double InTime { get; set; }
    public double OutTime { get; set; }
    public string Message { get; set; }
}

我们可以使用 MarkerReached 事件,以便在视频到达字幕的开始或结束时间时收到通知。当 MediaElement 跳过时间线标记时,不会引发 MarkerReached 事件。每当到达与媒体关联的标记时,就会引发此事件。该标记可能来自以下三个位置之一:存储在当前打开的媒体的元数据中,与当前打开的媒体关联,或者来自单独的流,使用脚本显式添加到当前打开的媒体的 Markers 集合中。我们可以在 MediaElement 的 loaded 事件中订阅上述事件。

this.MediaEl.MarkerReached += 
  new TimelineMarkerRoutedEventHandler(MediaEl_MarkerReached);

在播放媒体之前,我们必须为所有字幕添加标记。我们可以使用标记的两个属性:TimeTypeTimeMediaElement 引发 MarkerReached 事件的时间跨度,Type 是一个字符串,可用于在 MarkerReached 事件发生时标识字幕。我们可以使用以下代码将所有字幕添加到 Markers 集合中

private void AddMarker()
{
    foreach(Title comment in list)
    {
        this.MediaEl.Markers.Add(new TimelineMarker(){
            Time = TimeSpan.FromSeconds(comment.InTime),
            Type = comment.Id.ToString() + ":Start", Text = "Test"});
        this.MediaEl.Markers.Add(new TimelineMarker() {
            Time = TimeSpan.FromSeconds(comment.OutTime),
            Type = comment.Id.ToString() + ":End", Text = "Test" });
    }
}

在这里,我们使用 Type 来标识字幕以及它是字幕的开始还是结束。我们将每个字幕两次添加到 Markers 集合中,一次用于字幕的开始,一次用于字幕的结束。

以下是 MarkerReached 事件的代码

private void MediaEl_MarkerReached(object sender, TimelineMarkerRoutedEventArgs e)
{
    string[] array = e.Marker.Type.Split(':');
    if(array != null && array.Length == 2)
    {
        if(array[1] == "Start")
        {
            Title comment = list.SingleOrDefault(x => x.Id == array[0]);
            if(comment != null)
            {
                this.CommentCanas.Visibility = System.Windows.Visibility.Visible;
                CommentText.Text = comment.Message + " TimeSpan:" +
                                   this.MediaEl.Position.ToString();
            }
        }
        else if(array[1] == "End")
        {
            this.CommentCanas.Visibility = System.Windows.Visibility.Collapsed;
            CommentText.Text = string.Empty;
        }
    }
}

我们可以从事件参数中获取标记的 Type 值。Type 包含字幕的唯一 ID 以标识字幕,以及 StartEnd 以标识字幕的开始或结束。如果是 Start,那么我们可以将 CanvasVisibility 设置为 Visible 并设置文本。如果是 End,那么我们可以将 CanvasVisibility 设置为 Collapsed

© . All rights reserved.