Amazonで商品を見るセール会場へ

After Effects│チェックボックスを切り替えて複数レンダリングするスクリプト

目次

空のキューと出力予定を確認して2状態を書き出す練習

2026年10月3日確認:最初はDRY_RUN = trueで出力予定だけを表示します。

所有の練習コピーでPracticeSwitchコンポにヌルCtrlを置き、チェックボックス制御のエフェクト名をToggleにします。

チェックはキー・式のない0/1にし、元の状態を記録してください。

1秒程度のPracticeRenderコンポに色付きソリッドを置き、不透明度へ下の式を設定します。

チェックOFFで0、ONで100になることを手動で確認してから書き出しへ進みます。

練習用のレンダリング項目で設定を確認し、レンダリング設定をPractice Render、MOVを出力する出力モジュール設定をPractice MOVという名前で保存します。

テンプレート保存に使った練習項目をキューから外し、既存の本番項目を含めず空のキューで試してください。

下のコードをrender-toggle.jsxとしてUTF-8で保存し、プロジェクトパネルでPracticeRenderだけを選択して実行します。

出力先には既存の空フォルダを選び、OFF.movとON.movの2つの予定、選択数、テンプレート名を確認します。

初期状態ではチェック変更・キュー追加・レンダリングを行いません。

所有の練習コピーで設定を確認した後、DRY_RUN = falseへ変更して実行する手順です。

OFFの処理完了を待ち、完了状態を確認してからONを開始します。

2つの状態を同時にキューへ積むと、共通チェックの値を最後の状態で評価するため、順番を分けます。

既存項目があるキュー、複数の同名制御、キーや式のあるチェック、空でないフォルダ、同名出力がある場合は開始しません。

テンプレート不在・途中停止・レンダリングエラーの場合は次の状態へ進まず、作ったキュー項目だけを外し、元のチェック値へ戻す処理を試みます。

復元自体が失敗した場合はその内容を表示するので、元の値と空キューを手動で照合してください。

出力ファイルには連番を付け、日本語などのコンポ名はファイル名部分をアンダースコアへ置き換えます。

テンプレートをMOV以外にした場合の拡張子変更や連番画像の出力には、この例をそのまま使わないでください。

書き出された映像や途中のファイルはCtrl+Zでは消えません。

OFF/ONの映像内容、ファイルの再生、元のチェック状態、キューを確認し、途中ファイルは確認用に残してください。

コードはJavaScriptの構文・模擬APIと保存したAPI資料で確認していますが、AE本体での適用・映像の一致・Undoの実行確認は未完了です。

入力・条件操作・結果確認する点
DRY_RUN = true予定表示のみチェック・キューを変更しない
DRY_RUN = falseOFF完了後にON既存キューは拒否
途中失敗・復元次の状態へ進まない元のチェックとキューを照合

仕様の照合には、コミュニティで保守されているRenderQueue API参照、RenderQueueItem API参照、OutputModule API参照を参照しました。

2026年10月3日:出力予定の確認、空キュー、OFF完了後のON実行、元のチェック状態への復元を含む例へ改修しました。

チェックボックス制御の切り替えに合わせて複数パターンをレンダリングする方法をまとめました。

スクリプトでチェック状態を切り替えながら、レンダリングキューの処理を自動化します。

例えば、チェックボックス制御で切り替えたいレイヤーの不透明度に、下記のエクスプレッションを設定します。

comp("PracticeSwitch").layer("Ctrl").effect("Toggle")(1) == 1 ? 100 : 0;

これでチェックボックスのオン・オフに応じて表示を切り替えられます。

手動で切り替えずに2パターンの書き出しを一括で実行するため、スクリプトを作成しました。

チェックボックスを切り替えて2通りレンダリングするスクリプト

