作为一个 AS 起手的 Coder,代码写来写去还是 AS3 写起来最舒服,只是由于不能文件操作等问题,再加上现在做网页前端也基本用不到 Flash 了,便荒废了很久. 这次终于把录了半年的 Rain Stops, Goodbye (音频部分)杀青了,着手做 PV ,却又不想像以前那样用 Windows Live Movie Maker 随便做做了事,所以就想到用 as3 来动态生成一些内容最终做成视频.
其中涉及到的一个重要的问题就是视频编码,我稍稍 Google 了一圈,能找到的现成的编码器不多,其中 zero point nine 的 Flv Encoder 感觉还不错:第一,这是无损编码;第二,它支持在AIR环境下直接把视频写入硬盘.
AIR 环境算是让 AS3 摆脱了一些束缚,使其能作为一门常规的语言来开发,或者说终于能用 AS3 写软件了. 而且只要把运行环境改成 AIR 就可以直接使用原来的 Flash. 但是有一点要注意,在 Windows 下不能将源文件和发布的文件保存在中文路径下,不然会提示“Test Movie terminated. application descriptor not found”. 建议发布的时候选 Application with runtime embedded 不然的话还要很二地“安装”完才能用. 我用 Flash Builder 的时候就觉得这个设定很二,为何不干脆一点生成个能直接运行的二进制文件,真要搞什么安装可以作为可选附件.
Flv Encoder 的使用很简单,基本上把作者提供的 Example 改一改就能用了,基本没有其他需要翻文档的地方. FlvEncoder.addFrame() 是 Flv Encoder 用来写入帧的函数,第一个参数是图像数据(bitmapData),第二个参数是音频数据(ByteArray). 图像数据只要创建一个 ENTER_FRAME 的事件,每帧用 bitmapData.draw() 把舞台上的东西截下来就行了. 音频数据则比较复杂:作者提供的 Demo 做的是一个记录摄像头的工具,音频来自于输入设备;而我是要从本地读取 mp3 再读出每一帧之间的采样点.
关键的问题就在于“每一帧之间的采样点”. 一开始我试图使用 SoundMixer.computeSpectrum() 来获取,但最终音频不能正常输入,视频也不能正常播放. 然后我尝试了一下 SampleDataEvent 却发现这个事件纯粹是为了输出动态生成的音频用的. 最后我的思路是通过记录 SoundChannel 的 position 属性来定位采样点的位置,然后利用 Sound.extract() 方法来获取两个 position 之间的采样点. 这里有个注意点:SoundChannel 的 position 单位是毫秒,而 Sound.extract() 的参数中 position 的单位却是采样点的个数. 我将其转换过来以后发现无论帧之间空了多久,永远每次只采样 2048 个采样点,并且 SoundChannel.position 其实是根据采样点的数量换算得出的.
最终,我放弃了音频编码,毕竟音频对我而言不是很重要,一方面 Flash 原生只支持 mp3 而不支持 wav,但我最后出视频的时候还会再转码,为了避免二压肯定会用 wav 作为外部轨道,另一方面这样输出的视频可以作为蒙版给其他软件使用,有无音频根本无所谓.
0 条评论。