meiliyitian 发表于 2024-9-6 18:22

Adobe After Effects 2020自动裁剪气口的脚本

本帖最后由 meiliyitian 于 2024-9-10 09:24 编辑

一个在Adobe After Effects 2020中自动裁剪气口的脚本。

由于AI配音中间的气口经常(可以说99%)对应不上画面,每次都是手动裁剪分段,短的只有一两句还好,稍微长一点就麻烦死了。利用GPT写了一个自动裁剪气口的脚本。
解压密码:52pj

功能:
1、按照设定自动在气口处裁剪;
2、裁剪时按照设定直接全部+XXdb。
使用方法:
1、首先选中需要裁剪的图层右键-关键帧辅助-将音频转换为关键帧;
2、同时选中需要裁剪的图层和生成的音频振幅图层;
3、点击脚本运行按钮。

源代码如下:
function showUI() {
    // 创建一个窗口
    var win = new Window("palette", "气口自动裁剪", undefined);
    win.orientation = "column";

    // 静音阈值输入
    var silenceGroup = win.add("group");
    silenceGroup.add("statictext", undefined, "静音阈值 (默认为1):");
    var silenceInput = silenceGroup.add("edittext", undefined, "1");
    silenceInput.characters = 5;

    // 气口间隔输入
    var intervalGroup = win.add("group");
    intervalGroup.add("statictext", undefined, "气口最小间隔 (数值内的气口不切割):");
    var intervalInput = intervalGroup.add("edittext", undefined, "0.3");
    intervalInput.characters = 5;

    // 音频增益输入
    var gainGroup = win.add("group");
    gainGroup.add("statictext", undefined, "音频增益 (加多少音量):");
    var gainInput = gainGroup.add("edittext", undefined, "0");
    gainInput.characters = 5;

    // 按钮
    var runButton = win.add("button", undefined, "运行");
    runButton.onClick = function() {
      var silenceThreshold = parseFloat(silenceInput.text);
      var minInterval = parseFloat(intervalInput.text);
      var gainValue = parseFloat(gainInput.text);

      if (isNaN(silenceThreshold) || isNaN(minInterval) || isNaN(gainValue)) {
            alert("请确保输入正确的数值!");
            return;
      }

      splitAudioByAmplitude(silenceThreshold, minInterval, gainValue);
      // 运行后不关闭窗口
      // win.close(); // 不调用关闭函数
    };

    win.center();
    win.show();
}

function splitAudioByAmplitude(silenceThreshold, minInterval, gainValue) {
    // 确保用户选择了合成
    if (app.project.activeItem == null || !(app.project.activeItem instanceof CompItem)) {
      alert("请先选择一个合成!");
      return;
    }

    var comp = app.project.activeItem; // 当前合成
    var layers = comp.selectedLayers;// 获取选中的图层

    if (layers.length < 2) {
      alert("请确保选中了音频图层和生成的音频振幅图层!");
      return;
    }

    app.beginUndoGroup("Split Audio by Amplitude");

    var audioLayer = null;
    var audioAmplitudeLayer = null;

    // 遍历选中的图层,识别音频图层和音频振幅图层
    for (var i = 0; i < layers.length; i++) {
      var layer = layers;

      // 使用图层名称区分振幅图层和音频图层
      if (layer.name.toLowerCase().indexOf("音频振幅") !== -1) {
            audioAmplitudeLayer = layer; // 这是音频振幅层
      } else {
            audioLayer = layer; // 这是音频图层
      }
    }

    // 确保音频图层和振幅图层都被选中
    if (audioLayer == null || audioAmplitudeLayer == null) {
      alert("请确保同时选中了音频图层和音频振幅图层!");
      return;
    }

    // 获取音频振幅的滑块属性
    var audioAmplitude = audioAmplitudeLayer.property("Effects").property("两个通道").property("滑块");

    if (!audioAmplitude || audioAmplitude.numKeys === 0) {
      alert("音频振幅层中没有找到关键帧!");
      return;
    }

    var cutPoints = [];
    var keepSections = [];

    // 遍历所有振幅关键帧,找到小于阈值的振幅,记录其时间点
    for (var j = 1; j <= audioAmplitude.numKeys; j++) {
      var keyValue = audioAmplitude.keyValue(j);
      var keyTime = audioAmplitude.keyTime(j);

      // 记录需要保留的片段的起始点和结束点
      if (keyValue >= silenceThreshold) {
            if (keepSections.length === 0 || keepSections.end != null) {
                keepSections.push({ start: keyTime, end: null });
            }
      } else if (keepSections.length > 0 && keepSections.end == null) {
            keepSections.end = keyTime;
      }
    }

    // 如果最后一个片段没有结束时间,设置为图层的 outPoint
    if (keepSections.length > 0 && keepSections.end == null) {
      keepSections.end = audioLayer.outPoint;
    }

    // 检查相邻气口之间的间隔是否小于 minInterval 秒
    var finalSections = [];

    for (var i = 0; i < keepSections.length; i++) {
      var currentSection = keepSections;
      if (i === 0 || currentSection.start - keepSections.end > minInterval) {
            finalSections.push(currentSection);
      } else {
            // 合并两个片段
            finalSections.end = currentSection.end;
      }
    }

    var newLayers = [];

    // 根据最终保留的片段进行裁剪
    for (var k = 0; k < finalSections.length; k++) {
      var section = finalSections;
      
      // 分割片段
      if (section.start > audioLayer.inPoint && section.end < audioLayer.outPoint) {
            // 复制图层,保留这个片段
            var newLayer = audioLayer.duplicate();
            newLayer.inPoint = section.start;
            newLayer.outPoint = section.end;
            newLayers.push(newLayer);

            // 增加音频增益
            var audioLevels = newLayer.property("Audio").property("Audio Levels");
            audioLevels.setValue();
      }
    }

    // 删除原始图层
    audioLayer.remove();

    // 选中所有新生成的图层
    for (var i = 0; i < newLayers.length; i++) {
      newLayers.selected = true;
    }

    app.endUndoGroup();
}

