Exit
  • Global community
    • Language:
      • Deutsch
      • English
      • Español
      • Français
      • Português
  • 日本語コミュニティ
  • 한국 커뮤니티
0

Artboards to AVIF script

Community Expert ,
Aug 28, 2025 Aug 28, 2025

I have created an "Artboards to AVIF" script, based on my "Artboards to WebP" script.

 

Key Features:
* Only for Photoshop 2025 (v26.x.x) or later
* Export artboards as AVIF with lossy or lossless compression
* Adjustable quality slider for lossy AVIF
* Optional JPEG save with quality level dropdown
* Resize artboards by % with filename suffix (e.g. "_200")
* Filenames cleaned: spaces converted to web-friendly hyphens
* Artboard content trimmed to artboard bounds
* Metadata toggle (XMP, CRS, ancestors)
* ICC profile embedded, with automatic conversion to sRGB 8-bit RGB if required
* Option to overwrite existing files or add a timestamp suffix
* Output folder selection with option to open folder after export
 
Artboards-to-AVIF-Win.png
 
/*
Artboards-to-AVIF-PS2025-scriptUI-GUI-v1-0.jsx
Stephen Marsh
https://community.adobe.com/t5/photoshop-ecosystem-discussions/artboards-to-avif-script/m-p/15480083
v1.0 - 30th July 2025: Initial release

* Only for Photoshop 2025 (v26.x.x) or later!
* Saves artboards as AVIF with lossless/lossy quality options
* Resize artboard by % option, a filename suffix such as '_200' is added to indicate a 200% resize
* Filename word spaces (%20) are converted to web-friendly hyphens
* Artboard content is constrained to the artboard bounds
* Metadata is removed and the document ICC profile is embedded
* Optional JPEG save checkbox with quality level dropdown menu
* Option to overwrite existing files or to add a date-timestamp suffix '_YYYYMMDD-HHMMSS'
* Optionally convert RGB images to sRGB color profile, RGB color mode and 8 bpc (non-RGB images are automatically converted to sRGB 8 BPC)

Based on:
Artboards-to-WEBP-PS2025-scriptUI-GUI-v2-1.jsx
https://community.adobe.com/t5/photoshop-ecosystem-discussions/exporting-artboards-to-webp-format/td-p/12937135#U15431202
*/

