
大家好,兰音です。已经四个月没登录 B 站了咕了很久了。现在终于可以为另一个脚本 AE 的 om midi 进行更新了。
om midi,After Effects 的音 MAD / YTPMV 辅助脚本。它是一个能够自动将 MIDI 文件转换为 After Effects 中关键帧的脚本。希望在 om midi 的帮助下,可以把人们从枯燥繁重的音画对齐中解救出来,把更多的精力投入到更有创造性的工作中。
什么?还没有听说过 om midi?不!我无法忍受你的行为。现在,你会成为我们中的一员。可以先看一下之前的版本:



这个脚本已经是 2018 年更新的了(就像隔壁“音 MAD 助手”一样),至今已过了很久了。因此我决定将其更新一下。
在此非常感谢为该脚本和音 MAD / YTPMV 的偷懒事业做出贡献的所有前辈们。特别感谢脚本原作者们 @大卫·范·布林克 (omino.com)、@Dora (NGDXW)、@韩琦啥也不知道 (HanceyMica)、@家鳖大帝 (Z4HD) 的努力工作。

距离隔壁“音 MAD 助手”的 Vegas 脚本首次发布也已经有一年的时间了,在这段时间内也累计发布了有 40 个版本了。增加了的功能也越来越多,已经到了国产特有臃肿的地步了。虽然不温不火,但是后来被国外的一个斯巴达混音社团给看上了,然后疯狂添加功能,因此在今年(2022 年)七八月份的时候一度出现了一天一更的奇景。现在也差不多没什么功能需要添加了,除非在 v5 版本时用微软最新推出的 WinUI 3 技术重构一下 UI。

v5 prototype
不过在我看来,音 MAD 助手终究还是玩具,最大的原因就是 Vegas 预览视频的速度真的很快,可以加大量的功能来“玩弄”。不过真正做音 MAD,为了华丽的效果,最终还是要用到 AE(AviUtl 也可以,下次一定弄[/手动狗头]) 。自从我发布了音 MAD 助手了之后就没有用 Vegas 来做过音 MAD,因为后来都是用 AE 制作了。(确实有一个用 Vegas 制作的视频是在脚本发布之后投稿的,但是制作还是在脚本发布前。)因此做音 MAD 最终还是要看 om midi。
AE 最大的特点就是有表达式,因此自由度更高,也是 Vegas、Premiere 等其它软件无法比拟的。而音 MAD 助手略微“傻瓜式”,因此 om midi 脚本的门槛略微比音 MAD 助手更高。
为什么这篇文章这么多删除线?是因为我发现哔哩哔哩专栏有个 bug,就是编辑器工具栏上面没有斜体按钮,但是按 Ctrl + I 快捷键还是可以斜体的。但是最后投稿之后斜体的内容又没有了,因此之前的文章被删掉了很多内容。所以这次就用删除线代替斜体了。
理论上支持 CS4 及以后的版本。并且由于 Adobe After Effects 跨平台因此理论上 Windows 和 macOS 都能支持。
如果不支持你来打我呀可以在这里评论或在 GitHub 中提 issue。
在仓库中下载:https://github.com/otomad/om_midi/releases/latest
话说一年了真的有人注意到了那个奇怪的 GitHub 用户名了吗?
此时显示的是最新版的地址,后期更新后链接的页面可能会和图中不一样,请以最新版为准。

该版脚本由两部分组成,分别是 om midi 和 om utils。
点击 om_midi.jsx 下载脚本本体。其余两个是配套辅助的脚本。
om_utils.jsx 是我自己归纳的适用于制作音 MAD 的表达式库,在我之前的文章中

提到了部分,而这个表达式库是完整的。 “om” 其实是原作者网站 omino 的缩写,但恰好也是 Otomad 的缩写,因此我征用一下用作音 MAD 的表达式库应该没啥问题吧……
ease_in_100%.jsx 是另外的小工具脚本,没有图形界面,点击脚本立即执行,用于将选中的关键帧应用缓入效果,并将曲线拉至 100%。这在 MG 动画的制作中很常用。类似我第一次发布隔壁音 MAD 助手的时候,附带了一个隔一个选一个的脚本。这次也是一样。同样的,类似音 MAD 助手,在 om_midi 脚本本体中也内置了这个缓动脚本的图形化完整版。按需使用,如果轻量化使用就可以直接使用单独的小工具脚本了。
将 om_midi.jsx 放置在 After Effects 安装目录下的 Scripts\ScriptUI Panels 文件夹中。 例如:C:\Program Files\Adobe\Adobe After Effects 2022\Scripts\ScriptUI Panels 打开方式:(有可能需要先重启 AE)选择菜单 窗口 > om_midi.jsx
如果有需要,将 ease_in_100%.jsx 放置在 After Effects 安装目录下的 Scripts 文件夹中。 例如:C:\Program Files\Adobe\Adobe After Effects 2022\Scripts 打开方式:选择菜单 文件 > 脚本 > ease_in_100%.jsx
我这里脚本有点多哈,可能需要找半天。
对于 om_utils.jsx 表达式库,安装和使用方法都略微繁琐。之前听说可以放在 Scripts\Startup 目录下就可以全局使用,但这只是在所有脚本中可以使用,但是表达式中还是不能使用的。目前有两种引入方法:
1. 若放置在 aep 项目的相同目录下(与我之前那篇文章中提到的相同) 在表达式顶部添加:
$.evalFile(thisProject.fullPath.replace(/\\[^\\]*$/, "\\om_utils.jsx")); 2. 若放置在任意位置,然后添加到 AE 项目中(这似乎是标准的引入自定义表达式库的方式) 在表达式顶部添加:
footage("om_utils.jsx").sourceData; 可以利用表达式关联器(拉蚊香)将某个属性拖动到项目中的 om_utils.jsx 这个媒体项目,会自动填写 footage 这一段,然后在后面补上“.sourceData;”就可以了。
即可引入 om utils 表达式。
目前这两种引入的办法都还比较繁琐,如果大家有更好的办法欢迎告诉我。
其实 om midi 不止一个版本的,有很多前辈们对它做出了修改。 我特意看了一下 omino 的原版,似乎这个脚本应该称为 om midi 而不是 om_midi。而 om_midi.jsx 只是文件名而妥协的名称,因此为了规范化而统一名称。
除了 v1.2 之外,其它的版本均没有给出版本号。因此那些版本号是我自拟的。为方便表述,下文中的所有版本均以版本号替代。
所以,哔哩哔哩专栏不能添加表格吗?

