Hands-Free AI Video: How I Connected Google Sheets and Luma via Make.com
Navigating API Quirks and Conditional JSON Payloads
The rise of AI video generation tools like Luma Labs is incredibly exciting, opening up new possibilities for creators. However, manually generating clips, especially for ongoing projects, can quickly become time-consuming. As part of refining my automated workflows (and for my creative project, HenceStories!), I set out to build a system that could trigger Luma video generations directly from a simple Google Sheet, using Make.com as the automation platform. The goal? A truly "hands-free" video pipeline.
The Dream Workflow
The plan seemed straightforward enough:
Add details for a new video job (like prompts, image URLs, settings) to a row in a Google Sheet and mark its status as "Ready".
Have Make.com detect this "Ready" row.
Make.com calls the Luma Labs API with the details from the sheet.
Luma does its magic and generates the video.
Luma sends a notification (webhook) back to Make.com when the job is complete.
Make.com receives this notification, grabs the video URL, and updates the original Google Sheet row with the URL and a "Completed" status. (Optionally, it could also save the video file to cloud storage like Dropbox).
This setup would allow me to queue up multiple video jobs just by filling out a spreadsheet – pretty neat!
The API Curveball: Handling Optional Inputs
Connecting Google Sheets and setting up the basic Make.com scenarios (one to "Call" Luma, one to "Receive" the callback) went smoothly. However, I soon hit an unexpected hurdle when constructing the actual API request to Luma.
The Luma API allows for generating video from a text prompt, a starting image (frame0
), an ending image (frame1
), or both images. These image inputs are nested within a keyframes
object in the JSON payload sent to the API.
The challenge? If you only provide one image (or none), the API doesn't just want an empty string for the missing image URL. It requires the entire key for the missing frame (e.g., "frame1": {...}
) or potentially even the parent keyframes
object itself to be completely omitted from the JSON request. Sending incorrect structures, like frame1: {}
or frame1: { "url": "" }
, results in an error. This kind of strictness is fairly common with APIs, requiring careful payload construction.
Navigating Make.com's Visual Logic
My first instinct was to use Make.com's built-in functions. Functions like ifempty(variable, ignore)
worked perfectly for top-level optional fields, like the main text prompt. If the prompt cell in my Google Sheet was empty, ignore
would correctly remove the prompt
key from the final JSON.
However, applying this logic to nested objects like frame0
or frame1
within keyframes
proved trickier within the visual interface. Trying to ignore just the url
inside frame0
would leave an empty frame0: {}
object, which the API rejected. I needed a way to conditionally remove the entire frame0
or frame1
object, or the keyframes
object altogether, based on the input data from the Google Sheet.
The Router Workaround
After some experimentation, the most reliable solution within Make.com's visual builder involved using the Router module. Here’s how it works in my "Luma Caller" scenario:
The scenario triggers and finds "Ready" rows in Google Sheets.
It iterates through each job.
Initial Validation: A first router checks if essential data (like model, aspect ratio) is present.
Status Update: The Google Sheet row is updated to "Processing".
The Core Logic (Router): A second Router module checks the input columns for the
First Frame (C)
andLast Frame (D)
image URLs from the Google Sheet.Path 1: If only
First Frame (C)
has a URL, it proceeds down a path with an HTTP module configured only with the JSON structure forframe0
.Path 2: If only
Last Frame (D)
has a URL, it uses a different HTTP module configured only forframe1
.Path 3 (Fallback): If both
C
andD
have URLs, it uses a third HTTP module configured for bothframe0
andframe1
.
API Call & Update: The appropriate HTTP module calls the Luma API. On success, another Google Sheets module updates the row to "Generating" and stores the Luma Job ID.
Here's a look at that part of the Make.com scenario:
The Make.com 'Luma Caller' scenario flow. The crucial Router module branches the process based on input data (presence of first/last image frames), sending the job to one of three dedicated HTTP modules configured with the correct Luma API payload structure.
A separate "Luma Receiver" scenario listens for the webhook callback from Luma, filters for the "completed" status message, finds the matching row in the Google Sheet using the Job ID, and updates the status to "Completed", pasting in the final video URL.
Reflections and What's Next
This Router-based solution works reliably and achieves the goal: I can now trigger Luma video generations simply by adding rows to a Google Sheet. It's a functional hands-free pipeline!
From a Make.com perspective, the solution feels a bit repetitive, requiring separate, almost identical HTTP modules for each conditional path. I was genuinely surprised I couldn't find a more direct visual method to dynamically build or omit those nested JSON structures based on input variables. It works well, though I do wonder if the Make.com community has found more streamlined visual methods for handling such conditional nested structures.
This project was a valuable practical exercise, deepening my understanding of Make.com's capabilities, the practicalities of API integration, and the importance of carefully handling API requirements. It also highlighted the trade-offs between visual builders and code. For future projects involving more complex conditional logic, exploring platforms like n8n, which often integrate code modules more directly, might be worth comparing.
For now, I have a working automation that saves significant time and effort, demonstrating the practical power of tools like Make.com for streamlining creative and technical workflows.