最近写了一系列关于WPF二维动画的Blog,今天准备写个程序来实战一下。由于手头上确实没有什么好的例子,便写了个离线的弹幕播放器,效果如下:
实际上,用WPF实现一个弹幕播放器还是比较简单的,主要分为如下几个步骤:
- 下载离线弹幕文件,并解析为程序比较方便的识别格式
- 加载弹幕数据,并生成弹幕动画TimeLine,这里我将每一个弹幕用一个TextBlock表示,用一个Canvas来承载这些弹幕。用关键帧动画来表示弹幕,并将动画和TextBlock关联起来。
- 使用MediaElement加载弹幕,使用时钟模式控制,即用MediaTimeline来控制动画的播放
- 将MediaTimeLine和弹幕动画放在一个Storyboard中,这样弹幕和视频在时间上就关联起来了。
- 将MediaElement和弹幕Canvas放在一个Grid中,这样弹幕和视频在空间上就关联起来了。
- 播放Storyboard,就能看到下图所示的弹幕播放器了。
所用到的技术点:
- 用MediaTimeline来控制MediaElement播放视频。
貌似网上的一些例子都是非常入门的使用独立模式控制MediaElement,这种方式下获取不到TimeLine,不过官方的MSDN也挺详细的:http://msdn.microsoft.com/zh-cn/library/system.windows.media.mediatimeline(v=vs.90).aspx - 弹幕文件的获取和解析。
貌似目前有三大弹幕网站ABC,并且各大弹幕网站的格式都不一样,因为我想找一个弹幕比较多的来测试一下效果和性能,选取的B站的弹幕,视频取的是其今天首页的Fate/stay night UBW,(顺便说一句,这个动画的画质实在太赞了),关于其弹幕的下载和解析方式可以参看这一地址:BILIBILI网站视频真实地址解析策略 ,BILIBILI站弹幕内容地址解析策略 。 - 弹幕动画的实现。
弹幕动画实际上是一个由静止(动画播放开始到弹幕出现)和移动(弹幕出现到弹幕小时)两个状态组成的关键帧动画,可以参看我之前写的文档: http://www.cnblogs.com/TianFang/p/4060397.html
性能优化:
既然涉及到了动画,那么性能就是一个比较令人关心的问题,我这里选取的是比较热门的视频,有3k多条弹幕,由于我这里只是练习,只选取了其中的滚动弹幕,貌似仍然有近2800条,最火的视频应该基本上也和它是一个数量级了。
我这里的实现方式非常简单,2800多个弹幕对应2800个TextBlock和TimeLine,并且是一开始全部创建及播放,这么做有性能问题吗?结果测试,如果一上来就这么干的话,加载视频的速度明显较慢,但是播放的过程还算流畅,但CPU占用较高。如何对它来进一步优化呢?
首先我们可以将操作细化一下,大概分为如下三个部分:
- 创建弹幕对应的Animation和TextBlock
- 将TextBlock放置到Canvas中
- 播放所有Animation
分别简单的测试了一下,1和3的开销非常小,呈现近3k个TextBlock的开销则是非常大的,如何优化呢?非常简单:一开始不加载所有的TextBlock,只把即将要显示到界面上的载TextBlock放到Canvas中,当其不在界面上呈现后,从Canvas中删除即可(这种方式简单粗暴,但改变了最开始的逻辑,导致时间线控制变复杂了,最好的方式是实现一个虚拟化的Canvas,随着时间线自动加载和卸载TextBlock)。
经过这一优化,在60帧的的播放速率下,基本上CPU的占用在13%左右,我是一个比较老的四核的i5,应该是占了一个cpu的一半,还是非常理想的。虽然还有进一步的优化空间,但感觉没有太大必要了。
实现过程感想:
用WPF实现弹幕播放器确实非常简单,只需要在最开始创建弹幕的TextBlock和Timeline,将其组装到一起,和视频的MediaTimeline关联到一起就可以了。中间过程完全不用关心,WPF动画框架都可以自动帮你完成,暂停,播放,进度跳转都不需要额外的编码。就连其它的弹幕播放器没有实现的快放和慢放它都能直接实现(这本身就是Timeline的一个属性,直接设置即可)。
到此为止,这个弹幕播放器的关键点都已经列举出来了,相信认真看过这篇文章和我之前的动画的那一系列Blog的朋友已经能够写出自己的弹幕播放器了。这个弹幕播放器本身只是我的一个饭后练手的作品,一共大概也就花了两个多小时,并且很大一部分的时间还是花在学习MediaElement的使用、解析B站数据的上面了,真正实现弹幕播放器的时间比写这篇文章还少。另外,这个播放器的目的是练习WPF动画的使用,而不是做一个弹幕播放器,实现得非常随意,代码实在无法见人。并且细节实现也是非常不完善的。
真正要实现一个弹幕播放器估计要话费数十倍于此时间,以后如果有时间的话可能会将其完善后发布成一个开源项目(当前工作太忙,短期内可能性不大)。有技术讨论欢迎留言交流,但要实现类似功能的朋友请不要在此留言索取代码了,貌似本身开源的弹幕播放器就有不少了。