What is your goal?
I’d like to automate the export process of our image editing. We use Lightroom Desktop (CC) to collaborate during culling and editing, and need to export final images sharpened differently for screen and print. Lightroom Desktop doesn’t let one chain several export runs. It doesn’t even allow to create user presets, which would make the process even a bit faster.
Hence I’m looking at others way to accomplish the final export. Ideally I could automate Lightroom Desktop externally and automate it that way. Alternatively I could hook up an external function to process the images.
Looked at ImageMagick which would probably be good, if I could get the images piped to it somehow. This would preferably be an external service, but I could also look at putting it to work on an own computer, perhaps.
Then I found the Image module in Make, but it doesn’t seem to do sharpening, and the image pixel size is too restrictive.
Are there any solutions with Make, or without, you could think of?
Files reside in Google Drive, and should be placed back in another Google Drive folder, in case that makes a difference.
Cheers,
Björn
What is the problem & what have you tried?
Looking for solution ideas
Error messages or input/output bundles
None
Hey Björn,
Add a google script to the google drive folder to watch for new files and have it call a Make webhook to trigger the scenario. Use the google drive download a file module and then send it to whichever image editor you picked. I know Cloudinary and Picsart have tools for image sharpening and are available in Make, but feel free to check and find whichever one suits your needs. There are a ton of image processing softwares available. It will then return the processed file that you can then upload to the new folder with the corresponding google drive module.
Thank you @Stoyan_Vatov. Didn’t know one could add this kind of “watcher” to Google Drive. I found this thread describing one implementation:
https://community.make.com/t/trigger-webhook-on-new-file-upload-on-google-drive/30600
Is this a good way, or is there a better way? If I read that correctly, it doesn’t actually watch for new files, but for changes in files.
This here would suggest one could watch also for new files, but from there it’s a long step to a script:
https://developers.google.com/workspace/drive/api/guides/push
Cheers,
Björn
Thanks @Aneeq_Iftikhar. Cloudinary sounds just right for this. Need to check for CMYK and ICC, which I don’t think is a problem here, special thanks for the flag.
Are those values real Lightroom equivalents for screen and matte/glossy paper print?
Now if I could only get Lightroom Desktop to export the original TIFFs somehow automatically also…
.
Cheers,
Björn
Yeah that one watches for updates, not file creations.
Here is something done quick and dirty to get you started:
const FOLDER_ID = 'YOUR_FOLDER_ID';
const WEBHOOK_URL = 'YOUR_MAKE_WEBHOOK_URL';
const LOCK_WAIT_MS = 30000;
function checkForNewFiles() {
const lock = LockService.getScriptLock();
if (!lock.tryLock(LOCK_WAIT_MS)) return;
try {
const props = PropertiesService.getScriptProperties();
const lastSeen = props.getProperty('lastSeenCreatedTime') || '1970-01-01T00:00:00.000Z';
const lastSeenIds = new Set(JSON.parse(props.getProperty('lastSeenIds') || '[]'));
const query =
`'${FOLDER_ID}' in parents and trashed = false and createdDate >= '${lastSeen}'`;
const files = DriveApp.searchFiles(query);
const candidates = [];
while (files.hasNext()) {
const file = files.next();
const created = file.getDateCreated().toISOString();
if (created === lastSeen && lastSeenIds.has(file.getId())) {
continue;
}
candidates.push(file);
}
candidates.sort((a, b) => {
const timeDifference =
a.getDateCreated().getTime() - b.getDateCreated().getTime();
if (timeDifference !== 0) {
return timeDifference;
}
return a.getId().localeCompare(b.getId());
});
let cursor = lastSeen;
let cursorIds = [...lastSeenIds];
for (const file of candidates) {
const fileId = file.getId();
const createdTime = file.getDateCreated().toISOString();
const payload = {
fileId: fileId,
name: file.getName(),
mimeType: file.getMimeType(),
url: file.getUrl(),
downloadUrl: `https://drive.google.com/uc?export=download&id=${fileId}`,
createdTime: createdTime
};
try {
const response = UrlFetchApp.fetch(WEBHOOK_URL, {
method: 'post',
contentType: 'application/json',
payload: JSON.stringify(payload),
muteHttpExceptions: true
});
const status = response.getResponseCode();
if (status >= 200 && status < 300) {
console.log(`Sent ${fileId} to Make`);
if (createdTime === cursor) {
cursorIds.push(fileId);
} else {
cursor = createdTime;
cursorIds = [fileId];
}
cursorIds = [...new Set(cursorIds)];
} else {
console.error(
`Webhook failed for ${fileId}: ${status} ${response.getContentText()}`
);
break;
}
} catch (error) {
console.error(`Webhook error for ${fileId}: ${error}`);
break;
}
}
props.setProperty('lastSeenCreatedTime', cursor);
props.setProperty('lastSeenIds', JSON.stringify(cursorIds));
} finally {
lock.releaseLock();
}
}
You need to add a time driven trigger and set it to run like every 15 mins or however fast you want the detection to be.
Thanks again @Aneeq_Iftikhar. I’ll test with sharpness settings and see what comes closest. Would you happen to know if Lightroom’s sharpness is the function only with different strengths, or would/could there be more going on?
Regarding export automation, are you sure you’re in Lightroom Desktop (cloud) and not Classic (standalone)? I know Classic can do a lot of stuff, including publishing and export plug-ins, but I cannot see anything similar in Desktop. Where should that be, sorry to be so detailed?
Cheers,
Björn
Thank you @Stoyan_Vatov. I’ll try to test this during the weekend. Not really ably to script, but can “read” code somewhat
.
Is there a switch in this script to include sub-folders recursively? We operate with client specific delivery folders and setting the script up only at that root folder would be the only maintainable way.
I today found that Make has instant polling (ACID?) for Google Drive folders. Is the point with the script to avoid Make’s credit usage if I’d like to poll each minute? Google has limits to all kinds of stuff, but not extra costs for transactions, as I’d remember. Yes?
Cheers,
Björn
No, it only checks the current folder, but sub folders can be added. I’m not at home right now, so I can’t update it.
About the Make module, yeah it’s a polling module. It won’t trigger when a file is added, but it will periodically check for new files. So it’s good if you want to check once a day for example, otherwise it just wastes credits. Especially if you set it to run every minute.
Also, Lightroom sharpness is Amount, Radius, Detail, and Masking. While Cloudinary is only one value, so it’s not a direct conversion and will require testing to get it right.
I’m getting an “Exception: Invalid argument: q” error when testing the script. Folder ID and webhook should be OK.
The error message says the problem is at row 22, which reads:
while (files.hasNext()) {
This seems to be a common place for errors, some googling told me. It seems the problem relates to the search query. I tried to look and modify that, but wasn’t able to figure it out:
const query =
\`'${FOLDER_ID}' in parents and trashed = false and createdDate >= '${lastSeen}'\`;
According to Google results missing spaces, wrong formatting, wrong use of title/name in the search etc seem common reasons. I couldn’t spot the problem here, unfortunately.
Would you see the reason?
I’m on European/Scandinavian keyboard, if that’s any connection.
Cheers,
Björn
Good catch, you’re right. That export hook is Classic-only, not the cloud Lightroom Desktop app. My bad for not being clearer there.
If you’re on cloud Lightroom, there’s no built-in export automation like Classic has. Simplest fix is exporting into a folder that syncs to your Drive-watched folder. Or run Classic just for exports, some people do that purely for the plugin support. Hope that helps.