(function () {
    var DRY_RUN = true; // First check the plan. Set false only in your practice copy.
    var RENDER_TEMPLATE = "Practice Render", OUTPUT_TEMPLATE = "Practice MOV";
    var project = app.project;
    if (!project) { alert("Open a practice project."); return; }
    var queue = project.renderQueue, comps = [], files = [], created = [], i, j;
    if (queue.rendering || queue.numItems !== 0) { alert("Use an empty, idle render queue."); return; }
    if (!project.selection.length || project.selection.length > 5) { alert("Select 1 to 5 compositions in the Project panel."); return; }
    for (i = 0; i < project.selection.length; i++) {
        if (!(project.selection[i] instanceof CompItem)) { alert("Select compositions only."); return; }
        comps.push(project.selection[i]);
    }
    var controlComp = null, controlLayer = null, effect = null, matches = 0;
    for (i = 1; i <= project.numItems; i++) {
        var item = project.item(i);
        if (item instanceof CompItem && item.name === "PracticeSwitch") { controlComp = item; matches++; }
    }
    if (matches !== 1) { alert("Use exactly one PracticeSwitch comp."); return; }
    matches = 0;
    for (i = 1; i <= controlComp.numLayers; i++) {
        if (controlComp.layer(i).name === "Ctrl") { controlLayer = controlComp.layer(i); matches++; }
    }
    if (matches !== 1 || controlLayer.locked) { alert("Use one unlocked Ctrl layer."); return; }
    var effects = controlLayer.property("ADBE Effect Parade"); matches = 0;
    if (effects) {
        for (i = 1; i <= effects.numProperties; i++) {
            if (effects.property(i).name === "Toggle") { effect = effects.property(i); matches++; }
        }
    }
    if (matches !== 1 || effect.matchName !== "ADBE Checkbox Control") { alert("Use one Toggle Checkbox Control."); return; }
    var checkbox = effect.property("ADBE Checkbox Control-0001");
    if (!checkbox || checkbox.numKeys !== 0 || checkbox.expression !== "" || (checkbox.value !== 0 && checkbox.value !== 1)) {
        alert("Use a static 0/1 checkbox without an expression."); return;
    }
    var folder = Folder.selectDialog("Choose an existing empty practice output folder");
    if (!folder) { return; }
    if (!folder.exists || folder.getFiles().length !== 0) { alert("Choose an empty folder."); return; }
    var plan = [];
    for (i = 0; i < comps.length; i++) {
        var stem = (i + 1) + "_" + comps[i].name.replace(/[^A-Za-z0-9_-]/g, "_");
        files[i] = [new File(folder.fsName + "/" + stem + "_OFF.mov"), new File(folder.fsName + "/" + stem + "_ON.mov")];
        for (j = 0; j < 2; j++) {
            if (files[i][j].exists) { alert("Output already exists."); return; }
            plan.push(files[i][j].fsName);
        }
    }
    if (DRY_RUN) {
        alert("Plan only: no checkbox change, queue addition or render.\nTemplates: " + RENDER_TEMPLATE + " / " + OUTPUT_TEMPLATE + "\n" + plan.join("\n")); return;
    }
    if (queue.rendering || queue.numItems !== 0) { alert("Queue changed. Stop and review."); return; }
    var original = checkbox.value, cleanupErrors = [], completed = 0;
    function contains(values, target) {
        for (var k = 0; k < values.length; k++) { if (values[k] === target) { return true; } }
        return false;
    }
    function removeCreated() {
        for (var k = created.length - 1; k >= 0; k--) {
            try { created[k].remove(); } catch (error) { cleanupErrors.push(error.toString()); }
        }
        created = [];
    }
    try {
        for (j = 0; j < 2; j++) {
            checkbox.setValue(j);
            for (i = 0; i < comps.length; i++) {
                if (files[i][j].exists) { throw new Error("Output appeared; refusing overwrite."); }
                var rq = queue.items.add(comps[i]); created.push(rq);
                var om = rq.outputModule(1);
                if (!contains(rq.templates, RENDER_TEMPLATE) || !contains(om.templates, OUTPUT_TEMPLATE)) {
                    throw new Error("Save the named render and MOV output templates first.");
                }
                rq.applyTemplate(RENDER_TEMPLATE); om.applyTemplate(OUTPUT_TEMPLATE);
                om = rq.outputModule(1); om.file = files[i][j]; rq.render = true;
            }
            // render() returns after the queue finishes. Do not queue both states together.
            queue.render();
            for (i = 0; i < created.length; i++) {
                if (created[i].status !== RQItemStatus.DONE) { throw new Error("Render stopped or failed; do not start the next state."); }
            }
            completed++; removeCreated();
            if (cleanupErrors.length) { throw new Error("Queue cleanup failed; inspect the queue."); }
        }
    } catch (error) { alert("Stopped: " + error.toString() + "\nInspect and keep any partial practice output."); }
    finally {
        try { checkbox.setValue(original); } catch (error) { cleanupErrors.push("Checkbox restore: " + error.toString()); }
        removeCreated();
        if (cleanupErrors.length) { alert("Manual restoration needed:\n" + cleanupErrors.join("\n")); }
    }
    alert("Completed states: " + completed + " of 2. Check both files and the restored checkbox. Rendered files cannot be undone with Ctrl+Z.");
})();

参考:http://compojigoku.blog.fc2.com/blog-entry-18.html

After Effectsのほかの操作は、まとめからご覧いただけます。

旧実装の参考コードは、GitHubのMOTOKI-LLC/cg-method-codeにもまとめています。

レンダリングや書き出しを速くする方法は、ほかにもまとめています。

次に学ぶ・作業環境を選ぶ

学習を続けたい方や、作業環境を整えたい方は、目的に合うガイドをご覧ください。

After Effectsのおすすめ書籍

必要なPCスペック

周辺機器の優先度

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次