GithubHelp home page GithubHelp logo

m13253 / danmaku2ass Goto Github PK

View Code? Open in Web Editor NEW
544.0 19.0 89.0 977 KB

Convert comments from Niconico/AcFun/bilibili to ASS format

Home Page: http://m13253.blogspot.com/2013/11/play-danmaku-offline-danmaku2ass.html

License: GNU General Public License v3.0

Makefile 1.85% Shell 1.46% Python 96.69%

danmaku2ass's Introduction

Danmaku2ASS

What is it?

Danmaku2ASS converts comments from Niconico/Acfun/Bilibili to ASS format so that you can play it with any media player supporting ASS subtitle.

This software is free software released under GPL 3 license. There is no warranty to the extent permitted by law.

How to use it?

First, you will have to get the XML or JSON file from Niconico/Acfun/Bilibili, many software can help you get it. For example, you-get and nicovideo-dl.

Then, execute danmaku2ass. You can see further instructions below.

Installing

You may install danmaku2ass with the Makefile provided.

make
make install

PREFIX= is accepted by make install for specifying installation prefix.

A PKGBUILD is also provided.

Example usage

./danmaku2ass -o foo.ass -s 1920x1080 -fn "MS PGothic" -fs 48 -a 0.8 -dm 5 -ds 5 foo.xml

Name the output file with same basename but different extension (.ass) as the video. Put them into the same directory and most media players will automatically load them. For MPlayer, you will have to specify -ass option.

Make sure that the width/height ratio passed to danmaku2ass matches the one of your original video, or text deformation may be experienced.

You can also pass multiple XML/JSON files and they will be merged into one ASS file. This is useful when watching danmakus from different website at the same time.

Screenshot

5 Centimeters Per Second with Danmaku2ASS

Video: 5 Centimeters Per Second

Source: http://www.bilibili.tv/video/av135209/

Players for a specific site

If you prefer to watch videos on a specific site listed below with a media player, you can check these projects, which usually provide online streaming features:

  • Bilibili: BiliDan, (MPV Player, FFmpeg, Linux, OS X, (unstable on) Windows), officially supported by Danmaku2ASS contributer
  • Bilibili: BiliGui, (MPV Player, Ruby, Qt4, FFmpeg, Linux)
  • Bilibili: Biligrab, (Aria2, Python2, FFmpeg, OS X, (unstable on) Linux)
  • Bilibili: MoonPlayer, (MPlayer, Qt4, Linux, Windows)
  • Tudou Doupao, Acfun, Bilibili: Yatto, (MPV Player, FFmpeg, Linux)

Please submit your work if you have made a better one!

Command line reference

usage: danmaku2ass.py [-h] [-f FORMAT] [-o OUTPUT] -s WIDTHxHEIGHT [-fn FONT]
                      [-fs SIZE] [-a ALPHA] [-dm SECONDS] [-ds SECONDS]
                      [-fl FILTER] [-p HEIGHT] [-r]
                      FILE [FILE ...]

positional arguments:
  FILE                  Comment file to be processed

optional arguments:
  -h, --help            show this help message and exit
  -f FORMAT, --format FORMAT
                        Format of input file (autodetect|Bilibili|Tudou2|MioMi
                        o|Acfun|Niconico|Tudou) [default: autodetect]
  -o OUTPUT, --output OUTPUT
                        Output file
  -s WIDTHxHEIGHT, --size WIDTHxHEIGHT
                        Stage size in pixels
  -fn FONT, --font FONT
                        Specify font face [default: sans-serif]
  -fs SIZE, --fontsize SIZE
                        Default font size [default: 25]
  -a ALPHA, --alpha ALPHA
                        Text opacity
  -dm SECONDS, --duration-marquee SECONDS
                        Duration of scrolling comment display [default: 5]
  -ds SECONDS, --duration-still SECONDS
                        Duration of still comment display [default: 5]
  -fl FILTER, --filter FILTER
                        Regular expression to filter comments
  -flf FILTER_FILE, --filter-file FILTER_FILE
                        Regular expressions from file (one line one regex) to filter comments
  -p HEIGHT, --protect HEIGHT
                        Reserve blank on the bottom of the stage
  -r, --reduce          Reduce the amount of comments if stage is full

FAQ

The text is moving laggy. / The text is slightly blurred.

Most ASS renderers render ASS subtitles at the same resolution as the video. This is probably because the video is at low resolution or framerate.