表格中的大部分信息是从家鳖大帝的中文文档中获取的。
现在已经 2022 年了,我一开始打算使用 ECMAScript 2022 及以后的最新技术。没错 AE 的表达式确实是支持的,甚至也有设置选项:

我一开始信誓旦旦地在脚本中敲了几个箭头函数、模板字符串和 class。然后一运行脚本报错了。
结论:表达式确实可以用最新的 ESNEXT,至于脚本,对不起,这里只有 ExtendScript。ExtendScript 是什么?就是 ES3 加一些其它的(不规范的)东西。ES3 啥时候发布的?1999 年……非常远古了。然而 ExtendScript 就是不更新。
没关系,我们有微软的 TypeScript,加一点微软自家的 VSCode,嗯~味道好极了(窜台了抱歉)。然后我们就可以使用最新的 class、lambda 等各种新语法,然后 TypeScript 会自动帮我们转换为旧版兼容代码。这样也好,可以兼容到 Adobe Creative Suite (CS) 时代的 AE。(为什么我每次写脚本——上次那个 C# 的音 MAD 助手也是一样——都用不到最新的技术,非要这样那样地兼容旧版。)
你以为这就结束了?不,这才只是 ExtendScript 坑爹的第一步。第二步, 如果你学过 JavaScript,猜一下下面这两行代码的运算顺序是如何的?
/* 1. */ a || b && c
/* 2. */ a === 0 ? b : a === 1 ? c : d 你是不是以为它应该是
/* 1. */ a || (b && c)
/* 2. */ a === 0 ? b : (a === 1 ? c : d) 是的没错,任何现在的支持 JavaScript 的浏览器都是这么运算的。
然而傲娇的 ExtendScript 拥有自己的见解,不愿与世俗同流合污,它是这样运算的。
/* 1. */ (a || b) && c
/* 2. */ (a === 0 ? b : a === 1) ? c : d 它成功地把我的代码丑化器给弄坏了,我还得额外调配置。更多坑爹内容,你学了就知道了(才不要呢)。
除了现在所使用的 JSX 脚本之外,Adobe 还有一个新版的 CEP 插件,这样就可以使用最新的前端技术来开发了,毕竟 Adobe 都内置一个 Chromium 浏览器的。
这要是在 Adobe CC 2015 之前用还比较好,毕竟可以直接用 Adobe Extension Manager 安装。而现在,Adobe Extension Manager 已经被移除了。Adobe 现在想让用户都从它的 Adobe Add-Ons 市场上购买、下载插件。一是国内网络访问非常慢;二是如果你用的是盗版 Adobe 软件,那就都白想活啦!既然大家都知道了,这戏我也就不演了,我就是大名鼎鼎的……啊呸,抱歉。
在这一版中,我使用了 TypeScript 搭配 rollup 等前端技术重写了脚本。然后逐步重新实现原版中的所有功能,因此部分行为可能和原版不完全一致。其实就是懒得读源码。脚本中的所有功能都已经模块化了,方便之后修改。如果有什么 bug 或者新想法都可以来评论或者提 issue。该脚本和隔壁一样,会不定时地更新的。
该脚本甚至重写了 MIDI 读取器,优化了部分不规范 MIDI 文件的支持,因此理论上支持的 MIDI 文件比隔壁音 MAD 助手调库 (NAudio) 的还要多。
此外,该版类似隔壁优化了报错提示,遇到了错误,会用人话描述出来原因以及阐述解决方法。而不是默默吞掉不吭声,用户也不知道发生了什么。
另外注意这一版中把进度条暂时移除了,因为在 jsx 脚本中进度条并不是异步的,可能不知道是脚本处理太快了还是我太辣鸡了没读懂原版脚本,进度条一显示界面还没刷出来,就等处理完成关掉了。并且前版中经常遇到进度条结束了但关不掉的问题,于是暂时移除了,以后再看看能否加回。(音 MAD 助手原版没进度条就增加进度条,om midi 原版有进度条就移除进度条,我是跟进度条有仇吗?)
如果有需求,仓库中保存了前几个版本的脚本,需要者自提:
https://github.com/otomad/om_midi/tree/main/achieves
点击设置按钮,顶部标题栏写了当前版本号。
也可以用记事本打开脚本文件,文件顶部也写了当前版本号。

这是 VSCode
为节约空间代码已经被简化了,如果想改源码也可以去仓库里面看。

在顶部点击三个点按钮打开 MIDI 文件。在 v1.2 的时候家鳖大帝将按钮改名为“浏览...”,后来的版本又改回去了。(因为不是一个分支。)

脚本提前做了处理 MIDI 的操作,如果 MIDI 不合规范,脚本会立刻报错。
om midi 本来就是支持多轨的,但是由于没有选择,会将所有轨道全部挤到一个空对象图层中,很多人都觉得这个图层放在这不把多余的属性删除就很吃性能。在 v2.0 中,Dora (NGDXW) 先辈本来想引入一个多轨选择的菜单,但是失败了。测试的时候多轨 MIDI 文件会报出各种各样的错误,但是坑爹的 AE 默认会把所有错误吞掉而不是弹窗警告,因此也不好找出错误来。所以 v2.0 中多轨功能被抠掉了,只生成第一个轨道。
在这一版中多轨功能又回归了,但肯定不能像 v2.0 之前的版本那样把所有轨道全弄出来。因此类似隔壁,做了一个轨道选择器。
选择轨道的按钮标签会展示选中轨道的通道编号、轨道名称和音符个数(括号内)。

然后就可以选择轨道了,可多选。生成之后会为每一个轨道新增一个空对象图层而不是全部挤到一个图层里。并且如果轨道名称是中文的话会支持而不是显示为乱码。
隔壁的多轨功能和中文名称支持在最近的版本才支持。
设定 BPM。家鳖大帝先辈在之前的版本中曾留下了一个技术难点,就是 MIDI 的 BPM 不能自定义,只能根据 MIDI 中的配置而决定。这一版中可以自定义 BPM 了,并且打开 MIDI 文件时也能自动获取第一个 BPM。
至于动态 BPM,目前的版本还不支持,隔壁已经支持了(需要求积分,算曲边梯形面积[/手动狗头])。
开始时间以设定关键帧开始生成的时间:(默认值为显示开始时间)
显示开始时间——时间轴最左侧; 当前时间——光标处; 工作区域——如果设定了工作区域(B、N 快捷键),则为工作区域的最开始处; 0——一般情况下与显示开始时间一致,但是如果修改了合成的开始时间码的话,就是从 0 这个时间码开始。
如果 MIDI 文件在脚本打开期间被修改了,需要重新打开 MIDI 文件。
空对象
经典的创建空对象属性功能。
该版优化了一下,如果已经创建过空对象了,下一个创建时就会利用现有的空对象纯色源,而不是再创建一个新的,要不然纯色文件夹里面一堆空 1、空 2、空 3……全部都是一样的,看着也闹心。

该图片和下面的图片都来源于家鳖大帝的中文说明文档。
该属性于 v0.1 首次引入。
该属性标注了每个音符的音高,其值域为 [0, 127] 之间的整数。其中,中央 C5 的值为 60。 计算方法:为方便表述先建一个数组
["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"] 例如 C 的下标是 0,B 的下标是 11。
然后根据公式:后面的数字 × 12 + 前面的符号的下标。
以 C5 为例。.即可得出。
因此 MIDI 所能表示的音域范围为 C0 ~ G10。
该属性于 v0.1 首次引入。
该属性标注了每个音符的击键/松键力度信息,约等于音符的音量,其值域为 [0, 127] 之间的整数。不常用属性。
Dora 先辈在 v2.0 中留下了一个疑问,说 Velocity 究竟表示力度还是速度。这里解答一下,它就是力度,也可以理解为钢琴击键和松键时的速度,速度越快声音越大。但是速度这个词容易产生歧义,而力度就能很好地表示它。

由于“力度”这个属性各位音 MADer 都用得比较少,因此我对其做出了一点改动。
冷知识:MIDI 文件通过两种事件来记录一个音符信息,分别是 Note On(音符开)和 Note Off(音符关)。不管是 Note On 还是 Note Off,两种事件都记录两个信息,分别是音高和力度。当发出 Note On 事件时,电脑会一直发声,因为没有事件让它停止。这时就需要 Note Off 事件来使这个音符停止发声。Note On 和 Note Off 成对出现,缺一不可。那么如果是和弦的话,它是如何检测究竟关闭哪个 Note On 音符的呢?因为 Note On 和 Note Off 都记录了音高信息,如果它们俩的音高信息一样的话,就可以正确关闭需要的音符了。那如果这个和弦的几个音符都重叠在一个音高上呢?为此我特意用 FL Studio 做了一个测试:
假设有两个音符,设定好它们的持续时间和起始位置(左图),然后把它们重叠在一个音高上(右图)。

导出 MIDI,再将其导入回 FL Studio。可以看到音符的摆放位置还是一样的。

我们换成第二种摆放方法。设定好它们的持续时间和起始位置(左图),然后把它们重叠在一个音高上(右图)。

导出 MIDI,再将其导入回 FL Studio。可以看到音符的摆放位置变成了前一种摆放方式了。

由此可见,Note Off 优先关闭靠后的 Note On。即“栈”而不是“队列”。这可能就是在 FL Studio 中如果大量的音符重叠在一个音高上,音符就会莫名断开的缘故了。
另一个问题,Note On 和对应的 Note Off 都记录了相同的音高信息,因此才能关联起来。然而它们的力度信息却是不一定相同的。Note On 表示的力度信息与 FL 中写的一致,即击键力度,那 Note Off 表示的力度信息又是什么?我查阅了很多资料,有的地方说可以动态力度,从 Note On 的力度滑到 Note Off 的力度;也有的地方说这代表松键力度,像钢琴击键和松键的力度(速度)不一样,发出的声音也可能略有不一样。我个人感觉后者更靠谱一些。
因此在这一版的力度属性中,会在该音符发声完之后增加一个关键帧表示松键力度信息。反正这个属性的用处较少,因此改动了一下。
另外,在原版 v0.1 中,如果 MIDI 的第一个音符不是在乐曲最开始,会在最开始处增加一个力度为 0 的关键帧。这一版中继承了这一特性。
该属性于 v0.1 首次引入。
该属性标注了每个音符开的持续时间,整数。持续时间越长,数值越大。不常用属性。

在前面已经提到了,MIDI 文件内部音符只记录了音高和力度信息,并没有持续时间这个信息。但是大卫·范·布林克在最早的 v0.1 中设计读取 MIDI 文件的部分时,为了更方便,直接将音符关事件绑定在对应的音符开事件上,然后直接计算两个音符之间的时间差,就可以在解析 MIDI 期间将持续时间信息求出来了。
我最开始还没这么做,然后其它所有属性都已经做完了,发现这个属性还不好做出。因此为了这个不常用属性还单独实现了音符开和音符关相互绑定的功能。
该属性于 v1.0 首次引入。
根据节奏依次生成值域为 {-100, 100} 的关键帧,与前版保持一致,初始值为 100。单位:百分比。值曲线图表为方波。
花括号是集合,方括号是闭区间,圆括号是开区间。这个高一数学应该学过吧。

直接将图层的缩放属性“拉蚊香”(表达式关联器)到这个属性上,默认情况下其水平、垂直方向都会颠倒,相当于隔壁“颠倒”效果。这是因为这个属性是一维属性,而图层的缩放属性是二维属性,这将会对图层的两个维度同时进行映射。
- Q:那为什么不直接做成二维属性呢? - A:那如果我想要垂直翻转呢?
此时该图层缩放属性大致如下:(以实际情况为准,示例内容仅供参考,下同)
temp = thisComp.layer("midi").effect("缩放")("滑块");
[temp, temp]; 那么我如何实现仅水平翻转或垂直翻转呢?
还是上面的表达式,改成如下形式:
temp = thisComp.layer("midi").effect("缩放")("滑块");
[temp, 100]; 此举会使垂直方向的缩放值恒为 100,进而实现水平翻转的效果。
还是上面的表达式,改成如下形式:
temp = thisComp.layer("midi").effect("缩放")("滑块");
[100, temp]; 此举会使水平方向的缩放值恒为 100,进而实现垂直翻转的效果。
为表述内容的严谨性,这里尽量统一话术。少用“左右翻转”“上下翻转”而使用“水平翻转”“垂直翻转”。 但是如果之后是介绍 AviUtl 的话,此时就应该使用“左右翻转”“上下翻转”而不是“水平翻转”“垂直翻转”了。 不过相比之下,v2.0 版本写的“水平缩放”(其实是“左右缩放”)会更贴切 AE 的功能实现。 至于“左右抽动”“上下抽动”……算了“抽动”这个词听起来不太好。
该属性于 v1.2 首次引入,于 v2.0 移除,于 v3.x 重新引入。
根据节奏依次生成值域为 {-1, 1} 的关键帧,与前版保持一致,初始值为 1。值曲线图表为方波。
该属性与缩放属性类似,但是关键帧的值由 {-100, 100} 更换为 {-1, 1}。经过适当的表达式配置将允许图层在具备缩放/翻转效果的同时可被设置缩放比例。
所以这和直接将缩放属性的值除以 100 有啥区别……

首先还是拉蚊香,然后直接给出实现水平翻转和垂直翻转的表达式吧。
temp = thisComp.layer("midi").effect("高级缩放")("滑块");
[value[0] * temp, value[1]]; temp = thisComp.layer("midi").effect("高级缩放")("滑块");
[value[0], value[1] * temp]; 该属性于 v1.0 首次引入。
每有一个音符,关键帧的值依次为 0→90→180→270→0……以此类推。与前版保持一致,初始值为 0。单位:角度。值曲线图表为上阶梯。

直接用表达式关联器将旋转属性与该属性滑块关联即可。
该属性于 v1.0 首次引入,于 v2.0 移除,于 v3.x 重新引入。 可能是想到逆时针旋转这个东西直接用顺时针旋转属性的值,然后用表达式
(360 - 顺时针旋转的值) % 360; 就可以了,因此觉得没必要就删了。但是这版由于我看到只有顺时针旋转没有逆时针旋转强迫症犯了就把它加了回来。
每有一个音符,关键帧的值依次为 0→270→180→90→0……以此类推。与前版保持一致,初始值为 0。单位:角度。值曲线图表为下阶梯。

好吧原版其实是 0→-90→-180→-270→0……现版我把它改了。
直接用表达式关联器将旋转属性与该属性滑块关联即可。
该属性于 v1.0 首次引入。
每有一个音符,关键帧的值便 +1。前版初始值为 0,现版初始值为 1,我把逻辑改了一下。
因为现版类似力度属性,会在乐曲一开始如果没有音符的话,增加一个关键帧,其值为 0,这样可以表示一开始没有音符,而不是和后面的第一个音符关键帧 1 混在一起。
其实有了“计数”,其余的几个属性“缩放”“高级缩放”“顺时针旋转”“逆时针旋转”“布尔”都可以用这个属性来表示,因此这个属性还是比较常用的。

该属性一般不会直接使用,会作为某个表达式的一个参数调用。
注意由于 AE 一个图层的关键帧是不支持复音的,针对复音,该版脚本做出了优化,不会对同一个时间点上的音符重复计数。“缩放”等其它属性也是一样的。
例如这段 MIDI:

一眼就能看出来这是什么歌吧!Red Zone - Chords
同一时间点同时有四个音符。此时:
前版的关键帧值依次为:4→8→12→16…… 现版的关键帧值依次为:1→2→3→4…… (注意前版是以 0 起始的,实际上应该是 3→7→11→15……为控制变量改了一下。)
该属性于 v1.0 首次引入。
根据节奏依次生成值域为 {1, 0} ({true, false}) 的关键帧,与前版保持一致,初始值为 1 (true)。值曲线图表为方波。

可以由缩放属性的值推出:
(缩放 / 100 + 1) / 2; 因此这些属性真的可以直接用“计数”属性来推出,好多几乎都是重复的。
AE 中的所有效果的属性几乎都是用数字和字符串来表示的,并没有布尔。有的属性确实是个复选框,但是展示出来看数字发现还是 0 和 1。但是要注意,由于 JavaScript 这个坑爹的精度问题。0 可能并不一定是 0,有可能是一个非常小的数,因此在进行 if、三元运算符、=== 0 等判断的问题上,很有可能与预期不相符。因此为了解决模拟信号失真(不是)的问题,建议可以使用 ≥0.5、<0.5 等这样的判断会比较更合适。
该属性于 v1.0 首次引入。
在每个音符发声期间,从 0 线性变化到 1。值域为 [0, 1] 之间的浮点值,与前版保持一致,初始值为 0。值曲线图表为锯齿波。

根据图表,我们可以看到有些音符后面会定在 1 保持一段时间,这是因为这个音符的后面有点空白,这时没有音符,因此就会定在 1 这里。而另外一些音符之后立马跟着下一个音符,此时属性滑块值会从 1 突变为 0。换句话说,一个音符关的时间恰好是下一个音符开。难道两个关键帧可以重叠在一起吗?并不是,这时两个关键帧会“打架”。因此为了不能打架,只能金坷垃好处都有啥,谁说对了就给他,需要在音符关和音符开之间避让而腾出间隔。这个时间间隔在 v0.1 中已有体现,为 5 丝秒(秒,10 丝秒为 1 毫秒)。
为了让大家看清楚这里的间隔,我们把时间轴放大一下。

图片可能需要手动放大一下才能看清。两个关键帧中间有非常小的间隙。并且这些关键帧甚至都不在合成的帧率所能表示的帧上。如果点击一下关键帧,该关键帧会自动偏移到当前帧率所能表示的帧上。

隔壁 Vegas 可以取消“量化为帧”,AE 似乎暂时没有方法(如果有方法可以告诉我),因此不要乱点这些关键帧,否则可能值就变了。
在 v2.0 中,Dora 先辈分出了“时间重映射 1”“时间重映射 2”两个属性。好吧我确实没明白两个属性各自的作用。在评论区中,他说“时间重映射 1”类似 Vegas 拉伸素材,而“时间重映射 2”相当于在时间处截断素材。但是“创建空对象”就不应该与选中的素材有联系,它应该是可以独立运行的,不能因为素材长度的变化而改变其值。这也就是为什么在 v2.0 中必须选中一个图层才能执行创建空对象,而 v1.2 及之前的版本不用选中图层,只要激活合成就可以创建空对象了。并且这其实是一个读取不到选中图层的报错,而报错又不提示只会默默吞掉。我相信有很多人发现为什么在 v2.0 中点击生成按钮半天没反应。(当然还有另一个原因,)
所以这一版中恢复为一个“时间重映射”属性。至于“时间重映射 1”“时间重映射 2”,则依次更名为“时间重映射(拉伸)”“时间重映射(截断)”放在后面的“应用效果”中了。
直接将素材的时间重映射拉蚊香到这个属性上,一般不能满足用户条件。因为这个属性的值域为 [0, 1],而素材的时间重映射是从 0 到源的持续时间(单位:秒),每个素材的持续时间又不一样。因此需要将该属性的值乘以素材的持续时间才能覆盖到整个素材周期。然而,在 AE 中素材的最后一帧是空白(一般看起来是纯黑色的),因此直接这么做会发现素材在不断地闪烁黑色。为了解决还需要手动在表达式中去掉源的最后一帧,一般偷懒的解决方法是手动去掉一个固定的常数,但是这并不通用。正确的方式是获取源素材的帧率,然后将素材的时间去掉最后一帧的持续时间,这样才可以应对不同帧率的素材。然而不管怎么说,这些操作都过于繁琐,你需要写一段冗长的表达式然后复制到各个素材上,如果发现写错了,每一个素材都需要重新改。为此,有两种解决方案。一是使用后面将要提到的“应用效果”,二是使用后面要介绍的配套的表达式库 om utils。
该属性于 v3.x 首次引入。
在每个音符发声期间,第奇数个音符从 0 线性变化到 1,第偶数个音符从 1 线性变化到 0。值域为 [0, 1] 之间的浮点值,初始值为 0。值曲线图表为三角波。

此时时间会从开始播放到结束,然后又从结束倒放到开始。相当于隔壁“乒乓效应”效果。
这种效果在 YouTube 音 MADer スターハム 的作品风格中非常常见。然而在先前的版本中并没有直接实现此效果的属性,需要依靠“时间重映射”和“缩放”两个属性配合来完成。现在回想起来,实现这个效果的表达式还是我人生第一次写 AE 表达式甚至是写 JavaScript 的时候。
使用该属性的复杂程度与“时间重映射”一致,此处不再赘述。
该属性于 v3.x 首次引入。
不常用属性 +1。用于表示该时刻是否有音符。有则为 1,否则为 0。值域为 {1, 0}。
如果乐曲最开始没有音符,会在最开始增加一个关键帧,其值为 0。唯一三个会在乐曲最开始额外添加关键帧的属性分别是:力度、计数、音符开。
按理来说这个属性应该和“力度”属性合并,然而力度现在增加了松键力度。因此只好额外分出一个属性来表示。
该属性是唯一一个不会对音符关和音符开如果重合在一起则避让的属性。反之,两个属性会重叠在一起。其余属性如力度、时间重映射、来回,都会在音符关和音符开之间避让而腾出间隔。

用处嘛,一般是用于控制不透明度的。
该属性于 v3.x 首次引入。
该属性和接下来几个属性是和音符事件无关系的,而是元数据事件。
在 FL Studio 下方可以控制这些属性[右边的“通道控制”部分(FL 翻译错误)]:

通道声像调整——通道声像 通道音量——通道音量 通道音高——通道弯音
之前我曾误将“声像”写成“声相”,这是错误的。“声像”才是指的左右声道信息,而“声相”是指声音相位。
这个属性就是描述该通道的声相(声道)信息。值域为 [-64, 63] 之间的整数。值越小,声音越靠左;值越大,声音越靠右。 你可能注意到了,右声道(最大 63)比左声道(最大 64)能表示的数少一位,为什么呢?因为这个参数在 MIDI 文件中的表示范围为 [0, 127],一共可以表示 128 个数(0 也算一个数),是偶数,没有最中间的数(别说中位数取最中间两个数取平均值啊,不能是小数),然后 MIDI 规定 64 为中置声道,因此右声道只能比左声道少一位数了。
此处为了方便,将声像值减去了 64,使其“归零”,以 0 表示中置声道,以便使用。
然而由于 -64 和 63,两边不对称。为了方便,在设置中增加了一个选项。勾选后,此时声像值域会变为 [-100, 100] 之间的小数。
该属性于 v3.x 首次引入。
该属性描述该通道的音量信息。值域为 [0, 127] 之间的整数。
该属性于 v3.x 首次引入。
弯音表示滑音、倚音等。FL Studio 原文为通道音高。为了避免让人误以为是通道的音符的音高,因此换了个名字。
该属性描述该通道相对于标准音高的弯音轮信息,为 0 时表示标准音高。值域为 [-8192, 8191] 之间的整数。没错,左右又没对齐,原因同上。
在 MIDI 文件内部中值域为 [0, 16383],其中 8192 表示标准音高。为方便而将其“归零”。
在 FL Studio 中,使用 FL 自带的滑音是不能写入 MIDI 文件中的,因为 MIDI 文件不支持。像这样是不可以的。

正确的做法是这样。

至于具体多大值,左上角有显示。

至此,创建空对象的属性就全部介绍完了。
应用效果
应用效果于 v2.0 首次提供,该版中也增加了一些新的效果。使用这些效果之后,就不必再手动写表达式了。此时要求用户必须选中一个图层,而且在 MIDI 轨道中只能选择一条音轨,因为 AE 图层不能多轨。

对了,请不要做一些无意义的事。比如既顺时针旋转又逆时针旋转,既时间重映射(拉伸)又时间重映射(截断)。我也不知道这会发生什么事情[/手动滑稽]。
在“应用效果”和其它几个选项卡之间切换时,会发现开始时间这个设置发生了变动。这是因为“应用效果”和“空对象”“工具”使用不一样的配置。在“应用效果”中,开始时间默认值为“当前时间”。并且在“当前时间”这里玩了个文字游戏(其实就是懒得换字符串):
显示开始时间——将素材移动到时间轴最左侧; 当前时间——不移动素材,保持现有位置,注意此时就不是移动素材到光标处了; 工作区域——如果设定了工作区域,则移动素材到工作区域的最开始处; 0——一般情况下与显示开始时间一致,但是如果修改了合成的开始时间码的话,就是将素材移动到 0 这个时间码。
可以看到除了“当前时间”之外,其余选项几乎没有变动。
于是空对象中的“时间重映射 1”和“时间重映射 2”就被移动到这里来了。顾名思义,就是自动为素材根据 MIDI 音符节奏添加时间重映射。
那么就看括号中的词。“拉伸”就是类似 Vegas 的拉伸素材改变时间长度。每个音符均会遍历整段素材时间周期。这会改变每个素材的播放速度。这样可以保证每个音符完整播放整段素材而不是放一部分。
“截断”会保持素材的播放速度不变,播放音符的时间长度后截断。这样可以保证每个音符中的素材的播放速度都是相同的。
相比于前版,前版仅仅只是将关键帧放到图层中,而且也不是在素材的入点位置,该版优化了更多。
以时间重映射(拉伸)为例,如果手动将一段视频素材只截取一部分,只需要其中的一个动作之类的。像这样:

前版会忽视这个设定,应用时间重映射之后,还是会播放整段素材,会把完整的视频在每个音符中播放一遍,这使得我们手动截取一部分的操作变得无效。当时,必须右键图层,选择预合成,在弹出的对话框中还必须选择“将所有属性移动到新合成”,才能正常使用该功能。

现版中不必这样操作了。您可以自由截取素材的一段时间。然后应用时间重映射效果,脚本只会遍历截取后素材的持续时间,而不会跑到这段时间外面去了。类似隔壁可以在轨道中将素材截取时间,打开脚本后,选择“选中的轨道素材”。这样,截取素材变得更自由。
并且素材的长度会自动改变为乐曲的长度。

只截取素材中的一部分时间
特别地,如果乐曲一开始没有音符,会匀速常速播放素材截取入点之前的时间段。
当然了,如果想要预合成也不是不可以,该版同样是支持的。
注意:一般情况下,应用其它的效果,务必和“时间重映射(拉伸)”“时间重映射(截断)”“来回”之一同时开启,否则比如水平翻转,就会逐渐翻转到截取视频之后的时间段。当然如果你就是想实现这种奇怪的效果也可以,比如素材人物每说一个字就水平翻转一次之类的。
与空对象中的一样。这将使得素材从开始播放到结尾,又从结尾播放到开头,来回播放。同样的,这也会仅应用于截取的时间段。
标准的“左右抽”,没啥说的。
这里有一个音 MAD 的技巧,任何软件都能应用的:
应用水平翻转之前,先修剪一下素材画面。开启预览画面的对称网格。然后使得素材人物的鼻子位于画面正中央,或者两只眼睛平均对称位于水平中央竖线的两侧。必要时候还可以旋转画面使得人脸方向与画面一致,不过没必要。这样,应用水平翻转的效果会最好。
像这样:

困呐~
而不是把素材丢进去二话不说直接水平翻转开整,那样看起来真的就只是水平翻转,效果不佳。或者是多人物素材,直接正常水平翻转之后还会把两人位置也反过来,那样观感就变差了。
根据节奏,依次镜像素材的左半边和右半边。(噔噔咚!)
这在 YouTube 音 MADer Zetting Cokinger 的作品风格中非常常见。
就是顺时针和逆时针旋转啦。与创建空对象中的一致。
在 v2.0 中仅有顺时针旋转,因强迫症犯了就增加了逆时针旋转。
使用蒙版功能将素材修剪为正方形或圆形,应用旋转效果会更好。
就是反色/负片。画面颜色会根据节奏不停反转(闪来闪去)。阴间人狂喜。
嗯?好像混进来了什么隔壁音 MAD 助手中的奇怪的东西。

是这样的,之前我做了某个作品。当时在视频简介中写道,大概是当时我电脑性能太差了,运行当时的新版 Vegas Pro 19 几分钟之后电脑 CPU 会剧烈燃烧然后电脑过热保护强制断电。然后就没法用 Vegas 做了改用 AE 做。结果评论中 @一个喜欢伊蕾娜的屑up 回复道:
草,AE还能做音频吗?
没有啊,我只是用 AE 做 PV,音频还是用 FL 做的。
不过这个评论给了我启发。 于是现在真的能用 AE 做音频了[/手动滑稽]!
先将素材截取到要调的那个音的时间。勾选调音之后,指定素材原始音高(与隔壁一样)。应用之后,会复制一份选中的图层且仅开启音频,放到选中图层下方,然后对那个复制的新图层进行调音。
至于 AE 如何调音?你用了就知道了。
不过 AE 调音,纯纯的只是娱乐罢了。不会真的有人用 AE 调音吧?
至此,应用效果的属性就全部介绍完了。
类似隔壁音 MAD 助手,om midi 脚本中也内置了一些适用于 AE 的实用工具。既然是适用于 AE,那就别弄什么“隔一个选一个”了。
在选项卡顶部下拉菜单中选择所需工具。

大家可能使用过 Marker Conductor 这个脚本,用来生成给定 BPM 节拍的标记时非常有用。
为此,我复刻了一份该脚本并内置了大部分功能进来,毕竟这个功能在制作音 MAD 对轨时还是很常用的。
除非你是 @氷鳩さくの 这位大佬,不需要看节拍,凭耳朵就能听出节拍来对轨。(World 酱别打我……)
因为 AE 预览感觉没有 Vegas 流畅,很容易播放一会ㄦ就卡住然后慢放了。这时,借助一个节拍的标尺辅助来观察音乐节拍还是很有帮助的。可惜 AE 不像 Vegas 那样内置一个节拍标尺,只能用这种偏方。
BPM/秒数/帧数:根据指定的单位设定时间间隔。可以是小数。
节拍(仅限 BPM 单位):指定这是四几拍,默认四四拍。必须是正整数。如果想整八六拍,把 BPM 乘以 2 就行。
偏移(仅限时间/帧数单位):指定标记单位的偏移值。比如输入 10,就从 11 开始计数(与原版保持一致)。可以是小数,正负均可。
标记在:标记在一个新建的空对象图层(如果已有空对象纯色源,会利用现有的)还是标记在当前选中的图层。
开始时间:还有一个开始时间设置就在选项卡上方。这个设置就和前面创建空对象的时候是一样的。

制作音 MAD PV 或者做 MG 动画时,有一个速度曲线效果非常常用且好看。就是这样:

每一次都需要手动将那个锚点拉到头,因此这个工具就是自动为你做这件事的。只要选中所需的关键帧,然后应用脚本就可以了。



OK,以后有新工具再去新增。
AE 脚本不能像隔壁 Vegas 脚本那样,开一个新窗口放一大堆功能进去。AE 调色板面板的面积有限。因此其它的一些配置就放到设置里面去了。

标题栏显示了当前脚本的版本号。
左边那段描述原本是位于脚本主面板顶部的,现在放到设置中了。
先看左下角的一堆按钮。
仓库地址:打开 GitHub 仓库页面。 检查更新:下载最新版脚本。 关于脚本引擎:关于 ExtendScript 脚本的一些版本信息。
这里告诉了您如何导入配套表达式库的方法,主要导入方式太麻烦了,可以在这里复制命令。 具体内容和前文讲的一致。

不知道你们是否之前像我一样,用 FL Studio 生成一段某个固定 BPM 然后全是固定节奏四分音符的 MIDI,然后利用 om midi 生成关键帧?
该功能自动为你做这件事。点击该按钮之后,会自动导入一段纯四分音符的 MIDI,然后你可以改变 BPM 值,以生成某个 BPM 节奏的关键帧。
像这样:


计数
再看右边。
指定脚本语言。从 v1.2 开始 UI 变为了中文。现在为了照顾外国朋友,恢复了英文的支持,同时增加了日文。
应用默认值就是和 AE 软件的语言一致。
这次我吃了教训了,隔壁那边一整五个语言,后面加新功能每次都要翻译四遍,太麻烦了,又不敢删语言,怕万一真有人用就麻烦了。这次只整三个语言。
俄语全程拿谷歌翻译的,具体啥意思我也不懂。听说俄罗斯朋友拿英语还看得懂一些。 繁体中文,我后来才知道原来 Vegas 官方没有繁体中文版,只有民间繁体汉化包。
在前版中,MIDI 空对象名称将会命名为 [midi] 加上选中图层的名称,该版中改为了 [midi] 加上选中 MIDI 音轨名称。由于我不能帮大家做决定,因此给了一个开关可以改回去。MIUI 开关系统。
我后来才知道更早的版本是 [midi] 加上选中 MIDI 文件的名称。
前文提到了。通道声像正常情况下值域是 [-64, 63] 之间的整数,开启该选项后,值域会改为 [-100, 100] 之间的小数。这将使得后期处理数据时更加方便。该选项默认开启。
@氷鳩さくの (My_world) 的特有图层叠叠乐是怎么回事呢?图层相信大家都很熟悉,但是 @氷鳩さくの 的特有图层叠叠乐是怎么回事呢,下面就让小编带大家一起了解吧。
@氷鳩さくの 的特有图层叠叠乐,其实就是

大家可能会很惊讶 @氷鳩さくの 怎么会图层叠叠乐呢?但事实就是这样,

小编也感到非常惊讶。
这就是关于 @氷鳩さくの 的特有图层叠叠乐的事情了,大家有什么想法呢,欢迎一巴掌拍死营销号小编哦!
开启后,应用“水平翻转”“顺时针旋转”“逆时针旋转”这三个效果时,会在运动时增加动画视觉效果,而不是简单的静态感。默认开启。
水平翻转:将会添加缩放进入效果。 顺时针/逆时针旋转:将会添加缓入旋转效果。
改变图层“变换”中的值,无论如何它都会在所有添加的效果之后才执行,不能改变其顺序。有时候我想修改图层变换中的参数,想在执行变换之后再去增加一个效果,直接是无法做到的,除非创建预合成。
不过在 效果 > 扭曲 中,有一个名为“变换”的效果,这就可以满足需求。


然后,就会增加一个名为“变换”的效果,在这里面修改变换值,就可以和普通效果插件一样,改变其执行效果的顺序。然后就可以满足条件了。
om midi 用于制作水平翻转等也是一样的,先把水平翻转做好了,将缩放信息放在效果里面的变换中,然后就可以使用图层本身的变换来改变图层的尺寸和位置了。
开启该选项之后,“水平翻转”“顺时针旋转”“逆时针旋转”三个效果不会将属性添加到图层上的变换中,而是创建一个名为变换的效果,添加到这个变换的效果上面。如果该效果脚本已经创建过,不会额外再创建一次。
好了,至此,om midi 的所有设置已经讲完了。接下来来看 om utils 的使用方法。
在前文我们已经讲了,使用创建空对象的方法添加“时间重映射”属性到关键帧。而将素材应用这一属性,需要一段繁琐的表达式。有没有什么办法让它像内置函数比如 wiggle 那样,只需要填写几个参数就可以实现呢,即将这段表达式封装成一个自定义的函数,然后像 wiggle 那样,直接调用这个函数就好了。为此,我自行整理了一些适用于音 MAD 的一些表达式库。之后也可以逐步添加。如果发现了错误可以直接在 JSX 文件中修改,AE 中的表达式计算值会自动更新。
使用该功能需要用户具备一定的 AE 表达式能力。
根据前文的说法,有两种引入方法,两种方法都可以。第一种方法在我之前一篇专栏中已经提到过了,这次我们选择第二种方法。
直接将 jsx 文件拖入项目中。

怪奇怪的……
在需要使用的属性中,拉蚊香到到这个 om_utils.jsx 文件上,然后该属性表达式中会自动添加一行代码,然后手动将其补全。
footage(&quot;om_utils.jsx&quot;).sourceData; 然后我们就把这个表达式库引入进来了。(注意如果你使用的是第一种引入方式,添加的代码是不同的。)假设你学过 C 语言的话,这有点类似于 #include 的导入。之后,表达式库中的函数我们就可以使用了。
为了不污染全局命名空间,因此将所有函数成员放在了一个名为 Utils 的对象中。 也就是说,如果你想使用一个名为 timeRemap 的函数,你应该使用 Utils.timeRemap(参数); 。
例如,我想使用时间重映射函数。直接将素材的时间重映射关联到使用 om midi 创建的“时间重映射”空对象属性上。

我们发现这个素材持续时间有 30 秒(上方一次函数曲线),但是每个音符仅在它 0 ~ 1 秒的范围内扫描(下方像心电图一样的曲线),我们如何让它在整个素材持续周期内扫描呢?
在素材的时间重映射表达式中填写
footage(&quot;om_utils.jsx&quot;).sourceData;
Utils.timeRemap(&quot;[midi]Lead&quot;, true); // &quot;[midi]Lead&quot; 为空对象图层的名称。 我们可以看到每个音符都能遍历整个素材周期了。

接下来讲解一下每个函数的用法:
将 om midi 生成的时间重映射 [0 ~ 1] 值映射到素材源的实际时间值。
参数:
midiName: string? - om midi 图层名称。如果留空,则默认为当前图层名称前加上“[midi]”。例如如果素材的名称和 MIDI 轨道的名称一样,就可以不填写这个参数(或者填 undefined)。像这样就可以:

stretchOnly: boolean= - 为 true 时,将使用时间重映射拉伸而不是截断。默认为 false。注意如果素材时间过短无法在较长的时间截断,则仍然为拉伸。
rate: number= - 强行改变素材回放速率。默认为 1。
返回值:number - 时间重映射后的实际值。
获取指定属性/图层的前一个或当前关键帧/标记。
参数:
property: (Property | Layer | string)? - 指定的属性/图层/图层名称。留空表示当前属性。
time: number? - 时间。留空表示当前时间。
返回值:number - 前一个或当前关键帧/标记。 如果在此之前且当前没有任何关键帧/标记,返回 null。
报错:若指定的属性没有关键帧/标记,则会报错。
获取指定属性/图层的后一个关键帧/标记。
参数和 getPreviousKey 一样,不赘述了。
返回值:number - 后一个关键帧/标记。 如果在此之后没有任何关键帧/标记,返回 null。
报错:若指定的属性没有关键帧/标记,则会报错。
注意获取前一个关键帧的函数包含当前关键帧,而获取后一个关键帧的函数不包含当前关键帧。 如果给定的参数是图层,则获取标记;如果给定的参数是属性,则获取关键帧。
应用普通的静态水平翻转效果时增加缩放进入效果的缩放高度值。
参数:
midiName: string? - om midi 图层名称。如果留空,则默认为当前图层名称前加上“[midi]”。以下不再赘述。
incremental: number= - 缩放进入增量。默认为 15。
exponential: number= - 缩放进入函数曲线指数。默认为 3(三次函数)。
返回值:number - 缩放高度值。
应用普通的静态水平翻转效果时增加缩放进入效果的缩放宽度值。
注意这个函数必须搭配“缩放高度” (rescaleHeight) 的函数一同使用。
参数:
midiName: string? - om midi 图层名称。
返回值:number - 缩放宽度值。
根据 MIDI 节奏从指定的开始值(可非线性)变化到结束值。
参数:
start: number - 开始值。
end: number - 结束值。
exponential: number= - 指数。
midiName: string? - om midi 图层名称。
返回值:number - 变化值。
自动根据文本对象的文本发生变化而生成动画。
参数:
centerValue: number - 中间值。必填。
startValue: number - 开始值。必填。
endValue: number? - 结束值。如果为空则由中间值和开始值间接求得。
beatDuration: number? - 过渡动画持续时间。如果为空则根据 Marker Conductor 生成的 BPM 空对象上的标记求得。
返回值:number - 当前时间的值。
展现对象的所有键名。用于调试。 这个函数的名称灵感来源于 Python 的 dir 函数。
参数:
object: object - 任意对象。
该函数不会返回值,而是直接报错:直接将结果报错显示到错误提示中。
像这样:

通过报错提示,我们就可以知道这个对象(例如图中演示的 thisLayer)到底有那些属性可以调整和使用了。
至此,所有表达式讲解完了,以后可能会增加新的函数。
只有一个:不要做音 MIDI!
在此非常感谢为该脚本和音 MAD / YTPMV 的事业做出贡献的所有人!
十分抱歉,前天我宣称一天之内发布该脚本,结果这篇文章写了三天才写完,也就是说写完才发布了脚本。感谢您能阅读到这里。