#target photoshop

    (function () {

        try {

            app.bringToFront();

            var versionNumber = app.version.split(".");
            var versionCheck = parseInt(versionNumber);
            if (versionCheck < 26) {
                alert("You must use Photoshop 2025 or later to save using native AVIF format...");
                return;
            }

            if (app.documents.length === 0) {
                alert("Please open a document first!");
                return;
            }

            var doc = app.activeDocument;
            var layerSets = doc.layerSets;

            try {
                var docPath = app.activeDocument.path;
            } catch (e) {
                docPath = Folder("~/Desktop");
            }

            if (!hasArtboards()) {
                alert("No artboards found, script canceled!");
                return;
            }

            var exportSettings = {
                outputFolder: docPath,
                prefix: doc.name.replace(/\.[^\.]+$/, '').replace(/ /g, '-') + "_",
                quality: 50,
                isLossy: true,
                overwrite: true,
                openFolder: true,
                enableResize: false,
                resizeWidth: 200,
                scaleStyles: true,
                constrainProportions: true,
                jpegQuality: 9,
                saveJPEG: true
            };

            var dlg = new Window("dialog", "Export Artboards to AVIF (v1.0)");
            dlg.orientation = "column";
            dlg.alignChildren = ["fill", "top"];
            dlg.spacing = 10;
            dlg.margins = 16;

            var settingsGroup = dlg.add("panel", undefined, "");
            settingsGroup.orientation = "column";
            settingsGroup.alignChildren = ["fill", "top"];
            settingsGroup.margins = 10;
            settingsGroup.spacing = 8;

            var folderGroup = settingsGroup.add("group");
            folderGroup.orientation = "column";
            folderGroup.alignChildren = ["fill", "top"];
            folderGroup.add("statictext", undefined, "Output folder:");
            var folderSubGroup = folderGroup.add("group");
            var browseBtn = folderSubGroup.add("button", undefined, "Browse...");
            var folderText = folderSubGroup.add("statictext", undefined, exportSettings.outputFolder ? decodeURI(exportSettings.outputFolder.fsName) : "None selected", { truncate: 'middle' });
            folderText.alignment = ["fill", "left"];
            browseBtn.onClick = function () {
                var folder = Folder.selectDialog("Select Output Folder");
                if (folder) {
                    exportSettings.outputFolder = folder;
                    folderText.text = decodeURI(folder.fsName);
                }
            };

            var prefixGroup = settingsGroup.add("group");
            prefixGroup.orientation = "column";
            prefixGroup.alignChildren = ["fill", "top"];
            prefixGroup.add("statictext", undefined, "Filename prefix:");
            var prefixInput = prefixGroup.add("edittext", undefined, exportSettings.prefix);
            prefixInput.characters = 30;

            var compGroup = settingsGroup.add("group");
            compGroup.orientation = "column";
            compGroup.alignChildren = ["fill", "top"];
            var radioGroup = compGroup.add("group");
            radioGroup.orientation = "row";
            radioGroup.add("statictext", undefined, "Compression:");
            var lossyRadio = radioGroup.add("radiobutton", undefined, "Lossy");
            var losslessRadio = radioGroup.add("radiobutton", undefined, "Lossless");
            lossyRadio.value = true;

            var qualityGroup = compGroup.add("group");
            qualityGroup.orientation = "row";
            qualityGroup.alignChildren = ["left", "center"];
            qualityGroup.add("statictext", undefined, "Image quality (0-100):");
            var qualitySlider = qualityGroup.add("slider", undefined, exportSettings.quality, 0, 100);
            qualitySlider.preferredSize.width = 150;
            var qualityValue = qualityGroup.add("statictext", undefined, exportSettings.quality.toString());
            qualitySlider.onChanging = function () {
                qualityValue.text = Math.round(qualitySlider.value).toString();
            };
            qualitySlider.onChange = function () {
                qualityValue.text = Math.round(qualitySlider.value).toString();
            };

            lossyRadio.onClick = function () {
                qualitySlider.enabled = true;
                qualityValue.enabled = true;
            };

            losslessRadio.onClick = function () {
                qualitySlider.enabled = false;
                qualityValue.enabled = false;
            };

            var resizeGroup = settingsGroup.add("group");
            resizeGroup.orientation = "column";
            resizeGroup.alignChildren = ["fill", "top"];
            var resizeCheck = resizeGroup.add("checkbox", undefined, "Resize artboards");
            resizeCheck.value = false;
            var resizeOptionsGroup = resizeGroup.add("group");
            resizeOptionsGroup.orientation = "row";
            resizeOptionsGroup.alignChildren = ["left", "center"];
            resizeOptionsGroup.enabled = false;
            resizeOptionsGroup.add("statictext", undefined, "Resize %:");
            var widthInput = resizeOptionsGroup.add("editnumber", undefined, exportSettings.resizeWidth.toString());
            widthInput.characters = 5;
            resizeCheck.onClick = function () {
                resizeOptionsGroup.enabled = resizeCheck.value;
            };

            var checkGroup = settingsGroup.add("group");
            checkGroup.orientation = "column";
            checkGroup.alignChildren = ["left", "top"];
            var convertRGBCheck = checkGroup.add("checkbox", undefined, "Convert to sRGB");
            convertRGBCheck.value = true;
            var overwriteCheck = checkGroup.add("checkbox", undefined, "Overwrite existing files");
            overwriteCheck.value = true;
            var openFolderCheck = checkGroup.add("checkbox", undefined, "Open folder after export");
            openFolderCheck.value = false;

            var jpegGroup = checkGroup.add("group");
            jpegGroup.orientation = "row";
            jpegGroup.alignChildren = ["left", "center"];
            var saveJPEGCheck = jpegGroup.add("checkbox", undefined, "Save JPEG copy");
            saveJPEGCheck.value = false;
            var jpegQualityLabel = jpegGroup.add("statictext", undefined, "Quality:");
            var jpegQualityDropdown = jpegGroup.add("dropdownlist", undefined, ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"]);
            jpegQualityDropdown.selection = 9;
            jpegQualityLabel.enabled = false;
            jpegQualityDropdown.enabled = false;
            saveJPEGCheck.onClick = function () {
                jpegQualityLabel.enabled = saveJPEGCheck.value;
                jpegQualityDropdown.enabled = saveJPEGCheck.value;
            };

            var btnGroup = dlg.add("group");
            btnGroup.alignment = "right";
            var cancelBtn = btnGroup.add("button", undefined, "Cancel");
            var okBtn = btnGroup.add("button", undefined, "OK");
            cancelBtn.onClick = function () { dlg.close(0); };
            okBtn.onClick = function () {
                if (!exportSettings.outputFolder) {
                    alert("Please select an output folder.");
                    return;
                }
                exportSettings.prefix = prefixInput.text;
                exportSettings.quality = Math.round(qualitySlider.value);
                exportSettings.isLossy = lossyRadio.value;
                exportSettings.overwrite = overwriteCheck.value;
                exportSettings.openFolder = openFolderCheck.value;
                exportSettings.enableResize = resizeCheck.value;
                exportSettings.resizeWidth = parseInt(widthInput.text) || 100;
                exportSettings.saveJPEG = saveJPEGCheck.value;
                if (saveJPEGCheck.value && jpegQualityDropdown.selection !== null) {
                    exportSettings.jpegQuality = parseInt(jpegQualityDropdown.selection.text);
                }
                exportSettings.convertRGB = convertRGBCheck.value;
                dlg.close(1);
            };

            if (dlg.show() !== 1) {
                app.beep();
                return;
            }

            app.togglePalettes();

            var progressWin = new Window("palette", "Processing Artboards", undefined, { closeButton: false });
            progressWin.orientation = "column";
            progressWin.alignChildren = ["fill", "top"];
            progressWin.spacing = 10;
            progressWin.margins = 16;
            var progressText = progressWin.add("statictext", undefined, "Starting...");
            var progressBar = progressWin.add("progressbar", undefined, 0, layerSets.length);
            progressBar.preferredSize = [300, 20];
            progressWin.show();

            var dupedDoc = null;
            var avifCounter = 0;
            var jpegCounter = 0;

            try {
                dupedDoc = doc.duplicate(doc.name.replace(/\.[^\.]+$/, '').replace(/ /g, '-'), false);
                app.activeDocument = dupedDoc;

                if (activeDocument.mode !== DocumentMode.RGB) {
                    activeDocument.convertProfile("sRGB IEC61966-2.1", Intent.RELATIVECOLORIMETRIC, true, false);
                    activeDocument.changeMode(ChangeMode.RGB);
                } else if (exportSettings.convertRGB) {
                    activeDocument.convertProfile("sRGB IEC61966-2.1", Intent.RELATIVECOLORIMETRIC, true, false);
                }
                activeDocument.bitsPerChannel = BitsPerChannelType.EIGHT;

                deleteDocumentAncestorsMetadata();
                removeCRSmeta();
                removeXMP();

                var dupedDoclayerSets = app.activeDocument.layerSets;

                for (var i = dupedDoclayerSets.length - 1; i >= 0; i--) {
                    var currentSet = dupedDoclayerSets[i];
                    dupedDoc.activeLayer = currentSet;

                    progressText.text = "Processing: " + currentSet.name + " (" + (avifCounter + 1) + " of " + layerSets.length + ")";
                    progressBar.value = avifCounter + 1;
                    app.refresh();

                    if (isArtboard() === true) {
                        dupeActiveLayer(currentSet.name, currentSet.name);
                        trimTransparency(true, true, true, true);

                        if (exportSettings.enableResize && exportSettings.resizeWidth !== 100) {
                            imageSize(exportSettings.resizeWidth, exportSettings.scaleStyles, exportSettings.constrainProportions);
                        }

                        var artboardName = exportSettings.prefix + app.activeDocument.activeLayer.name
                            .replace(/[:\/\\*\?\"\<\>\|\\r\\n. ]+/g, "-")
                            .replace(/-+$/, '')
                            .replace(/^-+/, '');

                        if (exportSettings.enableResize) {
                            artboardName += "_" + exportSettings.resizeWidth.toString();
                        }

                        var finalFileName = exportSettings.overwrite ? artboardName : artboardName + "_" + getTimestamp();

                        saveAsAVIF(finalFileName);
                        if (exportSettings.saveJPEG) {
                            saveAsJPEG(finalFileName);
                            jpegCounter++;
                        }
                        app.activeDocument.close(SaveOptions.DONOTSAVECHANGES);
                        avifCounter++;
                    }
                }
                dupedDoc.close(SaveOptions.DONOTSAVECHANGES);
            } catch (e) {
                alert("Unexpected error during processing:\n" + e.message + "\nLine: " + e.line);
            } finally {
                try {
                    if (dupedDoc && app.documents.length && app.documents.indexOf(dupedDoc) !== -1) {
                        dupedDoc.close(SaveOptions.DONOTSAVECHANGES);
                    }
                } catch (e) { }
                app.bringToFront();
                progressWin.close();
                app.togglePalettes();
            }

            app.beep();
            alert((avifCounter + jpegCounter) + ' files saved to: ' + '\r' + exportSettings.outputFolder.fsName);

            if (exportSettings.openFolder) {
                exportSettings.outputFolder.execute();
            }


            ////// FUNCTIONS //////

            function imageSize(width, scaleStyles, constrainProportions) {
                var s2t = function (s) { return app.stringIDToTypeID(s); };
                var descriptor = new ActionDescriptor();
                descriptor.putUnitDouble(s2t("width"), s2t("percentUnit"), width);
                descriptor.putBoolean(s2t("scaleStyles"), scaleStyles);
                descriptor.putBoolean(s2t("constrainProportions"), constrainProportions);
                executeAction(s2t("imageSize"), descriptor, DialogModes.NO);
            }

            function hasArtboards() {
                for (var i = 0; i < activeDocument.layerSets.length; i++) {
                    activeDocument.activeLayer = activeDocument.layerSets[i];
                    var r = new ActionReference();
                    r.putEnumerated(stringIDToTypeID('layer'), stringIDToTypeID('ordinal'), stringIDToTypeID('targetEnum'));
                    var options = executeActionGet(r);
                    if (options.hasKey(stringIDToTypeID('artboard'))) return true;
                }
                return false;
            }

            function isArtboard() {
                try {
                    var r = new ActionReference();
                    r.putEnumerated(stringIDToTypeID('layer'), stringIDToTypeID('ordinal'), stringIDToTypeID('targetEnum'));
                    var options = executeActionGet(r);
                    return options.hasKey(stringIDToTypeID('artboard'));
                } catch (e) {
                    alert("Error:\n" + e.message + "\nLine: " + e.line);
                }
            }

            function dupeActiveLayer(docName, layerName) {
                try {
                    var s2t = function (s) { return stringIDToTypeID(s); };
                    var descriptor = new ActionDescriptor();
                    var reference = new ActionReference();
                    var reference2 = new ActionReference();
                    reference.putClass(s2t("document"));
                    descriptor.putReference(charIDToTypeID("null"), reference);
                    descriptor.putString(s2t("name"), docName);
                    reference2.putEnumerated(s2t("layer"), s2t("ordinal"), s2t("targetEnum"));
                    descriptor.putReference(s2t("using"), reference2);
                    descriptor.putString(s2t("layerName"), layerName);
                    executeAction(s2t("make"), descriptor, DialogModes.NO);
                } catch (e) {
                    alert("Error:\n" + e.message + "\nLine: " + e.line);
                }
            }

            function trimTransparency(top, bottom, left, right) {
                try {
                    var c2t = function (s) { return charIDToTypeID(s); };
                    var s2t = function (s) { return stringIDToTypeID(s); };
                    var descriptor = new ActionDescriptor();
                    descriptor.putEnumerated(s2t("trimBasedOn"), s2t("trimBasedOn"), c2t("Trns"));
                    descriptor.putBoolean(s2t("top"), top);
                    descriptor.putBoolean(s2t("bottom"), bottom);
                    descriptor.putBoolean(s2t("left"), left);
                    descriptor.putBoolean(s2t("right"), right);
                    executeAction(s2t("trim"), descriptor, DialogModes.NO);
                } catch (e) {
                    alert("Error:\n" + e.message + "\nLine: " + e.line);
                }
            }

            function removeCRSmeta() {
                try {
                    if (!documents.length) return;
                    if (ExternalObject.AdobeXMPScript === undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
                    var xmp = new XMPMeta(app.activeDocument.xmpMetadata.rawData);
                    XMPUtils.removeProperties(xmp, XMPConst.NS_CAMERA_RAW, "", XMPConst.REMOVE_ALL_PROPERTIES);
                    app.activeDocument.xmpMetadata.rawData = xmp.serialize();
                } catch (e) {
                    alert("Error:\n" + e.message + "\nLine: " + e.line);
                }
            }

            function deleteDocumentAncestorsMetadata() {
                try {
                    if (!documents.length) return;
                    if (ExternalObject.AdobeXMPScript === undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
                    var xmp = new XMPMeta(activeDocument.xmpMetadata.rawData);
                    xmp.deleteProperty(XMPConst.NS_PHOTOSHOP, "DocumentAncestors");
                    app.activeDocument.xmpMetadata.rawData = xmp.serialize();
                } catch (e) {
                    alert("Error:\n" + e.message + "\nLine: " + e.line);
                }
            }

            function removeXMP() {
                if (!documents.length) return;
                if (ExternalObject.AdobeXMPScript === undefined) ExternalObject.AdobeXMPScript = new ExternalObject("lib:AdobeXMPScript");
                var xmp = new XMPMeta(activeDocument.xmpMetadata.rawData);
                XMPUtils.removeProperties(xmp, "", "", XMPConst.REMOVE_ALL_PROPERTIES);
                app.activeDocument.xmpMetadata.rawData = xmp.serialize();
            }

            function saveAsAVIF(saveName) {
                try {
                    var s2t = function (s) { return stringIDToTypeID(s); };
                    var descSave = new ActionDescriptor();
                    var descAVIFOptions = new ActionDescriptor();
                    var idAVIFCompression = s2t("AVIFCompression");
                    if (exportSettings.isLossy) {
                        descAVIFOptions.putEnumerated(s2t("colorCompression"), idAVIFCompression, s2t("compressionLossy"));
                        descAVIFOptions.putInteger(s2t("colorQuality"), exportSettings.quality);
                    } else {
                        descAVIFOptions.putEnumerated(s2t("colorCompression"), idAVIFCompression, s2t("compressionLossless"));
                    }
                    descAVIFOptions.putEnumerated(s2t("alphaCompression"), idAVIFCompression, s2t("compressionLossless"));
                    descAVIFOptions.putEnumerated(s2t("colorFormat"), s2t("AVIFColorFormat"), s2t("AVIFFormat422")); // Options: AVIFFormat444, AVIFFormat422, AVIFFormat420
                    descAVIFOptions.putEnumerated(s2t("sampleDepth"), s2t("AVIFSampleDepth"), s2t("AVIFDepth12bit"));
                    descAVIFOptions.putInteger(s2t("encoderSpeed"), 6); // Options: 2 (slowest/smallest), 4, 6, 8, 10 (fastest/largest)
                    descAVIFOptions.putBoolean(s2t("includeXMPData"), false);
                    descAVIFOptions.putBoolean(s2t("includeEXIFData"), false);
                    descAVIFOptions.putBoolean(s2t("includePsExtras"), false);
                    descSave.putObject(s2t("as"), s2t("AVIFFormat"), descAVIFOptions);
                    descSave.putPath(s2t("in"), new File(exportSettings.outputFolder + '/' + saveName + '.avif'));
                    descSave.putBoolean(s2t("lowerCase"), true);
                    descSave.putEnumerated(s2t("saveStage"), s2t("saveStageType"), s2t("saveSucceeded"));
                    executeAction(s2t("save"), descSave, DialogModes.NO);
                } catch (e) {
                    alert("Error saving AVIF:\n" + e.message + "\nLine: " + e.line);
                }
            }

            function saveAsJPEG(_name) {
                var jpgOptns = new JPEGSaveOptions();
                jpgOptns.formatOptions = FormatOptions.STANDARDBASELINE;
                jpgOptns.embedColorProfile = true;
                jpgOptns.matte = MatteType.NONE;
                jpgOptns.quality = exportSettings.jpegQuality || 9;
                activeDocument.saveAs(new File(exportSettings.outputFolder + '/' + _name + '.jpg'), jpgOptns, true, Extension.LOWERCASE);
            }

            function getTimestamp() {
                var now = new Date();
                return now.getFullYear().toString() +
                    ("0" + (now.getMonth() + 1)).slice(-2) +
                    ("0" + now.getDate()).slice(-2) + "-" +
                    ("0" + now.getHours()).slice(-2) +
                    ("0" + now.getMinutes()).slice(-2) +
                    ("0" + now.getSeconds()).slice(-2);
            }

        } catch (e) {
            alert("Error:\n" + e.message + "\nLine: " + e.line);
        }

    })();

 

https://prepression.blogspot.com/2017/11/downloading-and-installing-adobe-scripts.html

 

TOPICS
Actions and scripting , macOS , Windows
94
Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Adobe
Community Expert ,
Sep 01, 2025 Sep 01, 2025

@Stephen Marsh nice job! 

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines
Community Expert ,
Sep 01, 2025 Sep 01, 2025
LATEST

@creative explorer - thank you!

Translate
Report
Community guidelines
Be kind and respectful, give credit to the original source of content, and search for duplicates before posting. Learn more
community guidelines