If you use MPlayer, you can add options similar to -vf scale=1920:1080 (change the values as you wish).`

I would like to render the danmakus into the video.

Use ffmpeg:

ffmpeg -i foo.flv -vf ass=foo.ass -vcodec libx264 -acodec copy foo-with-danmaku.flv

Change the parameters as you like.

Danmaku2ASS gave me some warnings of 'Invalid comment'.

This is probably because of comment styles that are not recognized by Danmaku2ASS. This is mostly normal. However, if you think that Danmaku2ASS missed some important things, please feel free to submit an issue.

Is there a GUI?

Currently no. But there will soon be one made of Gtk+ 3. If you would like to help me, please contact with me.

Contributing

Any contribution is welcome. Any donation is welcome as well.

danmaku2ass's People

Contributors

910jqk avatar alex8224 avatar asahui avatar coslyk avatar gesrua avatar goshin avatar guopm avatar implelee avatar lilhayah avatar m13253 avatar mingcongbai avatar qbnu avatar xziar avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

danmaku2ass's Issues

[功能需求]转换bilibili弹幕时似乎可以做到一些屏蔽选项

首先是关键字屏蔽,这个用正则匹配就好

顶部和底部的弹幕屏蔽可以匹配弹幕样式在转换的时候选择性的无视

深受广大补番爱好者喜爱的注册会员弹幕屏蔽似乎也可以做到,比如下面这个弹幕:

<d p="763.19000244141,1,25,16777215,1447234124,0,D5790686,1338918387">看不懂啊</d>

倒数第二列以D开头的id都是注册会员的,虽然不一定准确,至少我用flash播放的时候他们都被屏蔽了

鄙人的python功底非常不行,所以只能死皮赖脸地来求新功能了T^T

Deal with EBFB(Event Based Framework for Biliscript), or stop throwing error

The EBFB is used with the most recent Bilibili Ranking Week.

An example: http://www.bilibili.com/video/av2002118/

<?xml version="1.0" encoding="UTF-8"?><i><chatserver>chat.bilibili.com</chatserver><chatid>3094218</chatid><mission>0</mission><maxlimit>3000</maxlimit><source>e-r</source><ds>786995184</ds><de>787070480</de><max_count>3000</max_count><d p="9.293,1,25,16777215,1423932631,0,662b3a48,786997626">前5</d>
<d p="11.74,1,25,16777215,1423932652,0,54ad71cd,786997974">- -</d>
<d p="28.045,1,25,16777215,1423932653,0,662b3a48,786998000">不对应该是前3.....</d>
<d p="7.872,1,25,16777215,1423932660,0,68f41271,786998135">前</d>
<d p="23.901,1,25,16777215,1423932661,0,54ad71cd,786998204">第一</d>
<d p="55.461,1,25,16777215,1423932681,0,662b3a48,786998551">少有抢到前3.....</d>
<d p="14.676,1,25,16777215,1423932692,0,dec1a095,786998761">前十- -</d>
<d p="10.606,1,25,16777215,1423932694,0,8cbb3ed3,786998793">前5!!!</d>
<d p="5.833,1,25,16777215,1423932694,0,7d77048a,786998798">好早,明天弹幕肥了再看!</d>
<d p="17.967,1,25,16777215,1423932698,0,7577df6c,786998977">人好少</d>
<d p="0,1,25,16777215,1423932724,0,9026c750,786999399">好前</d>
<d p="16.289,1,25,16777215,1423932742,0,9026c750,787000039">前5</d>
<d p="17.202,1,25,16777215,1423932739,0,130b4443,787000077">前十</d>
<d p="10.927,1,25,16711680,1423932752,0,8be7501e,787000736">有人吗?</d>
<d p="80.396,5,25,3407616,1423932754,0,dec1a095,787000837">我要做十一!!!!谁抢了我十一。。</d>
<d p="6.792,1,25,16777215,1423932756,0,35212836,787000877">前!</d>
<d p="0,1,25,16777215,1423932771,0,6702328d,787001077">前</d>
<d p="30.843,1,25,16711680,1423932768,0,8be7501e,787001107">哎</d>
<d p="11.712,1,25,16777215,1423932783,0,97009d3b,787001315">卧槽好前啊</d>
<d p="4.353,1,25,16777215,1423932787,0,0e227fb2,787001369">啦啦啦</d>
<d p="35.636,1,25,3394815,1423932788,0,35212836,787001387">现在点击显示才3</d>
<d p="5.878,1,25,16777215,1423932788,0,57bac7ee,787001457">前</d>
<d p="17.015,1,25,16777215,1423932794,0,0e227fb2,787001553">前5</d>
<d p="0.45,1,25,16777215,1423932804,0,4a2c8cc7,787001678">早</d>
<d p="30.08,1,25,16777215,1423932810,0,0e227fb2,787001795">人呢</d>
<d p="70.309,1,25,16711680,1423932812,0,8be7501e,787001816">10位小伙伴们</d>
<d p="9.101,1,25,16777215,1423932764,0,ab2fb59d,787002020">前</d>
<d p="7.353,1,25,16777215,1423932852,0,839f86ef,787002567">前十!!</d>
<d p="76.43,1,25,16777215,1423932856,0,0e227fb2,787002667">好孤独</d>
<d p="126.012,1,25,16711680,1423932866,0,8be7501e,787002875">养肥了再看。</d>
<d p="9.282,1,25,16777215,1423932891,0,0c57a9ce,787003326">好早啊</d>
<d p="109.654,1,25,16777215,1423932892,0,9a89d8f0,787003348">卧槽前50啊,第一次啊</d>
<d p="14.435,1,25,16777215,1423932917,0,e5aede16,787003829">前100~~</d>
<d p="176.509,1,25,16711680,1423932915,0,8be7501e,787003839">早上再看</d>
<d p="8.759,1,25,16777215,1423932922,0,4964e1b3,787003948">太前</d>
<d p="8.329,1,25,16777215,1423932921,0,a59a07f0,787003978">早</d>
<d p="7.468,1,25,16777215,1423932920,0,e3ba35b7,787003979">前一百</d>
<d p="127.183,1,25,16777215,1423932939,0,0e227fb2,787004242">另外一个小伙伴你好</d>
<d p="0,4,25,13395609,1423932959,0,9408120c,787004620">第一次这么前!!!</d>
<d p="13.42,1,25,13395609,1423932970,0,9408120c,787004882">早</d>
<d p="3.093,1,25,16777215,1423932980,0,8c483a89,787004981">40!!</d>
<d p="0,1,25,16777215,1423932990,0,9567432e,787005178">前100!!!!!</d>
<d p="6.446,1,25,16777215,1423933019,0,020b8b9a,787005760">站前蹲坑</d>
<d p="0.916,1,25,16777215,1423933019,0,fc1a8e16,787005775">看我刷出了什么!</d>
<d p="1.933,1,25,16777215,1423932957,0,292ba98a,787006063">前一百!</d>
<d p="5.613,1,25,16777215,1423933055,0,9567432e,787006365">占个位,养肥了再看</d>
<d p="0,1,25,16777215,1423933075,0,222a151b,787006803">前》》》》》》》》》》》</d>
<d p="183.207,1,25,16777215,1423933098,0,a59a07f0,787007160">shenmegui</d>
<d p="15.269,1,25,16777215,1423933116,0,887fed8e,787007481">第79</d>
<d p="1.635,1,25,16777215,1423933127,0,a3d9f6e2,787007768">前100~!!</d>
<d p="45.655,1,25,13369395,1423933134,0,052277f2,787007806">前90!!!!</d>
<d p="173.253,1,25,16777215,1423933147,0,e3ba35b7,787008111">upid瞩目</d>
<d p="7.923,1,25,16777215,1423933158,0,252721c9,787008290">前一百</d>
<d p="277.249,1,25,16777215,1423933193,0,a59a07f0,787008882">drrrrrrrrrrrrrr</d>
<d p="112.875,1,25,16777215,1423933232,0,efdbdc7e,787009606">人好少//////////////////</d>
<d p="7.933,1,25,16777215,1423933264,0,f6e24bd6,787010161">qoam60</d>
<d p="7.18,1,25,16777215,1423933232,0,bada12c9,787011074">前</d>
<d p="1.01,1,25,16777215,1423933379,0,01c64df3,787012340">反复看了一下日期……</d>
<d p="20.109,1,25,16711680,1423933400,0,6d8b6877,787012628">早早早</d>
<d p="276.145,1,25,13395609,1423933444,0,9408120c,787013427">drrrrrrr</d>
<d p="275.306,1,25,16777215,1423933448,0,1b035168,787013517">刚刚看完第六集</d>
<d p="449.259,1,25,16777215,1423933579,0,fbbffb17,787015885">大声的告诉我们 你们捕到什么鱼</d>
<d p="14.116,1,25,16777215,1423933637,0,9a8c10ec,787016932">深夜党的胜利</d>
<d p="547.734,1,25,16777215,1423933722,0,d9523de8,787018617">这个好,哈哈</d>
<d p="908.238,1,25,16777215,1423933740,0,e3ba35b7,787018849">……</d>
<d p="0,1,25,16777215,1423933760,0,1bab18c6,787019171">第一次这么早</d>
<d p="13.719,1,25,16777215,1423933793,0,6617be74,787019757">前</d>
<d p="3.623,1,25,16711680,1423933825,0,0274dae0,787020323">看我刷出了什么!!!</d>
<d p="755.902,1,25,3381708,1423933835,0,dec1a095,787020524">这个真的是良心番,超好看。</d>
<d p="0,5,25,16711680,1423933916,0,d39ff4bb,787021935">我去 前100啊</d>
<d p="708.037,4,25,6750105,1423933917,0,dec1a095,787021945">我去,居然还能这么高,群众眼睛瞎了么。</d>
<d p="1217.4,1,25,16777215,1423933978,0,e3ba35b7,787023091">woc112!</d>
<d p="0,1,25,16777215,1423934012,0,15ed24e3,787023695">前</d>
<d p="143.526,1,25,16711680,1423934084,0,0274dae0,787024974">鬼畜区的胜利</d>
<d p="0,1,25,16777215,1423934085,0,2143683d,787024982">我擦,我刷出啥来了!</d>
<d p="960.516,1,25,16777215,1423934019,0,fbbffb17,787025249">这个好</d>
<d p="39.164,1,25,16777215,1423934102,0,59b7bdb7,787025269">前</d>
<d p="167.111,1,25,16711680,1423934107,0,0274dae0,787025366">哇,这个赞</d>
<d p="760.683,1,25,16711680,1423934146,0,6d8b6877,787026045">前面的别走,加我一个</d>
<d p="3.498,1,25,16777215,1423934161,0,016aed09,787026355">前100!!!</d>
<d p="0,1,25,16777215,1423934168,0,7617c20f,787026475">这么早</d>
<d p="820.081,5,25,13395609,1423934172,0,9408120c,787026554">触触你好触触再见(ーー゛)</d>
<d p="0,1,25,16777215,1423934176,0,50861d55,787026585">前300!</d>
<d p="225.883,1,25,16711680,1423934220,0,0274dae0,787027377">绅士的胜利</d>
<d p="0,1,25,16777215,1423934265,0,4d42dd66,787028168">前!</d>
<d p="0.489,1,25,16777215,1423934362,0,4ac15cf3,787029786">看看我刷出了什么!!</d>
<d p="399.629,1,25,16711680,1423934400,0,0274dae0,787030340">丞相的热潮啊</d>
<d p="950.633,1,25,16777215,1423934425,0,93629986,787031687">我就知道233333333</d>
<d p="375.001,1,25,16777215,1423934537,0,016aed09,787032527">!!!</d>
<d p="18.379,1,25,16777215,1423934561,0,6c2ce484,787032976">第90!</d>
<d p="28.969,1,25,16777215,1423934598,0,a95304a4,787033502">居然这么早(#°Д°)</d>
<d p="53.323,1,25,16777215,1423934665,0,ada2d417,787034650">前100,深夜单身汪的胜利</d>
<d p="249.49,1,25,16777215,1423934674,0,6c2ce484,787034762">!!!!!</d>
<d p="682.836,1,25,16711680,1423934721,0,0274dae0,787035479">泰语?</d>
<d p="511.827,1,25,16777215,1423934738,0,6c2ce484,787035723">这个超6</d>
<d p="137.044,4,25,65535,1423934848,0,d402794e,787037414">居然那么前- -吓得我赶紧发条弹幕</d>
<d p="6.707,1,25,16777215,1423934909,0,4c4bd2cd,787038381">前300...</d>
<d p="742.08,1,25,16777215,1423934930,0,016aed09,787038708">茶叔my女神!!!</d>
<d p="2.967,1,25,16777215,1423934992,0,32bf842a,787039724">深夜党的福利</d>
<d p="314.558,4,25,16711680,1423934997,0,49a6310e,787039824">真是绅士的胜利</d>
<d p="25.335,1,25,16777215,1423935001,0,4c4bd2cd,787039869">刚从录的地平线过来,慢了...</d>
<d p="15.767,1,25,16777215,1423934989,0,315127ed,787040518">前前前前前</d>
<d p="901.403,1,25,16777215,1423935070,0,0cabb26b,787040867">280?</d>
<d p="9.187,1,25,16777215,1423935077,0,563b24fa,787041042">居然前100</d>
<d p="899.17,1,25,16777215,1423935087,0,016aed09,787041120">哈哈哈哈哈哈哈哈哈哈哈这个</d>
<d p="0,1,25,16777215,1423935093,0,7a061440,787041204">~~~</d>
<d p="26.717,1,25,16777215,1423935104,0,a19cab48,787041365">又是全线标红的节奏?</d>
<d p="0.933,1,25,3407871,1423935113,0,876edcdd,787041501">前500,话说虐猫子好勤快啊这星期!果然情人节没人么……</d>
<d p="939.952,1,25,16777215,1423935128,0,016aed09,787041722">跪】</d>
<d p="739.144,5,25,16777215,1423935142,0,2143683d,787041949">茶叔!</d>
<d p="108.348,1,25,16777215,1423935138,0,acbd728b,787041962">好靠前</d>
<d p="86.851,1,25,16777215,1423935165,0,2f746e86,787042336">绅士的胜利</d>
<d p="0,1,25,16777215,1423935178,0,67b26e86,787042517">什么情况= =</d>
<d p="1004.84,1,25,16777215,1423935193,0,016aed09,787042737">hhhhhhhh</d>
<d p="760.902,5,25,16777215,1423935209,0,2143683d,787042962">寄生兽是良心番不是很久之前的事了么···</d>
<d p="168.85,1,25,16777215,1423935250,0,a19cab48,787043581">这个好好好!</d>
<d p="146.078,1,25,16777215,1423935262,0,2f746e86,787043812">圣人惠的胜利</d>
<d p="202.242,1,25,16777215,1423935283,0,a19cab48,787044030">  就是不放2333</d>
<d p="4.501,1,25,16777215,1423935231,0,234449ca,787044105">前500!</d>
<d p="0.555,1,25,16777215,1423935310,0,fa311488,787044407">前150!</d>
<d p="187.2,1,25,16777215,1423935316,0,2f746e86,787044542">LL大法好</d>
<d p="6.59,1,25,16777215,1423935344,0,1d5299a7,787044908">好前</d>
<d p="18.105,1,25,16777215,1423935364,0,0be7b71f,787045141">这次好早啊</d>
<d p="42.788,1,25,16777215,1423935399,0,15e99cba,787045707">还能赶上前500不错</d>
<d p="13.097,1,25,16777215,1423935426,0,99deb540,787046035">前250!!!!!!!!</d>
<d p="895.913,5,25,16777215,1423935476,0,2143683d,787046695">我就知道···</d>
<d p="827.592,1,25,16777215,1423935473,0,6c2ce484,787046700">打脸系列= =</d>
<d p="953.549,1,25,16777215,1423935496,0,315127ed,787046935">意料之中</d>
<d p="936.632,1,25,16777215,1423935502,0,2143683d,787047083">毅力帝···</d>
<d p="950.792,1,25,16777215,1423935532,0,2143683d,787047489">逗比战争果然不负众望</d>
<d p="13.512,1,25,16777215,1423935589,0,22d79303,787048254">卧槽前150!</d>
<d p="928.158,1,25,16777215,1423935601,0,6c2ce484,787048434">这个听着都累。。。</d>
<d p="100.488,1,25,16777215,1423935628,0,6a8b4fda,787048861">前100!</d>
<d p="390.636,1,25,16777215,1423935685,0,99deb540,787049633">哈哈哈哈哈哈哈哈</d>
<d p="26.397,1,25,65280,1423935698,0,e4bfb79a,787049776">好前面</d>
<d p="14.392,1,25,16777215,1423935700,0,5083a8b7,787049822">500播放- -</d>
<d p="37.863,1,25,65280,1423935710,0,e4bfb79a,787049970">好早</d>
<d p="11.386,1,25,16777215,1423935715,0,4337fd6b,787050056">这么早~!</d>
<d p="426.512,1,25,16777215,1423935722,0,99deb540,787050142">瑟爹prprprprprpr</d>
<d p="555.866,1,25,16711680,1423935727,0,2f746e86,787050203">FFFFFFFFFFFFFFFFFFFFFFFF</d>
<d p="23.27,1,25,16777215,1423935743,0,4337fd6b,787050432">居然在前600</d>
<d p="754.805,1,25,16777215,1423935753,0,22d79303,787050564">茶叔这投稿时间QVQ</d>
<d p="557.325,1,25,15597585,1423935695,0,7627f03c,787050856">FFF</d>
<d p="955.838,1,25,16777215,1423935816,0,22d79303,787051388">BGM用烂系列</d>
<d p="8.312,1,25,16777215,1423935820,0,f889cdf6,787051443">前500!!!!!!!</d>
<d p="2.867,1,25,16777215,1423935746,0,8bc3cb7e,787051538">卧槽 我就随便看看 第一次这么前!!!</d>
<d p="628.535,1,25,16777215,1423935835,0,2f746e86,787051642">竟然升了</d>
<d p="0,1,25,16777215,1423935850,0,cae35aae,787051891">前600!!发条弹幕明天来看</d>
<d p="823.5,1,25,16777215,1423935777,0,c18176e6,787051958">大触你嚎</d>
<d p="831.6,1,25,16777215,1423935835,0,c18176e6,787052404">!!我喜欢她们唱的歌</d>
<d p="257.281,1,25,16777215,1423935904,0,15e99cba,787052536">哇,岚少久违的上了周刊</d>
<d p="897.533,1,25,16777215,1423935887,0,c18176e6,787053134">雾草_(:_」∠)_</d>
<d p="771.943,1,25,16777215,1423936000,0,2f746e86,787053884">真良心番</d>
<d p="943.6,1,25,16777215,1423935931,0,c18176e6,787054050">请收下我的膝盖</d>
<d p="960.167,1,25,16777215,1423936025,0,c18176e6,787054223">什么鬼</d>
<d p="18.202,1,25,16777215,1423936026,0,bfd97d7f,787054234">前200!</d>
<d p="456.799,1,25,16777215,1423936043,0,6a8b4fda,787054460">沼泽鱼!</d>
<d p="614.878,1,25,16777215,1423936078,0,99deb540,787054977">还不错哎~</d>
<d p="0.747,5,25,6750156,1423936088,0,0308e2c5,787055042">好前_(:з」∠)_</d>
<d p="141.085,1,25,16777215,1423936101,0,853d6fba,787055243">这个质量完全不怎么样啊</d>
<d p="929.681,1,25,16777215,1423936175,0,2f746e86,787056161">丧心病狂</d>
<d p="457.391,1,25,16777215,1423936175,0,da40de60,787056191">鱼~好大的鱼~虎纹鲨鱼</d>
<d p="722.361,1,25,16777215,1423936182,0,80de13ed,787056247">丞相V5</d>
<d p="457.391,1,25,16777215,1423936182,0,da40de60,787056296">鱼~好大的鱼~虎纹鲨鱼~</d>
<d p="936.921,1,25,16777215,1423936191,0,5a11a77b,787056370">wtf...........</d>
<d p="955.893,1,25,16777215,1423936219,0,2f746e86,787056746">不出所料,大触的世界</d>
<d p="2.553,1,25,16777215,1423936227,0,3e858f88,787056863">前1000~</d>
<d p="932.712,1,25,16777215,1423936286,0,99deb540,787057570">哦这歌简直了!</d>
<d p="568.632,1,25,10027008,1423936300,0,da40de60,787057773">FFFF</d>
<d p="96.702,1,25,255,1423936399,0,47119331,787058972">143位小伙伴好</d>
<d p="1041.44,1,25,16777215,1423936404,0,4fae9409,787059036">前一千</d>
<d p="10.65,1,25,16777215,1423936413,0,f681ed7c,787059138">略早= =</d>
<d p="162,1,25,16777215,1423936418,0,cc47272b,787059220">前1000~~</d>
<d p="0.845,1,25,16777215,1423936452,0,2488f768,787059661">前700~</d>
<d p="826.838,1,25,10027008,1423936469,0,da40de60,787059879">圆珠笔比铅笔更容易打细调子 但是比较难把握 </d>
<d p="866.929,1,25,6684927,1423936528,0,da40de60,787060582">速度:又是我的活</d>
<d p="937.979,1,25,255,1423936593,0,47119331,787061408">我整个人都卧槽了......</d>
<d p="925.922,1,25,6684927,1423936610,0,da40de60,787061584">这个真心碉堡 这首歌68分钟 只断了20次</d>
<d p="687.481,1,25,16777215,1423936656,0,27b561f6,787062183">+++++++++++</d>
<d p="834.667,1,25,16777215,1423936652,0,8bc3cb7e,787063015">这个…卧槽…这么久了么</d>
<d p="745.961,5,25,6750156,1423936760,0,0308e2c5,787063321">茶叔!!</d>
<d p="32.838,1,25,13408614,1423936775,0,a4a8026b,787063521">我去第一次进前1000、、、609</d>
<d p="4.094,1,25,16777215,1423936830,0,2da0c482,787064168">钱1000</d>
<d p="826.241,5,25,6750156,1423936846,0,0308e2c5,787064406">这个我好像看过...</d>
<d p="860.325,5,25,6750156,1423936897,0,0308e2c5,787064909">小受喵的猪肉2333333333333</d>
<d p="930.67,5,25,6750156,1423936968,0,0308e2c5,787065652">良心翻唱</d>
<d p="162.333,1,25,16777215,1423936994,0,2516bfea,787065955">这个不错啊</d>
<d p="17.634,1,25,16777215,1423937071,0,dad25416,787066817">av2002118   突破200W了啊</d>
<d p="924.74,1,25,16777215,1423937122,0,74bcdc62,787067392">圆周率终于来啦!</d>
<d p="168.602,1,25,16777215,1423937150,0,fa6823ff,787067638">这个大赞</d>
<d p="1217.36,5,25,6750156,1423937321,0,0308e2c5,787069496">第112←_←简直</d>
<d p="0,8,25,16777215,1423932504,2,bf7f7709,786995184">/**
    EBFB(Event Based Framework for Biliscript) beta
    Author: Xarple
    This work is released to Public Domain, do whatever you want with it.
*/
var buttonInfos=
{   
    'Textjingdian':  { startTime: 50.5, delay: 9, x: 11, y:294, width: 122, height: 23 ,avNum: 'av70467',text:' '},
    'Text30':    { startTime: 76, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1978431',text:' '},
    'Text29':    { startTime: 106, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1966343',text:' '},
    'Text28':    { startTime: 125, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1962377',text:' '},
    'Text27':    { startTime: 155, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1968263',text:' '},
    'Text26':    { startTime: 174, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1976535',text:' '},
    'Text25':    { startTime: 193, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1983098',text:' '},
    'Text24':    { startTime: 212, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1966372',text:' '},
    'Text23':    { startTime: 252, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1975935',text:' '},
    'Text22':    { startTime: 282, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1968804',text:' '},
    'Text21':    { startTime: 301, delay: 16, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1967946',text:' '},
    'Textpickup':    { startTime: 335, delay: 29, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1834666',text:' '},
    'Text20':    { startTime: 368, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1968681',text:' '},
    'Text19':    { startTime: 387, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1972509',text:' '},
    'Text18':    { startTime: 406, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1982422',text:' '},
    'Text17':    { startTime: 425, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1960135',text:' '},
    'Text16':    { startTime: 444, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1972019',text:' '},
    'Text15':    { startTime: 463, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1961937',text:' '},
    'Text14':    { startTime: 482, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1982221',text:' '},
    'Text13':    { startTime: 501, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1971979',text:' '},
    'Text12':    { startTime: 531, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1965400',text:' '},
    'Text11':    { startTime: 550, delay: 16, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1972265',text:' '},
    'Textbangwai':   { startTime: 572.5, delay: 24, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1968461',text:' '},
    'Text10':    { startTime: 601, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1971745',text:' '},
    'Text9':     { startTime: 620, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1958068',text:' '},
    'Text8':     { startTime: 650, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1989613',text:' '},
    'Text7':     { startTime: 669, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1964560',text:' '},
    'Text6':     { startTime: 688, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1966071',text:' '},
    'Text5':     { startTime: 718, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1983560',text:' '},
    'Text4':     { startTime: 737, delay: 17, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1987195',text:' '},
    'Texth5':    { startTime: 812, delay: 14, x: 11, y:294, width: 122, height: 23 ,avNum: 'av949415',text:' '},
    'Texth4':    { startTime: 826, delay: 15, x: 11, y:294, width: 122, height: 23 ,avNum: 'av944472',text:' '},
    'Texth3':    { startTime: 841, delay: 15, x: 11, y:294, width: 122, height: 23 ,avNum: 'av949602',text:' '},
    'Texth2':    { startTime: 856, delay: 15, x: 11, y:294, width: 122, height: 23 ,avNum: 'av954068',text:' '},
    'Texth1':    { startTime: 871, delay: 14, x: 11, y:294, width: 122, height: 23 ,avNum: 'av948808',text:' '},
    'Text3':     { startTime: 892.5, delay: 9, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1982092',text:' '},
    'Text2':     { startTime: 923.5, delay: 9, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1979414',text:' '},
    'Text1':     { startTime: 954, delay: 9, x: 11, y:294, width: 122, height: 23 ,avNum: 'av1973126',text:' '}
};

if($G._("exists"))
{
trace("exists: " + $G._("exists"));
0();//只为Error1009
};

var lastPlayerState = '';
if (!$G._get('exists') &amp;&amp; Player.state == 'playing')
{
    lastPlayerState = Player.state;
    Player.pause();
}

function traceDetailedly(object, objectName)
{
    if (object == null)
    {
        trace('null');
        return;
    }

    function traceStringAtCurrentDepth(string)
    {
        var advance = '';
        for (var i = 0; i &lt; nowDepth; ++i)
            advance += '    ';
        trace(advance + string);
    }

    function traceObject(obj, name)
    { 
        if (obj == null)
        {
            if (name != '')
                traceStringAtCurrentDepth('- ' + name + ': null');
            return;
        }

        if (name != '')
            traceStringAtCurrentDepth('- ' + name + ': ' + obj.toString());
        else
            traceStringAtCurrentDepth('- ' + obj.toString());

        nowDepth++;
        {
            foreach(obj, function (key, val)
            {
                if (val != null)
                    traceObject(val, key);
            });
        }
        nowDepth--;
    }

    var nowDepth = 0;
    traceObject(object, objectName == null ? '' : objectName);
}

function combineObjects(first, second, isOverwriteExisting)
{
    if (!first)
        first = {};
    if (!second)
        return first;
    foreach(second, function (key, val)
    {
        if (isOverwriteExisting == false)
        {
            if (first.hasOwnProperty(key))
                return;
        }

        if (val != null)
            first['' + key] = val;
    });
    return first;
}

function optional(value, defaultValue)
{
    return (value == null) ? defaultValue : value;
}

function setProperties(object, properties, ignores)
{
    if (ignores)
    {
        foreach(properties, function (key, val)
        {
            if (ignores.indexOf(key) == -1 &amp;&amp; object.hasOwnProperty(key))
                object['' + key] = val;
        });
    }
    else
    {
        foreach(properties, function (key, val)
        {
            if (object.hasOwnProperty(key))
                object['' + key] = val;
        });
    }
}

function newRandomizer(initialSeed)
{
    return
    {
        seed : optional(initialSeed, 0),
        rand : function ()
        {
            this.seed = 40692 * (this.seed % 52774) - 3791 * (this.seed / 52774);
            if (this.seed &lt; 0)
                this.seed += 2147483399;
            return this.seed;
        },
        randRange : function (min, max)
        {
            return (this.rand() % (max - min)) + min;
        }
    };
};

function newByteArray()
{
    var byteArray = $G._get('byteArray');
    if (!byteArray)
    {
        if (!Bitmap)
        {
            trace('OPのBitmap库没有被加载!');
            Player.seek(0);
             load("libBitmap" , function(){});

            0();
        }

        var bitmapData = Bitmap.createBitmapData(1, 1);
        byteArray = bitmapData.getPixels(bitmapData.rect);
        byteArray.position = 0;
        byteArray.length = 0;
        $G._set('byteArray', byteArray);
    }
    return clone(byteArray);
}

function newCanvas(param)
{
    var object = $.createCanvas({});

    ScriptManager.popEl(object);
    if (param &amp;&amp; param.parent)
        param.parent.addChild(object);

    object.transform.matrix3D = null;
    if (param)
        setProperties(object, param, ['parent']);
    return object;
}

function newShape(param)
{
    var object = $.createShape({});

    ScriptManager.popEl(object);
    if (param &amp;&amp; param.parent)
        param.parent.addChild(object);

    object.transform.matrix3D = null;
    if (param)
        setProperties(object, param, ['parent']);
    return object;
}

function newButton(param)
{
    var object = $.createButton({ onclick: param.onClick });

    ScriptManager.popEl(object);
    if (param &amp;&amp; param.parent)
        param.parent.addChild(object);

    object.transform.matrix3D = null;
    if (param)
        setProperties(object, param, ['parent']);
    return object;
}

function newBitmap(param)
{
    var object = Bitmap.createBitmap({});

    ScriptManager.popEl(object);
    if (param &amp;&amp; param.parent)
        param.parent.addChild(object);

    object.transform.matrix3D = null;
    if (param)
        setProperties(object, param, ['parent']);
    object.smoothing = true;
    return object;
}

function rectFill(shape, x, y, width, height, color, alpha)
{
    shape.graphics.beginFill(optional(color, 0x9999FF), optional(alpha, 1.0));
    shape.graphics.drawRect(x, y, width, height);
    shape.graphics.endFill();
}

function getDisplayObjectRectangle(object, targetCoordinateSpace)
{
    function getFilteredRectangle(rect, filters)
    {
        if (filters == null)
            return rect;

        var filter = filters[0];
        if (filter == null)
            return rect;

        var bitmapData = Bitmap.createBitmapData(rect.width, rect.height, false);
        var newRect = bitmapData.generateFilterRect(bitmapData.rect, filter);
        bitmapData.dispose();

        newRect.x += rect.x;
        newRect.y += rect.y;

        var left = newRect.left;
        var top = newRect.top;
        var right = newRect.right;
        var bottom = newRect.bottom;

        var length = filters.length;
        for (var i = 1; i &lt; length; i++)
        {
            bitmapData = Bitmap.createBitmapData(newRect.width, newRect.height, false);

            var savedX = newRect.x;
            var savedY = newRect.y;

            newRect = bitmapData.generateFilterRect(bitmapData.rect, filters[i ^ 0]);
            bitmapData.dispose();

            newRect.x += savedX;
            newRect.y += savedY;

            if (newRect.left &lt; left)
                left = newRect.left;
            if (newRect.top &lt; top)
                top = newRect.top;
            if (newRect.right &gt; right)
                right = newRect.right;
            if (newRect.bottom &gt; bottom)
                bottom = newRect.bottom;
        }

        return Bitmap.createRectangle(left, top, right - left, bottom - top);
    }

    var targetCoordinateSpace = optional(targetCoordinateSpace, object);
    var rect = getFilteredRectangle(object.getBounds(targetCoordinateSpace), object.filters);

    if (object.hasOwnProperty('numChildren'))
    {
        var i = object.numChildren;
        while (i-- &gt; 0)
            rect = rect.union(getDisplayObjectRectangle(object.getChildAt(i), targetCoordinateSpace));
    }

    return rect;
}

function convertToBitmap(object, parent)
{
    var rect = getDisplayObjectRectangle(object);
    var bitmapData = Bitmap.createBitmapData(rect.width, rect.height, true, 0);
    var matrix = $.createMatrix();
    matrix.translate(-rect.x, -rect.y);
    bitmapData.draw(object, matrix);

    var result = newBitmap({ bitmapData: bitmapData, parent: parent });
    if (rect.x != 0 || rect.y != 0)
    {
        var canvas = newCanvas({ parent: parent });
        result.x = rect.x;
        result.y = rect.y;
        canvas.addChild(result);
        result = canvas;
    }

    result.transform = object.transform;
    result.blendMode = object.blendMode;
    result.alpha = object.alpha;
    result.filters = object.filters;
    return result;
}

function decodeBase64(str)
{
    if (base64DecodeLookupTable == null)
    {
        base64DecodeLookupTable = [];
        for (var n = 0; n &lt; 256; n++)
            base64DecodeLookupTable[n] = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'.indexOf(String.fromCharCode(n));
    }

    str = (str.split('\t')).join('');
    str = (str.split('\n')).join('');
    var bytes = newByteArray();
    bytes.writeUTFBytes(str);

    var c1, c2, c3, c4;
    var i = 0, out = 0;
    var len = str.length;

    while (i &lt; len)
    {
        c1 = base64DecodeLookupTable[bytes[i++] ^ 0];
        c2 = base64DecodeLookupTable[bytes[i++] ^ 0];
        bytes[out++] = (c1 &lt;&lt; 2) | ((c2 &amp; 0x30) &gt;&gt; 4);
        c3 = base64DecodeLookupTable[bytes[i++] ^ 0];
        if (c3 == -1) break;//was '='
        bytes[out++] = ((c2 &amp; 0x0f) &lt;&lt; 4) | ((c3 &amp; 0x3c) &gt;&gt; 2);
        c4 = base64DecodeLookupTable[bytes[i++] ^ 0];
        if (c4 == -1) break;//was '='
        bytes[out++] = ((c3 &amp; 0x03) &lt;&lt; 6) | c4;
    }
    bytes.length = out;
    bytes.endian = 'littleEndian';
    return bytes;
}

function extractFontData(base64Codes)
{
    var data = decodeBase64(base64Codes);
    data.endian = 'littleEndian';
    data.uncompress();
    data.position = 0;

    var includeKerning = data.readBoolean();
    var includeVertInfo = data.readBoolean();
    var glyph, kerning, size;
    var i, j;

    var fontData = {};
    fontData.size = data.readUnsignedShort();
    fontData.underlinePosition = data.readFloat();
    fontData.underlineThickness = data.readFloat();
    fontData.width = data.readUnsignedShort();
    fontData.height = data.readUnsignedShort();
    fontData.ascender = data.readShort();
    fontData.descender = data.readShort();
    fontData.glyphCount = data.readUnsignedShort();

    for (i = 0; i &lt; fontData.glyphCount; ++i)
    {
        glyph = {};
        glyph.advanceHori = data.readUnsignedShort();
        if (includeVertInfo)
            glyph.advanceVert = data.readUnsignedShort();

        size = data.readUnsignedShort();
        glyph.commands = $.toIntVector([]);
        for (j = 0; j &lt; size; ++j)
            glyph.commands.push(data.readUnsignedByte());

        size = data.readUnsignedShort();
        glyph.paths = $.toNumberVector([]);
        for (j = 0; j &lt; size; ++j)
            glyph.paths.push(data.readShort() / 32.0);

        glyph.kernings = {};
        if (includeKerning)
        {
            size = data.readUnsignedShort();
            for (j = 0; j &lt; size; ++j)
            {
                kerning = {};
                kerning.x = data.readByte();
                if (includeVertInfo)
                    kerning.y = data.readByte();

                glyph.kernings['' + String.fromCharCode(data.readUnsignedShort())] = kerning;
            }
        }

        fontData['' + String.fromCharCode(data.readUnsignedShort())] = glyph;
    }

    return fontData;
}

function extractBatchRendering(base64Codes)
{
    var data = decodeBase64(base64Codes);
    data.endian = 'littleEndian';
    data.uncompress();
    data.position = 0;

    var shape = newShape();
    var shapeGraphics = shape.graphics;

    var lineCapNames = ['none', 'square', 'round'];
    var lineJointNames = ['miter', 'round', 'bevel'];
    var gradientTypeNames = ['linear', 'radial'];
    var gradientSpreadMethodNames = ['pad', 'reflect', 'repeat'];

    var batchType = 0;
    var color = 0;
    var thickness = 0;
    var gradientType = 0;
    var gradientProfileCount = 0;
    var gradientColors = [];
    var gradientAlphas = [];
    var gradientRatios = [];
    var matrix = $.createMatrix();
    var gradientSpreadMethod = 0;
    var focalPointRatio = 0;
    var commands = $.toIntVector([]);
    var paths = $.toNumberVector([]);
    var j = 0;
    var count = 0;

    var batchCount = data.readUnsignedShort();
    for (var i = 0; i &lt; batchCount; ++i)
    {
        // 0: Soild Fill
        // 1: Gradient Fill
        // 2: Soild Line
        // 3: Gradient Line
        batchType = data.readUnsignedByte();

        if (batchType == 0)
        {
            color = data.readUnsignedInt();
            shapeGraphics.beginFill(color &amp; 0xFFFF00, (((color &amp; 0xFF000000) &gt;&gt; 24) &amp; 0xFF) / 255.0);
        }
        else if (batchType == 2 || batchType == 3)
        {
            thickness = data.readUnsignedShort() / 32.0;
            color = data.readUnsignedInt();
            shapeGraphics.lineStyle
            (
                thickness,
                color &amp; 0xFFFF00,
                (((color &amp; 0xFF000000) &gt;&gt; 24) &amp; 0xFF) / 255.0,
                true,
                'none',
                lineCapNames[data.readUnsignedByte() | 0],
                lineJointNames[data.readUnsignedByte() | 0],
                data.readUnsignedShort() / 32.0
            );
        }

        if (batchType == 1 || batchType == 3)
        {
            gradientType = data.readUnsignedByte();

            gradientProfileCount = data.readUnsignedByte();
            gradientColors.length = gradientProfileCount;
            gradientAlphas.length = gradientProfileCount;
            gradientRatios.length = gradientProfileCount;

            for (j = 0; j &lt; gradientProfileCount; ++j)
            {
                color = data.readUnsignedInt();
                gradientColors[j | 0] = color &amp; 0xFFFF00;
                gradientAlphas[j | 0] = (((color &amp; 0xFF000000) &gt;&gt; 24) &amp; 0xFF) / 255.0;
                gradientRatios[j | 0] = data.readUnsignedByte();
            }

            matrix.a = data.readFloat();
            matrix.b = data.readFloat();
            matrix.c = data.readFloat();
            matrix.d = data.readFloat();
            matrix.tx = data.readFloat();
            matrix.ty = data.readFloat();

            gradientSpreadMethod = data.readUnsignedByte();
            focalPointRatio = data.readUnsignedShort() / 32.0;

            if (batchType == 1)
            {
                shapeGraphics.beginGradientFill
                (
                    gradientTypeNames[gradientType | 0],
                    gradientColors,
                    gradientAlphas,
                    gradientRatios,
                    matrix,
                    gradientSpreadMethodNames[gradientSpreadMethod | 0],
                    'rgb',
                    focalPointRatio
                );
            }
            else
            {
                shapeGraphics.lineGradientStyle
                (
                    gradientTypeNames[gradientType | 0],
                    gradientColors,
                    gradientAlphas,
                    gradientRatios,
                    matrix,
                    gradientSpreadMethodNames[gradientSpreadMethod | 0],
                    'rgb',
                    focalPointRatio
                );
            }
        }

        count = data.readUnsignedShort();
        commands.length = count;
        for (j = 0; j &lt; count; ++j)
            commands[j | 0] = data.readUnsignedByte();

        count = data.readUnsignedShort();
        paths.length = count;
        for (j = 0; j &lt; count; ++j)
            paths[j | 0] = data.readShort() / 16.0;

        shapeGraphics.drawPath(commands, paths, data.readUnsignedByte() ? 'evenOdd' : 'nonZero');

        if (batchType == 0 || batchType == 1)
            shapeGraphics.endFill();
    }

    return function (graphics)
    {
        graphics.copyFrom(shapeGraphics);
    };
}

/*
param:
{
    resourceDefine,
    parent || null
}
*/
function performResource(param)
{
    var resourceDefine = param.resourceDefine;
    var resourceParent = param.parent;

    function getResource(path)
    {
        var blocks = path.split('\\');
        var resource = this['' + blocks[0]];

        if (resource == null)
            return null;

        var blockLength = blocks.length;
        for (var i = 1; i &lt; blockLength; ++i)
        {
            var block = blocks[i ^ 0];

            if (resource.children == null)
                return null;

            var numChildren = resource.children.length;
            for (var j = 0; j &lt; numChildren; ++j)
            {
                var child = resource.children[j];
                if (child.name &amp;&amp; child.name == block)
                {
                    resource = resource.children[j];
                    break;
                }
            }

            if (j == numChildren)
                return null;
        }

        param.resourceDefine = resource;
        return performResource.call(this, param);
    }

    if (resourceDefine.referencePath) // jump
    {
        return getResource.call(this, resourceDefine.referencePath);
    }
    else if (resourceDefine.data) // bitmap
    {
        var bitmapData = Bitmap.createBitmapData(resourceDefine.width, resourceDefine.height, true, 0);
        var pixels = decodeBase64(resourceDefine.data);
        pixels.uncompress();
        bitmapData.setPixels(bitmapData.rect, pixels);

        var bitmap = newBitmap({parent: resourceParent, bitmapData: bitmapData});
        setProperties(bitmap, resourceDefine, ['width', 'height', 'data', 'parent']);
        return bitmap;
    }
    else
    {
        var canvas = newCanvas({parent: resourceParent});
        setProperties(canvas, resourceDefine, ['render', 'parent', 'children']);

        if (resourceDefine.render)
            resourceDefine.render.call(this, canvas.graphics);

        if (resourceDefine.children)
        {
            var length = resourceDefine.children.length;
            for (var i = 0; i &lt; length; ++i)
            {
                param.resourceDefine = resourceDefine.children[i^0];
                param.parent = canvas;
                performResource.call(this, param);
            }
        }

        return canvas;
    }
}

/*
param:
{
    text: string,
    textColor || 0xffffff,
    font: FontData,
    userDefinedBeginFill(graphics) || textColor,
    initalValues || null,
    arrangeParam || null,
    isVerticalLayout || false,
}
*/
function newTextBox(param)
{
    var textBox =
    {
        canvas : newCanvas(param.initalValues),
        text : param.text,
        textColor : optional(param.textColor, 0xFFFF33),
        font : param.font,
        userDefinedBeginFill : param.userDefinedBeginFill,

        /*
            arrangeParam || null
        */
        setText : function (text, arrangeParam)
        {
            this.text = text;
            while (this.canvas.numChildren)
                this.canvas.removeChild(this.canvas.getChildAt(0));

            var textLength = text.length;
            for (var i = 0; i &lt; textLength; ++i)
            {
                var charShape = newCanvas({parent: this.canvas});

                var char = text.charAt(i);
                if (char == '\n' || !this.font.hasOwnProperty(char))
                    continue;

                var glyphInfo = this.font['' + char];
                if (glyphInfo.paths)
                {
                    if (this.userDefinedBeginFill)
                        this.userDefinedBeginFill(charShape.graphics);
                    else
                        charShape.graphics.beginFill(this.textColor);

                    charShape.graphics.drawPath(glyphInfo.commands, glyphInfo.paths, 'nonZero');
                    charShape.graphics.endFill();
                }
            }

            this.rearrange(optional(arrangeParam, {}));
        },

        /*
        param:
        {
            letterSpacing:number || 0.0,
            underline:number || false,
            isHorizontallyCentered:bool || false,
            isVerticalCentered:bool || false,
            isVerticalLayout:bool || false,
            'index':
            {
                scale:number || 1.0,
                letterSpacingOffset:number || 0.0,
            }
        }
        */
        rearrange : function (param)
        {
            var letterSpacing = optional(param.letterSpacing, 0.0);
            var isHorizontallyCentered = optional(param.isHorizontallyCentered, false);
            var isVerticalCentered = optional(param.isVerticalCentered, false);
            var isVerticalLayout = optional(param.isVerticalLayout, false);
            var underline = optional(param.underline, false);

            var currentLineSize = isVerticalLayout ? this.font.width : this.font.height;
            var penPos = {x:0, y:0};
            var prevChar = 0;

            var underlineShape = null;
            if (underline)
            {
                if (this.text.length == this.canvas.numChildren)
                    underlineShape = newCanvas({ parent: this.canvas });
                else
                {
                    underlineShape = this.canvas.getChildAt(this.canvas.numChildren - 1);
                    underlineShape.graphics.clear();
                }

                if (this.userDefinedBeginFill)
                    this.userDefinedBeginFill(underlineShape.graphics);
                else
                    underlineShape.graphics.beginFill(this.textColor);
            }
            else if (this.text.length != this.canvas.numChildren)
                this.canvas.removeChildAt(this.canvas.numChildren - 1);

            var charCount = this.text.length;
            for (var i = 0; i &lt; charCount; ++i)
            {
                var char = this.text.charAt(i);
                if (char == '\n')
                {
                    if (underline)
                    {
                        if (isVerticalLayout)
                            underlineShape.graphics.drawRect(penPos.x, 0, Math.ceil(this.font.underlineThickness) * 2, penPos.y);
                        else
                            underlineShape.graphics.drawRect(0, penPos.y + this.font.underlinePosition, penPos.x, Math.ceil(this.font.underlineThickness) * 2);
                    }

                    if (isVerticalLayout)
                    {
                        penPos.x += currentLineSize;
                        penPos.y = 0;
                    }
                    else
                    {
                        penPos.x = 0;
                        penPos.y += currentLineSize;
                    }

                    prevChar = 0;
                    currentLineSize = isVerticalLayout ? this.font.width : this.font.height;
                    continue;
                }

                var charShape = this.canvas.getChildAt(i);
                var glyphInfo = this.font['' + char];

                if (param.hasOwnProperty('' + i))
                {
                    var glyphAdjust = param['' + i];

                    var scale = glyphAdjust.scale ? glyphAdjust.scale : 1.0;
                    charShape.scaleX = scale;
                    charShape.scaleY = scale;

                    var charSize = isVerticalLayout ? charShape.width : charShape.height;
                    if (charSize &gt; currentLineSize)
                        currentLineSize = charSize;

                    if (!isVerticalLayout)
                    {
                        if (prevChar != 0 &amp;&amp; glyphInfo.kernings.hasOwnProperty(prevChar))
                            penPos.x += glyphInfo.kernings[prevChar].x * scale;
                    }

                    charShape.x = penPos.x;
                    charShape.y = penPos.y;

                    if (isVerticalLayout)
                    {
                        penPos.y += glyphInfo.advanceVert * scale + letterSpacing;
                        if (glyphAdjust.letterSpacingOffset)
                            penPos.y += glyphAdjust.letterSpacingOffset;
                    }
                    else
                    {
                        penPos.x += glyphInfo.advanceHori * scale + letterSpacing;
                        if (glyphAdjust.letterSpacingOffset)
                            penPos.x += glyphAdjust.letterSpacingOffset;
                    }
                }
                else
                {
                    charShape.scaleX = 1;
                    charShape.scaleY = 1;

                    if (!isVerticalLayout)
                    {
                        if (prevChar != 0 &amp;&amp; glyphInfo.kernings.hasOwnProperty(prevChar))
                            penPos.x += glyphInfo.kernings[prevChar].x;
                    }

                    charShape.x = penPos.x;
                    charShape.y = penPos.y;

                    if (isVerticalLayout)
                        penPos.y += glyphInfo.advanceVert + letterSpacing;
                    else
                        penPos.x += glyphInfo.advanceHori + letterSpacing;
                }

                prevChar = char;
            }

            if (underline)
            {
                if (isVerticalLayout)
                    underlineShape.graphics.drawRect(penPos.x, 0, Math.ceil(this.font.underlineThickness) * 2, penPos.y);
                else
                    underlineShape.graphics.drawRect(0, penPos.y + this.font.underlinePosition, penPos.x, Math.ceil(this.font.underlineThickness) * 2);
            }

            if (isHorizontallyCentered)
            {
                var halfWidth = (this.canvas.width / this.canvas.scaleX) / 2;

                var charCount = this.canvas.numChildren;
                for (var i = 0; i &lt; charCount; ++i)
                    (this.canvas.getChildAt(i)).x -= halfWidth;
            }

            if (isVerticalCentered)
            {
                var halfHeight = (this.canvas.height / this.canvas.scaleY) / 2;

                var charCount = this.canvas.numChildren;
                for (var i = 0; i &lt; charCount; ++i)
                    (this.canvas.getChildAt(i)).y -= halfHeight;
            }
        }
    };

    textBox.setText(param.text, param.arrangeParam);
    return textBox;
}

/*
param:
{
    startTime: number,
    delay: number,
    onInit() || null,
    onPlay() || null,
    onUpdate(localTime, deltaTime) || null,
    onComplete() || null,
    onPlayerSeeked(localTime) || null,
    onPlayerSizeChanged() || null,
    onPlayerStateChanged(playerState) || null,
}
*/
function newStandardEvent(param)
{
    return
    {
        startTime : param.startTime,
        delay : param.delay,
        displayObjects : [],
        tweens : [],
        subEvents : [],
        parentEvent : null,
        onInit : function ()
        {
            if (param.onInit)
                param.onInit.call(this);
        },
        onPlay : function ()
        {
            var displayObjectsCount = this.displayObjects.length;
            for (var i = 0; i &lt; displayObjectsCount; ++i)
                this.displayObjects[i^0].visible = true;

            if (param.onPlay)
                param.onPlay.call(this);
        },
        onUpdate : function (localTime, deltaTime)
        {
            var tweenCount = this.tweens.length;
            for (var i = 0; i &lt; tweenCount; ++i)
                this.tweens[i^0].update(localTime);

            if (param.onUpdate)
                param.onUpdate.call(this, localTime, deltaTime);

            if (this.subEvents.length)
            {
                var length = this.subEvents.length;
                for (var i = 0; i &lt; length; ++i)
                {
                    var event = this.subEvents[i^0];

                    if (!event.isPlaying &amp;&amp; localTime - event.startTime &gt; 0 &amp;&amp; localTime - event.startTime &lt; event.delay)
                    {
                        event.isPlaying = true;
                        if (event.onPlay)
                            event.onPlay();
                    }
                    else if (event.isPlaying &amp;&amp; localTime - event.startTime &gt;= event.delay)
                    {
                        event.isPlaying = false;
                        if (event.onComplete)
                            event.onComplete();
                    }

                    if (event.isPlaying &amp;&amp; event.onUpdate)
                        event.onUpdate(localTime - event.startTime, deltaTime);
                }
            }
        },
        onComplete : function ()
        {
            var displayObjectsCount = this.displayObjects.length;
            for (var i = 0; i &lt; displayObjectsCount; ++i)
                this.displayObjects[i^0].visible = false;

            if (param.onComplete)
                param.onComplete.call(this);
        },
        onPlayerSeeked : function (localTime)
        {
            var displayObjectsCount = this.displayObjects.length;
            if (localTime &lt;= 0 || localTime &gt;= this.delay)
            {
                for (var i = 0; i &lt; displayObjectsCount; ++i)
                    this.displayObjects[i^0].visible = false;
            }
            else
            {
                for (var i = 0; i &lt; displayObjectsCount; ++i)
                    this.displayObjects[i^0].visible = true;
            }

            if (param.onPlayerSeeked)
                param.onPlayerSeeked.call(this, localTime);

            if (this.subEvents.length)
            {
                var length = this.subEvents.length;
                for (var i = 0; i &lt; length; ++i)
                {
                    var event = this.subEvents[i^0];
                    if (event.onPlayerSeeked)
                        event.onPlayerSeeked(localTime - event.startTime);

                    event.isPlaying = (localTime - event.startTime &gt; 0
                                    &amp;&amp; localTime - event.startTime &lt; event.delay);
                }
            }
        },
        onPlayerSizeChanged : function ()
        {
            if (param.onPlayerSizeChanged)
                param.onPlayerSizeChanged.call(this);

            if (this.subEvents.length)
            {
                var length = this.subEvents.length;
                for (var i = 0; i &lt; length; ++i)
                {
                    if (this.subEvents[i^0].onPlayerSizeChanged)
                        this.subEvents[i^0].onPlayerSizeChanged();
                }
            }
        },
        onPlayerStateChanged : function (playerState)
        {
            if (param.onPlayerStateChanged)
                param.onPlayerStateChanged.call(this, playerState);

            if (this.subEvents.length)
            {
                var length = this.subEvents.length;
                for (var i = 0; i &lt; length; ++i)
                {
                    if (this.subEvents[i^0].onPlayerStateChanged)
                        this.subEvents[i^0].onPlayerStateChanged();
                }
            }
        },
        pushDisplayObject : function (displayObject)
        {
            this.displayObjects.push(displayObject);
            return displayObject;
        },
        pushTween : function (tween)
        {
            this.tweens.push(tween);
            return tween;
        },
        pushSubEvent : function (event)
        {
            event.parentEvent = this;
            event.isPlaying = false;
            if (event.onInit)
                event.onInit();
            if (event.onPlayerSeeked)
                event.onPlayerSeeked(0);
            this.subEvents.push(event);
            return event;
        },
        pushSubEventList : function (eventList)
        {
            var length = eventList.length;
            for (var i = 0; i &lt; length; ++i)
                this.pushSubEvent(eventList[i^0]);
        },
        pushSubEventWithGlobalStartTime : function (event)
        {
            event.parentEvent = this;
            event.isPlaying = false;
            if (event.onInit)
                event.onInit();
            if (event.onPlayerSeeked)
                event.onPlayerSeeked(0);

            var totalTime = this.startTime;
            var e = this;
            while (e.parentEvent != null)
            {
                e = e.parentEvent;
                totalTime += e.startTime;
            }
            event.startTime -= totalTime;

            this.subEvents.push(event);
            return event;
        },
        pushSubEventListWithGlobalStartTime : function (eventList)
        {
            var length = eventList.length;
            for (var i = 0; i &lt; length; ++i)
                this.pushSubEventWithGlobalStartTime(eventList[i^0]);
        },
        computeDuration: function ()
        {
            var duration = this.delay;

            var tweenCount = this.tweens.length;
            for (var i = 0; i &lt; tweenCount; ++i)
            {
                var subDuration = this.tweens[i^0].duration;
                if (subDuration &gt; duration)
                    duration = subDuration;
            }

            var subEventCount = this.subEvents.length;
            for (var i = 0; i &lt; subEventCount; ++i)
            {
                var subDuration = this.subEvents[i^0].computeDuration() + this.subEvents[i^0].startTime;
                if (subDuration &gt; duration)
                    duration = subDuration;
            }

            return duration;
        }
    };
}

/*
param:
{
    startTime: number,
    delay: number,
    framesPerSecond: number,
    onEnterFrame(frame),
    onUpdate(localTime, deltaTime) || null,
    onInit() || null,
    onPlay() || null,
    onComplete() || null,
    onPlayerSeeked(localTime) || null,
    onPlayerSizeChanged() || null,
    onPlayerStateChanged(playerState) || null,
}
*/
function newSequenceEvent(param)
{
    var eventParams =
    {
        startTime : param.startTime,
        delay : param.delay,
        onInit : function ()
        {
            this.framesPerSecond = param.framesPerSecond;
            this.frameDelay = 1.0 / this.framesPerSecond;
            this.frame = 0;
            this.time = 0;

            if (param.onInit)
                param.onInit.call(this);
        },
        onPlay : function ()
        {
            this.frame = 0;
            this.time = 0;

            if (param.onPlay)
                param.onPlay.call(this);
        },
        onUpdate : function (localTime, deltaTime)
        {
            this.time += deltaTime;
            while (this.time &gt;= this.frameDelay)
            {
                this.time -= this.frameDelay;
                this.frame += 1;
                param.onEnterFrame.call(this, this.frame);
            }

            if (param.onUpdate)
                param.onUpdate.call(this, localTime, deltaTime);
        }
    };

    if (param.onComplete)
    {
        eventParams.onComplete = function ()
        {
            param.onComplete.call(this);
        };
    }

    if (param.onPlayerSeeked)
    {
        eventParams.onPlayerSeeked = function (localTime)
        {
            param.onPlayerSeeked.call(this, localTime);
        };
    }

    if (param.onPlayerSizeChanged)
    {
        eventParams.onPlayerSizeChanged = function ()
        {
            param.onPlayerSizeChanged.call(this);
        };
    }

    if (param.onPlayerStateChanged)
    {
        eventParams.onPlayerStateChanged = function (playerState)
        {
            param.onPlayerStateChanged.call(this, playerState);
        };
    }

    return newStandardEvent(eventParams);
}

/*
param:
{
    text: string,
    font: FontData,
    userDefinedBeginFill(graphics) || beginFill(0xffffff),
    lyricInfo,
    canvasParent || $.root,
    onInit() || null,
    onPlay() || null,
    onUpdate(localTime, deltaTime) || null,
    onComplete() || null,
    onPlayerSeeked(localTime) || null,
    onPlayerSizeChanged() || null,
    onPlayerStateChanged(playerState) || null,
}
*/
function newLyricEvent(param)
{
    var eventParams =
    {
        startTime : param.lyricInfo.startTime,
        delay : param.lyricInfo.delay,
        onInit : function ()
        {
            this.textBox = newTextBox(
            {
                text : param.text,
                font : param.font,
                userDefinedBeginFill : param.userDefinedBeginFill,
                canvasParent : param.canvasParent
            });
            this.pushDisplayObject(this.textBox.canvas);

            if (param.onInit)
                param.onInit.call(this);
        },
        onPlay : function ()
        {
            var length = this.onPlayCallbacks.length;
            if (length)
            {
                for (var i = 0; i &lt; length; ++i)
                    (this.onPlayCallbacks[i ^ 0]).call(this);
            }
        },
        onUpdate : function (localTime, deltaTime)
        {
            var length = this.onUpdateCallbacks.length;
            if (length)
            {
                for (var i = 0; i &lt; length; ++i)
                    (this.onUpdateCallbacks[i ^ 0]).call(this, localTime, deltaTime);
            }
        },
        onComplete : function ()
        {
            var length = this.onCompleteCallbacks.length;
            if (length)
            {
                for (var i = 0; i &lt; length; ++i)
                    (this.onCompleteCallbacks[i ^ 0]).call(this);
            }
        },
        onPlayerSeeked : function (localTime)
        {
            var length = this.onPlayerSeekedCallbacks.length;
            if (length)
            {
                for (var i = 0; i &lt; length; ++i)
                    (this.onPlayerSeekedCallbacks[i ^ 0]).call(this, localTime);
            }
        },
        onPlayerSizeChanged : function ()
        {
            var length = this.onPlayerSizeChangedCallbacks.length;
            if (length)
            {
                for (var i = 0; i &lt; length; ++i)
                    (this.onPlayerSizeChangedCallbacks[i ^ 0]).call(this);
            }
        },
        onPlayerStateChanged : function (playerState)
        {
            var length = this.onPlayerStateChangedCallbacks.length;
            if (length)
            {
                for (var i = 0; i &lt; length; ++i)
                    (this.onPlayerStateChangedCallbacks[i ^ 0]).call(this, playerState);
            }
        }
    };

    var lyricEvent = newStandardEvent(eventParams);

    lyricEvent.text = param.text;
    lyricEvent.font = param.font;
    lyricEvent.lyricInfo = param.lyricInfo;

    lyricEvent.onPlayCallbacks = [];
    lyricEvent.onUpdateCallbacks = [];
    lyricEvent.onCompleteCallbacks = [];
    lyricEvent.onPlayerSeekedCallbacks = [];
    lyricEvent.onPlayerSizeChangedCallbacks = [];
    lyricEvent.onPlayerStateChangedCallbacks = [];

    if (param.onPlay)
        lyricEvent.onPlayCallbacks.push(param.onPlay);
    if (param.onUpdate)
        lyricEvent.onUpdateCallbacks.push(param.onUpdate);
    if (param.onComplete)
        lyricEvent.onCompleteCallbacks.push(param.onComplete);
    if (param.onPlayerSeeked)
        lyricEvent.onPlayerSeekedCallbacks.push(param.onPlayerSeeked);
    if (param.onPlayerSizeChanged)
        lyricEvent.onPlayerSizeChangedCallbacks.push(param.onPlayerSizeChanged);
    if (param.onPlayerStateChanged)
        lyricEvent.onPlayerStateChangedCallbacks.push(param.onPlayerStateChanged);

    lyricEvent.applyFilterSeparately = function (filter)
    {
        var length = this.textBox.canvas.numChildren;
        for (var i = 0; i &lt; length; ++i)
        {
            var charShape = this.textBox.canvas.getChildAt(i);
            if (!charShape.filters || charShape.filters.length == 0)
                charShape.filters = [filter];
            else
                charShape.filters.push(filter);
        }
    };

    return lyricEvent;
}

function newEventsDispatcher()
{
    return
    {
        /*
        event:
        {
            startTime: number,
            delay: number,
            onInit() || null,
            onPlay() || null,
            onUpdate(localTime, deltaTime) || null,
            onComplete() || null,
            onPlayerSeeked(localTime) || null,
            onPlayerSizeChanged() || null,
            onPlayerStateChanged(playerState) || null,

            // internal:
            isPlaying: bool,
        }
        */
        run: function(events)
        {
            var eventCount = events.length;
            for (var i = 0; i &lt; eventCount; ++i)
            {
                var event = events[i^0];
                event.isPlaying = false;
                if (event.onInit)
                    event.onInit();
                if (event.onPlayerSeeked)
                    event.onPlayerSeeked(0);
            }

            var lastPlayerState = Player.state;
            var lastWidth = 0;
            var lastHeight = 0;

            var currentSystemTime = getTimer() * 0.001;
            var lastSystemTime = currentSystemTime;

            var currentPlayerTime = Player.time;
            var lastPlayerTime = currentPlayerTime;

            var playerTimeInSeconds = 0;
            var playerBaseTimeInSystem = 0;
            var deltaTime = 0;

            $.root.addEventListener('enterFrame', function()
            {
                currentPlayerTime = Player.time * 0.001;
                currentSystemTime = getTimer() * 0.001;
                deltaTime = currentSystemTime - lastSystemTime;
                lastSystemTime = currentSystemTime;

                if (lastPlayerState != Player.state)
                {
                    lastPlayerState = Player.state;
                    for (var i = 0; i &lt; eventCount; ++i)
                    {
                        if (events[i^0].onPlayerStateChanged)
                            events[i^0].onPlayerStateChanged(lastPlayerState);
                    }
                }

                if (lastPlayerState == 'playing')
                {
                    if (currentPlayerTime != lastPlayerTime)
                    {
                        lastPlayerTime = currentPlayerTime;
                        playerBaseTimeInSystem = currentPlayerTime - currentSystemTime;
                    }
                    else
                        playerTimeInSeconds = playerBaseTimeInSystem + currentSystemTime;

                    if (Math.abs(currentPlayerTime - playerTimeInSeconds) &gt;= 1)
                    {
                        playerTimeInSeconds = currentPlayerTime;

                        for (var i = 0; i &lt; eventCount; ++i)
                        {
                            var event = events[i^0];

                            if (event.onPlayerSeeked)
                                event.onPlayerSeeked(playerTimeInSeconds - event.startTime);

                            event.isPlaying = (playerTimeInSeconds - event.startTime &gt; 0
                                            &amp;&amp; playerTimeInSeconds - event.startTime &lt; event.delay);
                        }
                    }
                }

                if (lastWidth != $.width || lastHeight != $.height)
                {
                    lastWidth = $.width;
                    lastHeight = $.height;

                    for (var i = 0; i &lt; eventCount; ++i)
                    {
                        if (events[i^0].onPlayerSizeChanged)
                            events[i^0].onPlayerSizeChanged();
                    }
                }

                if (lastPlayerState == 'playing')
                {
                    for (var i = 0; i &lt; eventCount; ++i)
                    {
                        var event = events[i^0];

                        if (!event.isPlaying &amp;&amp; playerTimeInSeconds - event.startTime &gt; 0 &amp;&amp; playerTimeInSeconds - event.startTime &lt; event.delay)
                        {
                            event.isPlaying = true;
                            if (event.onPlay)
                                event.onPlay();
                        }
                        else if (event.isPlaying &amp;&amp; playerTimeInSeconds - event.startTime &gt;= event.delay)
                        {
                            event.isPlaying = false;
                            if (event.onComplete)
                                event.onComplete();
                        }

                        if (event.isPlaying &amp;&amp; event.onUpdate)
                            event.onUpdate(playerTimeInSeconds - event.startTime, deltaTime);
                    }
                }
            });
        }
    };
}

function createButton(text)
{
    var buttonInfo = buttonInfos['' + text];
    return newStandardEvent(
    {   
        startTime: buttonInfo.startTime,
        delay : buttonInfo.delay,
        onInit : function ()
        {
            var holder=this.pushDisplayObject( newCanvas({parent: stageCanvas}) );
            var button=newButton({ onClick:function()
                    {
                        Player.jump(buttonInfo.avNum,1,true);
                        Player.pause();
                    },
                    parent: holder
                });
            button.x=buttonInfo.x;
            button.y=buttonInfo.y;
            button.width=buttonInfo.width;
            button.height=buttonInfo.height;
            button.text=buttonInfo.text? buttonInfo.text:text;  
            button.alpha=0.5;                   /** 透明度 */                            
        }
    });
}

if (!$G._get('exists'))
{   
    load("libBitmap", function()
    {

        var eventsDispatcher = newEventsDispatcher();
        eventsDispatcher.run(
        [
            newStandardEvent(
            {
                startTime : 0.0,
                delay : 99999,
                onInit : function ()
                {
                    this.layerRoot =
                    {
                        canvas : newCanvas({ parent: $.root }),
                        width : 640,            /** 视频大小 */
                        height : 384
                    };
                    var stage = this.layerRoot;
                    stageCanvas = stage.canvas;
                    var mask = newCanvas({parent: stageCanvas});
                        rectFill(mask, 0, 0, this.layerRoot.width, this.layerRoot.height);
                    stageCanvas.mask = mask;

                    this.pushSubEventList(
                    [
                        createButton('Textjingdian'),
                        createButton('Text30'),
                        createButton('Text29'),
                        createButton('Text28'),
                        createButton('Text27'),
                        createButton('Text26'),
                        createButton('Text25'),
                        createButton('Text24'),
                        createButton('Text23'),
                        createButton('Text22'),
                        createButton('Text21'),
                        createButton('Textpickup'),
                        createButton('Text20'),
                        createButton('Text19'),
                        createButton('Text18'),
                        createButton('Text17'),
                        createButton('Text16'),
                        createButton('Text15'),
                        createButton('Text14'),
                        createButton('Text13'),
                        createButton('Text12'),
                        createButton('Text11'),
                        createButton('Textbangwai'),
                        createButton('Text10'),
                        createButton('Text9'),
                        createButton('Text8'),
                        createButton('Text7'),
                        createButton('Text6'),
                        createButton('Text5'),
                        createButton('Text4'),
                        createButton('Texth5'),
                        createButton('Texth4'),
                        createButton('Texth3'),
                        createButton('Texth2'),
                        createButton('Texth1'),
                        createButton('Text3'),
                        createButton('Text2'),
                        createButton('Text1'),
                    ]);
                },
                onPlayerSizeChanged : function ()
                {
                    var scale = Math.min($.width / this.layerRoot.width, $.height / this.layerRoot.height);
                    var x = ($.width - (this.layerRoot.width * scale)) / 2;
                    var y = ($.height - (this.layerRoot.height * scale)) / 2;

                    this.layerRoot.canvas.scaleX = scale;
                    this.layerRoot.canvas.scaleY = scale;
                    this.layerRoot.canvas.x = x;
                    this.layerRoot.canvas.y = y;
                }
            }),
        ]);
    $G._set('exists', true);

        if (lastPlayerState == 'playing')
        {
            Player.play();
            ($G._("loading")).change(60);
        };
    });
}</d>
</i>

有輸出卻沒有字幕

小弟用NicoFox下載彈幕,用danmaku2ass轉換後只有metadata等卻沒有字幕

NicoFox下載的xml:
http://www.mediafire.com/download/xfq1w151qc4o4wd/sm23726371_-_人参で顔が変わっちゃったハムスター.xml

記錄:
$ ./danmaku2ass.py -o sm2372637171\ -\ 人参で顔が変わっちゃったハムスター.ass -s 1024x600 sm2372637171\ -\ 人参で顔が変わっちゃったハムスター.xml
$ less sm2372637171\ -\ 人参で顔が変わっちゃったハムスター.ass
[Script Info]
; Script generated by Danmaku2ASS
; https://github.com/m13253/danmaku2ass
Script Updated By: Danmaku2ASS (https://github.com/m13253/danmaku2ass)
ScriptType: v4.00+
PlayResX: 1024
PlayResY: 600
Aspect Ratio: 1024:600
Collisions: Normal
WrapStyle: 2
ScaledBorderAndShadow: yes
YCbCr Matrix: TV.601

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, It
alic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment,
MarginL, MarginR, MarginV, Encoding
Style: Danmaku2ASS_64f7, Helvetica, 25, &H00FFFFFF, &H00FFFFFF, &H00000000, &H00000000, 0, 0, 0, 0, 1
00, 100, 0.00, 0.00, 1, 1, 0, 7, 0, 0, 0, 0

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text

[Niconico] I want to add a feature which allows users to specify the fontsize coefficient

I find the moving comment is too small, but when I increase the fontsize, the subtitle get out of screen.
Therefore, I want to add a feature which allows users to specify the fontsize coefficient since everyone have different taste.

I have implenmented it in my fork and I want to know how you guys think about it.
I will create a pull request after the NicoFox pull request is done.
Thanks!

无法判断带有BOM的弹幕文件的站点来源信息

信息:
F:\Desktop\danmaku2ass-master>python danmaku2ass.py -o 1.ass -s 640x480 -fn "MS
PGothic" -fs 48 -a 0.8 -dm 5 -ds 5 1.xml
Traceback (most recent call last):
File "danmaku2ass.py", line 845, in
main()
File "danmaku2ass.py", line 841, in main
Danmaku2ASS(args.file, args.output, width, height, args.protect, args.font,
args.fontsize, args.alpha, args.duration_marquee, args.duration_still, args.redu
ce)
File "danmaku2ass.py", line 779, in Danmaku2ASS
comments = ReadComments(input_files, font_size)
File "danmaku2ass.py", line 806, in ReadComments
raise ValueError(_('Unknown comment file format: %s') % i)
ValueError: Unknown comment file format: 1.xml

F:\Desktop\danmaku2ass-master>pause
请按任意键继续. . .

然后发现不支持utf8有BOM格式。。

转换比较大的弹幕文件时出错?

刚才把多个弹幕文件合并成了一个大约包含13万条弹幕的文件,转换时报错:
F:\哔哩哔哩视频和弹幕备份\danmaku2ass-master>python danmaku2ass.py -o 2.ass -s 640x480 -fn "MS PGothic" -fs 20 -a 0.8 -dm 5 -ds 5 all.xml Traceback (most recent call last): File "danmaku2ass.py", line 859, in <module> main() File "danmaku2ass.py", line 855, in main Danmaku2ASS(args.file, args.output, width, height, args.protect, args.font, args.fontsize, args.alpha, args.duration_marquee, args.duration_still, args.reduce) File "danmaku2ass.py", line 779, in Danmaku2ASS comments = ReadComments(input_files, font_size) File "danmaku2ass.py", line 807, in ReadComments comments.extend(CommentProcessor(FilterBadChars(f), font_size)) File "danmaku2ass.py", line 173, in ReadCommentsBilibili dom = xml.dom.minidom.parse(f) File "C:\Users\chenxuuu\AppData\Local\Programs\Python\Python35-32\lib\xml\dom\minidom.py", line 1958, in parse return expatbuilder.parse(file) File "C:\Users\chenxuuu\AppData\Local\Programs\Python\Python35-32\lib\xml\dom\expatbuilder.py", line 913, in parse result = builder.parseFile(file) File "C:\Users\chenxuuu\AppData\Local\Programs\Python\Python35-32\lib\xml\dom\expatbuilder.py", line 207, in parseFile parser.Parse(buffer, 0) xml.parsers.expat.ExpatError: XML or text declaration not at start of entity: line 43690, column 0

弹幕文件:http://pan.baidu.com/s/1o8zWf4A

mac下make install报错

我的mac版本:macOs High Sierra 10.13.6
make install报错如下:
mkdir -p "/usr/local/share/danmaku2ass"
install -Dm0755 danmaku2ass.py "/usr/local/share/danmaku2ass/danmaku2ass.py"
install: illegal option -- D
usage: install [-bCcpSsv] [-B suffix] [-f flags] [-g group] [-m mode]
[-o owner] file1 file2
install [-bCcpSsv] [-B suffix] [-f flags] [-g group] [-m mode]
[-o owner] file1 ... fileN directory
install -d [-v] [-g group] [-m mode] [-o owner] directory ...
make: *** [install] Error 64
请问该怎么解决,望回复

Problems with converting Nico files (to ass)

  1. The difference in vertical values of the move function in a ass file is too large(second and fourth parameters)
    like this {\move(1920, 144, -720, 144)} next comment-> {\move(1920, 288, -672, 288)}
    There's a huge gap between the two comments
    changing the screen size setting doesn't change the large gap
    (because of this problem, I touched all the setting prices, but I failed to narrow the gap)
    there is too much blank vertical space between the on-screen comments

  2. Comments are not used even though there is a longitudinal space left.
    If it's likely to overlap, need to utilize longitudinal space, but it's not
    so there are too many overlapping situations(in case of long comment)
    It's not really like this in Nico-dong

I ask you to solve this problem

新版土豆弹幕

看到代码里有 tudou 弹幕的解析部分,但似乎与我下载回来的弹幕不兼容。


测试视频:http://www.tudou.com/albumplay/92J2xqpSxWY.html

弹幕地址:http://service.danmu.tudou.com/list?mat=0&mcount=1&ct=1001&uid=0&iid=132648348
其中 mcount, mat 似乎与分页有关,具体意义不明。
mat 表示时间起点(分钟),mcount 表示分钟数,如 mat=1&mcount=5 为时间 1 ~ 6 min 的弹幕。


格式

截取了一部分。

{
    "result": [
        {
            "aid": 116018,
            "content": "土豆,我这一辈子都不会卖屏幕上出现的商品",
            "createtime": 1451060829000,
            "id": 61955942,
            "iid": 132648348,
            "ipaddr": 30254764,
            "level": 1,
            "lid": 0,
            "mat": 1,
            "ouid": 102599789,
            "playat": 114000,
            "propertis": "{\"color\":3646691,\"pos\":4,\"effect\":0,\"size\":1}",
            "status": 99,
            "type": 1,
            "uid": 97773723,
            "ver": 1
        },
        {
            "aid": 116018,
            "content": "假发:嘀嘀嘀,待机中",
            "createtime": 1451057680000,
            "id": 61954013,
            "iid": 132648348,
            "ipaddr": 2002405118,
            "level": 1,
            "lid": 0,
            "mat": 1,
            "ouid": 102599789,
            "playat": 118000,
            "propertis": "",
            "status": 99,
            "type": 1,
            "uid": 469328303,
            "ver": 1
        }
    ],
    "count": 165,
    "filtered": false
}

playat 是出现的时间毫秒数。
弹幕的样式都移到了 propertis 里,与原来的样式属性意义相同。


我的解析实现:Goshin@f530b37?diff=unified

Lifetime of different type of danmaku should be different

When using danmaku2ass, I found out that the lifetime of bottom/top centered comment is the same as that of regular moving ones, which may not be a good idea.

We need lifetime longer than 10 seconds for moving danmaku to be easily read, but this would be too long for centered comments as they will cover up the video for too long. Actually, the life time of bottom/top centered comments varies, depending on their length, the size of the screen, etc. Maybe you can reference a project on Github named ``gdanmaku'' for some ideas of calculating the lifetime.

Add auto dectection of resolution using mplayer2

What do you think about adding auto detection of resolution?

Do you think using mplayer2 for this purpose is suitable?
I choose mplayer2 because I presume that many GNU/Linux distros will have it installed
but I haven't think about Windows/Mac users yet. Is this script supposed to be cross-platform?

I will dealt with it later if you think this addition is ok.

alexvong243f@26fa477

Btw, have you watched the latest anime by SHAFT? I love the op :P

danmaku2ass.py is needed by BiliDan

For two packages: danmaku2ass, and BiliDan to work properly, we either need:

  1. To link danmaku2ass.py with danmaku2ass;
  2. Install danmaku2ass without renaming it to danmaku2ass.

我使用C++重构了这个项目的核心部分

我使用C++重构了这个项目的核心部分,极大加速了大弹幕文件的转换,并使得代码结构更利于维护,👉项目地址。成熟后预计为我另一个项目bilix提供支持。

因为重构的调整较大,没有采用fork的方式,但标明了您的贡献,如果您对此有疑问请联系我。

py2 分支好像不支持最新的acfun弹幕

acfun弹幕示例:

{
    "onlineCount":1,
    "addCount":8,
    "added":[
        {
            "color":16740362,
            "rank":0,
            "userId":13587975,
            "createTime":1587916624952,
            "danmakuId":166416891,
            "body":"好先进的概念",
            "roleId":0,
            "mode":1,
            "position":128064,
            "size":25
        },
        {
            "color":16740362,
            "rank":5,
            "userId":23400562,
            "createTime":1588765316290,
            "danmakuId":170107303,
            "body":"来了",
            "roleId":0,
            "mode":4,
            "position":3579,
            "size":25
        },
        {
            "color":16777215,
            "rank":5,
            "userId":33007032,
            "createTime":1588167587631,
            "danmakuId":167778244,
            "body":"有p1就不错了,知足吧",
            "roleId":0,
            "mode":1,
            "position":270635,
            "size":25
        },
        {
            "color":16777215,
            "rank":0,
            "userId":266066,
            "createTime":1585824686962,
            "danmakuId":150199607,
            "body":"卧槽",
            "roleId":0,
            "mode":1,
            "position":200446,
            "size":25
        },
        {
            "color":16777215,
            "rank":5,
            "userId":30076018,
            "createTime":1585403643995,
            "danmakuId":148471996,
            "body":"想玩,只能康康了",
            "roleId":0,
            "mode":1,
            "position":13961,
            "size":25
        },
        {
            "color":16777215,
            "rank":0,
            "userId":27564872,
            "createTime":1585116632347,
            "danmakuId":144802425,
            "body":"来了来了",
            "roleId":0,
            "mode":1,
            "position":10180,
            "size":25
        },
        {
            "color":16777215,
            "rank":0,
            "userId":31782103,
            "createTime":1586877612614,
            "danmakuId":156870711,
            "body":"手里的p1瞬间就不香了",
            "roleId":0,
            "mode":1,
            "position":242939,
            "size":25
        },
        {
            "color":16777215,
            "rank":5,
            "userId":29300286,
            "createTime":1589811740177,
            "danmakuId":173357818,
            "body":"这声音",
            "roleId":0,
            "mode":1,
            "position":183943,
            "size":25
        }
    ],
    "host-name":"hb2-acfun-kcs191.aliyun",
    "totalCount":8,
    "result":0,
    "deleteCount":0,
    "deleted":[

    ],
    "fetchTime":1592322615593,
    "interval":10,
    "lastFetchTime":0,
    "totalCountShow":"8",
    "isChange":true
}

Current comment file format probe algorithm is not robust

Currently, Danmaku2ASS probes comment file format by prefetching the first bytes.

However, this may fail because there may be some <!-- XML comments --> (#8) or the JSON object may be reordered.

I am considering a robust algorithm which look into the XML or JSON format to figure out which file format is used.

We need a GUI

Danmaku2ASS GUI mockup

wxWidgets 3 / PyQt 5 / PyGObject 3 are preferred.

报bug,转化出来的ASS文件没有弹幕

环境版本

MacOS 10.14.2 (18C54)
Python 3.7.1

调用命令

#!/bin/sh
block_list='(房价|我|别撸了|生日|生快|版权|盗版|屏蔽|地域|弹幕|举报|低龄|脑子|吃相|字幕|跳过|跳不了|什么玩意|乱七八糟|快进|什么鬼|水了|跳了|无力吐槽|食用|快乐|百度)'

for file in "$@"
do
  echo $file
  echo ${file%%.xml}.ass
  danmaku2ass -s 1920x1080 -a 0.80 -fn 苹方 -fs 36 -dm 15 -ds 10 -fl "$block_list" -o "${file%%.xml}.ass" "$file"
done

XML文件

<?xml version="1.0" encoding="UTF-8"?>
<i>
    <chatserver>chat.bilibili.com</chatserver>
    <chatid>65231499</chatid>
    <mission>0</mission>
    <maxlimit>1000</maxlimit>
    <state>0</state>
    <real_name>0</real_name>
    <source>k-v</source>
    <d p="163.82700,1,25,16777215,1544241828,0,13fd4b8a,8965143281008640">承包超可爱的桃桃</d>
    <d p="20.59700,1,25,16777215,1544242873,0,7f6e1e,8965691235893248">可爱</d>
    <d p="203.80000,1,25,16777215,1544243903,0,9239bf53,8966231173890048">可爱可爱</d>
    <d p="20.33900,1,25,16777215,1544259304,0,4e89dc88,8974305555644416">可爱可爱(´▽`)ノ♪</d>
    <d p="20.99600,1,25,16777215,1544259361,0,11de8a8f,8974335734185984">发个弹幕</d>
    <d p="16.73800,1,25,16777215,1544267187,0,6c6e8259,8978438823084032">你太可爱了吧</d>
    <d p="14.30100,1,25,16777215,1544268022,0,bad08559,8978876191473664">白丝赛高</d>
    <d p="11.16600,1,25,16777215,1544271986,0,1600e0bb,8980954457047040">可爱</d>
    <d p="17.57800,1,25,16777215,1544277093,0,53bf5727,8983632374923264">弹幕呢?</d>
    <d p="95.68700,1,25,16777215,1544281710,0,ce63e8ce,8986052690706432">阔爱</d>
    <d p="164.24800,1,25,16777215,1544305485,0,eb1985ed,8998517892710400">好可爱,喜欢这段</d>
    <d p="28.47600,1,25,16777215,1544353416,0,1bd3daea,9023647588024320">丝袜好评</d>
    <d p="122.07300,1,25,16777215,1544357146,0,1fe363b2,9025602867167232">好怀念这支舞,以前最喜欢的一支舞</d>
    <d p="11.86400,1,25,16777215,1544399513,0,c84f420d,9047815416709120">好可爱啊</d>
    <d p="73.77000,1,25,16777215,1544402226,0,f035b254,9049237865627648">弹幕呐</d>
    <d p="27.16200,1,25,16777215,1544403450,0,ddaef6b8,9049879840030722">兄弟们安排一下 1分钟我要这个up主所有资料</d>
    <d p="92.27200,1,25,16777215,1544405078,0,e960484,9050733030670336">。</d>
    <d p="28.21000,1,25,16777215,1544409337,0,2aae21ac,9052966348652544">毫无抵抗力</d>
    <d p="101.78800,1,25,16777215,1544432273,0,edccd9a9,9064991025004544">。</d>
    <d p="42.80000,1,25,16777215,1544436699,0,103f4b08,9067311499051008">还不错</d>
    <d p="62.02000,1,25,16777215,1544436736,0,103f4b08,9067331150938112">细节啊</d>
    <d p="105.95400,1,25,16777215,1544440904,0,b7d4347b,9069516379652096">熊猫之后这里看到桃子~哈哈</d>
    <d p="39.29700,1,25,16777215,1544448490,0,8d972b77,9073493390393344">怀念啊!当年被逼学这个</d>
    <d p="17.82200,1,25,16777215,1544452260,0,fe7c40c6,9075470031126528">太可爱了!</d>
    <d p="70.80500,1,25,16777215,1544499248,0,bcb7f904,9100105286156288">哈哈哈我还记得当时高一元旦晚会跳的这个,我现在大学了</d>
    <d p="25.51500,1,25,16777215,1544707839,0,e7304f82,9209467081064448">可耐就是萌</d>
    <d p="22.23800,1,25,16777215,1544853315,0,c4f5fe99,9285738553147392">承包</d>
    <d p="3.14400,4,18,16755202,1544286033,1,8ac82061,8988319131631618">快乐合成器 送达到你的内心深处</d>
    <d p="6.96600,4,18,16755202,1544286049,1,8ac82061,8988327805976576">与传递给你的旋律 一起演奏</d>
    <d p="29.49300,4,18,16755202,1544286095,1,8ac82061,8988351766462464">现在只是变成了好笑的事情而已</d>
    <d p="33.32200,4,18,16755202,1544286108,1,8ac82061,8988358746308608">所有看到的事物都熠熠生辉</d>
    <d p="37.11700,4,18,16755202,1544286122,1,8ac82061,8988366006648834">那些日子我们在璀璨的微笑呢</d>
    <d p="26.00000,4,18,16755202,1544286079,1,8ac82061,8988343299211264">短暂飘散的淡淡单相思之情</d>
    <d p="44.80300,4,18,16755202,1544286161,1,8ac82061,8988386527281152">“变成大人吧?” 不成为大人也可以的哦</d>
    <d p="48.59800,4,18,16755202,1544286178,1,8ac82061,8988395408719872">不知道的事情很多 说不出口的不知道</d>
    <d p="52.57600,4,18,16755202,1544286194,1,8ac82061,8988403450249216">“真是非常相似呢” 对不起我说谎了</d>
    <d p="41.12600,4,18,16755202,1544286140,1,8ac82061,8988375439638528">只有忍耐的事情 是必须记住的吗?</d>
    <d p="56.16600,4,18,16755202,1544286440,1,8ac82061,8988532665745408">快乐合成器 送达到你的内心深处</d>
    <d p="59.62000,4,18,16755202,1544286457,1,8ac82061,8988541845504000">与传递给你的旋律 一起演奏</d>
    <d p="67.19400,4,18,16755202,1544286484,1,8ac82061,8988555742806016">全部都用这个声音消去</d>
    <d p="71.43300,4,18,16755202,1544286499,1,8ac82061,8988563832045568">什么优点都没有 对于我来说唯一的一个</d>
    <d p="75.26200,4,18,16755202,1544286511,1,8ac82061,8988570081034240">只有一点 能做出的事情</d>
    <d p="78.76300,4,18,16755202,1544286522,1,8ac82061,8988575822512130">毫无装饰的语言 让你心情澎湃</d>
    <d p="63.60300,4,18,16755202,1544286471,1,8ac82061,8988548768727040">无聊的“方针”和讨厌的事情</d>
    <d p="90.02300,4,18,16755202,1544286553,1,8ac82061,8988591805956096">喜欢的事情并不会无聊</d>
    <d p="93.73900,4,18,16755202,1544286564,1,8ac82061,8988597788606464">并不需要 “牵强附会”之类的感情?</d>
    <d p="97.56900,4,18,16755202,1544286576,1,8ac82061,8988603831025664">因为身处这个时代 如果放弃的话就只是到这个地步</d>
    <d p="82.98100,4,18,16755202,1544286537,1,8ac82061,8988583375929346">用电子音传递给你哦</d>
    <d p="105.37300,4,18,16755202,1544286685,1,8ac82061,8988660983136256">“抱歉呢 这么晚才到 你正在睡着吧?”</d>
    <d p="101.64300,4,18,16755202,1544286658,1,8ac82061,8988646792757248">不向前迈出一步的话 什么都开始不了</d>
    <d p="109.02000,4,18,16755202,1544286699,1,8ac82061,8988668434317312">“惊到了 我也正在想着你”</d>
    <d p="112.50400,4,18,16755202,1544286712,1,8ac82061,8988675194486784">心中内侧发烫般</d>
    <d p="124.02800,4,18,16755202,1544286745,1,8ac82061,8988692751843328">用拭去泪水的旋律 弹奏的哦</d>
    <d p="116.30000,4,18,16755202,1544286723,1,8ac82061,8988681202827264">被幸福的声音 吸引的2人</d>
    <d p="127.85600,4,18,16755202,1544286758,1,8ac82061,8988699404533760">不逞强也可以的吗? 当然可以</d>
    <d p="131.39100,4,18,16755202,1544286780,1,8ac82061,8988711141769216">只要对自己坦诚就好</d>
    <d p="120.39600,4,18,16755202,1544286735,1,8ac82061,8988687115223040">快乐合唱器 看吧 逐渐变快乐了</d>
    <d p="135.40700,4,18,16755202,1544286914,1,8ac82061,8988781387972608">什么优点都没有 对于我来说唯一的一个</d>
    <d p="143.19400,4,18,16755202,1544286944,1,8ac82061,8988797179002880">稍微有点害羞 单纯的心情</d>
    <d p="147.04400,4,18,16755202,1544286957,1,8ac82061,8988803600482304">用电子音传递给你哦</d>
    <d p="139.72300,4,18,16755202,1544286934,1,8ac82061,8988791508828160">只有一点 能做出的事情</d>
    <d p="175.08000,4,18,16755202,1544287020,1,8ac82061,8988836561944576">无聊的“方针”和讨厌的事情</d>
    <d p="167.56400,4,18,16755202,1544286986,1,8ac82061,8988819146145792">快乐合成器 送达到你的内心深处</d>
    <d p="178.82600,4,18,16755202,1544287030,1,8ac82061,8988842242605056">全部都用这个声音消去</d>
    <d p="171.26100,4,18,16755202,1544287000,1,8ac82061,8988826153254912">与传递给你的旋律 一起演奏</d>
    <d p="182.80300,4,18,16755202,1544287498,1,8ac82061,8989087404392448">什么优点都没有 对于我来说唯一的一个</d>
    <d p="190.90600,4,18,16755202,1544287534,1,8ac82061,8989106393579520">毫无装饰的语言 让你心情澎湃</d>
    <d p="194.29900,4,18,16755202,1544287545,1,8ac82061,8989112185913344">用电子音传递给你哦</d>
    <d p="197.69100,4,18,16755202,1544287569,1,8ac82061,8989124678123520">快乐合唱器 看吧 逐渐变快乐了</d>
    <d p="186.51700,4,18,16755202,1544287513,1,8ac82061,8989095102513154">只有一点 能做出的事情</d>
    <d p="205.41500,4,18,16755202,1544287595,1,8ac82061,8989138338447360">不逞强也可以的吗? 当然可以</d>
    <d p="209.05000,4,18,16755202,1544287607,1,8ac82061,8989144432246784">只要对自己坦诚就好</d>
    <d p="201.59900,4,18,16755202,1544287582,1,8ac82061,8989131530567680">用拭去泪水的旋律 弹奏的哦</d>
    <d p="217.13700,4,18,16755202,1544287988,1,8ac82061,8989344543539200">只有一点 能做出的事情</d>
    <d p="220.90900,4,18,16755202,1544288001,1,8ac82061,8989350990708736">稍微有点害羞 单纯的心情</d>
    <d p="224.74000,4,18,16755202,1544288011,1,8ac82061,8989356573327360">用电子音传递给你哦</d>
    <d p="213.11100,4,18,16755202,1544287975,1,8ac82061,8989337615073280">什么优点都没有 对于我来说唯一的一个</d>
