使用MediaElement和Storyboard连续播放视频

3
我有一系列按顺序录制的视频文件。我需要在我的应用程序中按照相同的顺序播放它们。
1. 我已经知道每个视频的相对开始时间和持续时间。 2. 下一个视频可能要等好几秒、几分钟,甚至几个小时后才开始录制。 3. 我需要某种位置更改通知,以便可以将其他UI元素与视频位置同步(例如图形)。 4. 在没有录制视频的部分,视频窗口将显示空白屏幕。 5. 不幸的是,目前我只能使用WinForms,但我正在将MediaElement嵌入ElementHost。
看起来MediaTimeline + Storyboard组合很适合我的需要。Storyboard提供了CurrentTimeInvalidated事件,满足条件3。至于条件1和条件2,我相信我可以为每个视频创建一个MediaTimeline,并将它们全部添加到Storyboard中作为子项。似乎我已经部分实现了它,但仍然遇到一些问题。
在当前的实现中,Storyboard从头到尾播放得非常好。然而,视频只显示在最后一个添加到Storyboard的视频上。
这是我想要实现的视频时间轴播放器的一些简化的伪代码。
public class VideoTimelineEntry
{
    public Uri Uri;
    public TimeSpan RelativeStartTime;
    public TimeSpan Duration;
}

public class VideoTimelinePlayer : System.Windows.Forms.UserControl
{
    private MediaElement _mediaElement = ...; // Contained in ElementHost
    private Storyboard _storyboard = new Storyboard();

    public void LoadTimeline(IEnumerable<VideoTimelineEntry> entries)
    {
        foreach (VideoTimelineEntry entry in entries)
        {
            MediaTimeline mediaTimeline = new MediaTimeline
            {
                BeginTime = entry.RelativeStartTime,
                Duration  = new Duration(entry.Duration),
                Source    = entry.Uri
            };

            _storyboard.Children.Add(mediaTimeline);

            // I think this is my problem. How do I set the target
            // so that it is always playing the current video, and
            // not just the last one in my timeline?
            Storyboard.SetTarget(mediaTimeline, _mediaElement);
        }
    }

    public void Play()
    {
        _storyboard.Begin();
    }

    public void Pause()
    {
        _storyboard.Pause();
    }

    public void Stop()
    {
        _storyboard.Stop();
    }
}

任何帮助都将不胜感激。
1个回答

3
看起来每个MediaTimeline只能定位到1个MediaElement。为了解决这个问题,我现在为每个MediaTimeline创建一个专用的MediaElement。我认为这不是一个好的解决方案,但是除非我想处理轮询/定时和动态更改视频源,否则我想不到更好的方法。然而,我使用Storyboard的原因是为了避免这样做。
更新7/24/14: 我决定发布一个非常简化的示例来改进这个答案。
public void LoadTimeline(IEnumerable<MediaTimeline> mediaTimelines)
{
    // Check that none of the timelines overlap as specified by the
    // acceptance criteria.
    // e.g. timeline2.BeginTime < timeline1.BeginTime + timeline1.Duration.

    _storyboard.Children.Clear();

    foreach (MediaTimeline mediaTimeline in mediaTimelines)
    {
        _storyboard.Children.add(mediaTimeline);

        MediaElement mediaElement = new MediaElement();

        // _grid is just an empty <Grid></Grid> in the xaml layer.
        _grid.Children.Add(mediaElement);

        // Each media timeline now targets a dedicated media element.
        Storyboard.SetTarget(mediaTimeline, mediaElement);

        // Bring the active media element to the top.
        mediaTimeline.CurrentStateInvalidated += (sender, args) =>
        {
            Panel.SetZIndex(mediaElement, int.MaxValue);
        };
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接