// 显示UI
showUI();


运行截图:
https://free2.yunpng.top/2024/09/06/66dad70002979.png
https://free2.yunpng.top/2024/09/06/66dad70004e69.png

但是现在还是有点麻烦,不知道有没有大佬解决一下【选中需要裁剪的图层右键-关键帧辅助-将音频转换为关键帧】这一步。




24.9.10更新V4.0,更新内容:
1、窗口可停靠在AE界面;
2、优化裁剪逻辑,在裁剪位置会往前往后加一帧,避免因为裁剪阈值导致的音频断掉;
3、裁剪完成后自动删除音频振幅;
4、裁剪后备份一份原音频(不可见且关闭声音);
5、裁剪后的图层进行重命名;






ahsldhy 发表于 2024-9-7 22:58

meiliyitian 发表于 2024-9-7 20:51
就还是得去AE里面按照分割号再裁切吗

你的目的是裁切完事气口 还要按照打标一键切割吗,用门限的话,原本的气口位置会是空白,你如果需要对照视频,得把视频也拖进去,对照好了再导出来

meiliyitian 发表于 2024-9-8 00:21

ahsldhy 发表于 2024-9-7 22:58
你的目的是裁切完事气口 还要按照打标一键切割吗,用门限的话,原本的气口位置会是空白,你如果需要对照 ...

那这个还是会比较麻烦,因为视频音频随时都可能会调整。而且要是效果加的多了导出很慢,要是再多一个步骤导出的时候去掉效果更麻烦

zy19970 发表于 2024-9-6 19:38

不知道是不是我的浏览器出了故障,源代码并没有出现在合适的位置

tek2y 发表于 2024-9-6 22:29

看起来好像很厉害的样子

ahsldhy 发表于 2024-9-7 00:06

很牛逼的东西
但是你把音频拉倒AU里面,用门限 把气口限制掉不就好了

changshin 发表于 2024-9-7 08:03

这个比较喜欢!!!

meiliyitian 发表于 2024-9-7 09:53

ahsldhy 发表于 2024-9-7 00:06
很牛逼的东西
但是你把音频拉倒AU里面,用门限 把气口限制掉不就好了

然后还得导回来?没用过这个方法,如果AU里面分割好段的配音能直接导在AE里面也不错

ydafu168 发表于 2024-9-7 13:06

都是厉害人啊

ahsldhy 发表于 2024-9-7 16:39

meiliyitian 发表于 2024-9-7 09:53
然后还得导回来?没用过这个方法,如果AU里面分割好段的配音能直接导在AE里面也不错

分割号 你保存成mp3或者wav格式 不就好了

meiliyitian 发表于 2024-9-7 20:51

ahsldhy 发表于 2024-9-7 16:39
分割号 你保存成mp3或者wav格式 不就好了

就还是得去AE里面按照分割号再裁切吗
页: [1] 2
查看完整版本: Adobe After Effects 2020自动裁剪气口的脚本