</i>

输出的ASS文件是

[Script Info]
; Script generated by Danmaku2ASS
; https://github.com/m13253/danmaku2ass
Script Updated By: Danmaku2ASS (https://github.com/m13253/danmaku2ass)
ScriptType: v4.00+
PlayResX: 1920
PlayResY: 1080
Aspect Ratio: 1920:1080
Collisions: Normal
WrapStyle: 2
ScaledBorderAndShadow: yes
YCbCr Matrix: TV.601

[V4+ Styles]
Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
Style: Danmaku2ASS_6654, 苹方, 36, &H33FFFFFF, &H33FFFFFF, &H33000000, &H33000000, 0, 0, 0, 0, 100, 100, 0.00, 0.00, 1, 1, 0, 7, 0, 0, 0, 0

[Events]
Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text

bilibili PC端的xml格式弹幕文件更新成2.0了,貌似转不了ass

就是从Microsoft Store里面下载的哔哩哔哩动画,缓存的弹幕文件片段如下:
<?xml version="2.0" encoding="UTF-8"?><i><oid>200140199</oid><d p="34656419668557827,0,61486,1,25,16777215,1593244049,0,3dbb2ac3">握草</d><d p="34754197277638663,0,59166,1,25,16777215,1593430545,0,9ee00804">哇!</d><d p="34756064507854853,0,85100,1,25,16777215,1593434107,0,f2d4d56d">花擦</d><d p="34756661216280581,0,68609,1,25,16777215,1593435245,0,da7c12b1">密恐噩梦</d><d p="34758278075908099,0,19419,1,25,16777215,1593438329,0,c01dcfe2">首页通知书</d><d p="34776859265728517,0,75319,1,25,16777215,1593473770,0,1b180964">在外扩过程中异丙醇挥发,溶剂只剩下水形成的吗</d><d p="34778872253251589,0,68856,1,25,16777215,1593477609,0,af464b21">哇啊</d><d p="34785012342063107,0,14962,1,25,16777215,1593489320,0,d4727c54">有人懂这个吗</d><d p="34785323440930819,0,64239,1,25,16777215,1593489914,0,607a790d">好看</d><d p="34785664146866183,0,68201,1,25,16777215,1593490563,0,d73392f">哇</d><d p="34785966402568199,0,31539,1,25,16777215,1593491140,0,933b2b85">酒精吧?</d><d p="34786043575664643,0,48120,1,25,16777215,1593491287,0,2eadee2e">中文太小了</d><d p="34786153443360771,0,35665,1,25,41194,1593491497,0,dd1ba50f">美国的外用&quot;酒精&quot;一般是异丙醇</d><d p="34786496944799747,0,66534,1,25,16777215,1593492152,0,308a8108">好美</d><d p="34786970322862087,0,143059,1,25,16777215,1593493055,0,481c1036">我明白了</d><d p="34787654679134211,0,152807,1,25,16777215,1593494360,0,520477ba">虽然不是很懂,但是无妨</d><d p="34787750865534981,0,74830,1,25,16777215,1593494544,0,90ed6922">!好看</d><d p="34788354776104967,0,27687,1,25,16777215,1593495695,0,eb298367">首页通知书</d><d p="34788375536861191,0,67266,1,25,16777215,1593495735,0,eb298367">有意思</d><d p="34788394940760071,0,104289,1,25,16777215,1593495772,0,eb298367">颜色很好看唉</d> ......

会报错:“ValueError: Failed to detect comment file format: ......”
希望作者能抽出时间改进一下,感谢

Crash when loading translation files (Py2 version)

When convert xml danmaku to ass via danmaku2ass (py2 version) on Debian GNU/Linux Stretch, it reports:

Traceback (most recent call last):
File "../danmaku2ass2.py", line 40, in
gettext.install('danmaku2ass', os.path.join(os.path.dirname(os.path.abspath(os.path.realpath(sys.argv[0] or 'locale'))), 'locale'))
File "/usr/lib/python2.7/posixpath.py", line 73, in join
path += '/' + b
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe8 in position 11: ordinal not in range(128)

danmaku2ass (py3 version) works with no problem.

报Bug,转换后字幕顺序混乱

视频与xml下载自https://www.bilibili.com/bangumi/play/ss416,转换后的ass大约在7分30秒钟左右,弹幕顺序出现大批混乱,原视频与原弹幕并无异常。本地播放器为IINA 0.0.15.1 build 69。

转换配置为

#!/bin/sh
block_list='(房价|我|别撸了|生日|生快|版权|盗版|屏蔽|地域|弹幕|举报|低龄|脑子|吃相|字幕|跳过|跳不了|什么玩意|乱七八糟|快进|什么鬼|水了|跳了|无力吐槽|食用|快乐|百度)'

for file in "$@"
do
  echo $file
  echo ${file%%.xml}.ass
  danmaku2ass -s 1920x1080 -a 0.90 -fn 苹方 -fs 36 -dm 15 -ds 10 -fl "$block_list" -o "${file%%.xml}.ass" "$file"
done

av510431_我的朋友很少NEXT:第11话_迷茫而又懦弱的我.zip

Acfun高级弹幕的滤镜支持

Acfun高级弹幕支持多种滤镜特效。
虽然那些是Adobe Flash的东西,用ASS字幕无法完美再现。
但是有一部分滤镜,如阴影或描边,可以比较完美地模拟。
有一些高级弹幕需要借助阴影和描边滤镜来达到一定的效果,所以这个feature必须实现。
可惜,Acfun官方提供的特效测试用例从2013年11月开始就无法访问了。现在需要各类有关Acfun弹幕滤镜的详细文档。

如果可以的话,请各位帮忙。 @biergaizi @jabbany @chitosai

请教一下为什么我无法转换B站弹幕呢?提示:ValueError: Unknown comment file format

以下命令行转换NICONICO弹幕可以正常完成,但是转换B站字幕时会报错,提示:ValueError: Unknown comment file format,请教一下这是为什么呢?以下是报错信息:
D:\danmaku2ass-master\danmaku2ass.py -o "1 (2).ass" -
s 1920x1080 -fn "微软雅黑" -fs 45 -a 0.8 -dm 5 -ds 5 "1 (2).xml"
Traceback (most recent call last):
File "D:\danmaku2ass-master\danmaku2ass.py", line 870, in le>
main()
File "D:\danmaku2ass-master\danmaku2ass.py", line 866, in main
Danmaku2ASS(args.file, args.output, width, height, args.protect, args.font,
args.fontsize, args.alpha, args.duration_marquee, args.duration_still, args.redu
ce)
File "D:\danmaku2ass-master\danmaku2ass.py", line 802, in Danma
ku2ASS
comments = ReadComments(input_files, font_size)
File "D:\danmaku2ass-master\danmaku2ass.py", line 831, in ReadC
omments
raise ValueError(_('Unknown comment file format: %s') % i)
ValueError: Unknown comment file format: 1 (2).xml

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.