Google Sheets 영상 자동화: Apps Script와 Sume
Apps Script 요청 한 번으로 시트 행 최대 100개를 Sume 영상 실행으로 바꾸고, 시간 기반 트리거로 큐를 폴링해 URL을 다시 시트에 쓰세요.

Google Sheets로 영상을 자동화하려면 Apps Script가 시트의 행을 대량 실행 하나로 묶어 Sume에 보내게 하세요. /v1/formats/{handle}/{slug}/bulk-runs에 UrlFetchApp.fetch POST를 한 번 보내면 최대 100개 행이 Format 실행으로 큐에 들어가고, 시간 기반 트리거가 큐를 폴링해 완성된 영상 URL을 각 행에 다시 씁니다.
Sume에는 Google Sheets 부가기능이 없습니다. 여러분의 스크립트에서 HTTPS로 직접 호출하는 방식입니다. Sume 관련 내용은 대량 실행과 실행과 결과 (영문) 문서에서, Apps Script 관련 내용은 Google 레퍼런스 페이지에서 가져왔으며 모두 2026-09-27에 확인했습니다. 요청 계약만 따로 보려면 Sume Format 대량 실행을 참고하세요.
Apps Script에서 시트를 Sume로 어떻게 보내나요?
API 키는 셀에도, 코드에도 넣지 마세요. 프로젝트 설정 페이지에서 스크립트 속성으로 추가하세요. 스크립트 속성은 스크립트의 모든 사용자가 공유하므로, 키를 가져도 되는 사람과만 프로젝트를 공유하세요. Sume 문서는 여기에 더해 키를 프론트엔드 JavaScript, 지원 티켓, 스크린샷에 절대 넣지 말라고 안내합니다.
아래 함수는 Videos 탭의 2행부터 101행까지(A열에 지시문, B열에 이미지 URL)를 읽어 큐 하나로 POST합니다. acme/product-promo는 여러분 Format의 handle과 slug를 대신하는 자리표시자입니다. Sume는 input의 필드 목록을 공개하지 않으므로, 여러분의 Format이 읽는 키를 보내세요.
Sume 쿡북은 시트 행 ↔ index 대응표를 직접 관리하라고 안내합니다. items[i].index는 제출한 위치이기 때문입니다. 이 코드는 모든 행을 순서대로 보내므로 행 번호는 항상 index + 2입니다. 행은 중간에 비는 곳 없이 이어지게 두세요. 범위 안의 빈 행도 항목으로 전송됩니다.
contentType: "application/json"을 보내세요. UrlFetchApp의 기본값은application/x-www-form-urlencoded입니다.muteHttpExceptions: true를 주면 상태 코드가 실패를 가리킬 때fetch가 예외를 던지지 않고 응답을 반환하므로, Sume의 오류 본문을 로그로 남길 수 있습니다.Idempotency-Key는 새 배치마다 올리는BATCH속성으로 만들어지므로, 바뀌지 않은 배치로submitSheet를 다시 실행하면 두 번째 큐를 시작하지 않고 기존 큐를202와 함께 돌려받습니다.- 이 스크립트는 한 번에 배치 하나만 추적합니다.
QUEUE_ID는 하나뿐이고,dropTrigger는 새 폴링 트리거를 설치하기 전에 이전 트리거를 제거합니다.
const API = "https://api.sume.com/v1";
const props = PropertiesService.getScriptProperties();
function submitSheet() {
const sheet = SpreadsheetApp.openById(props.getProperty("SHEET_ID")).getSheetByName("Videos");
const rows = sheet.getDataRange().getValues().slice(1, 101); // row 1 is the header
const items = rows.map((r) => ({ instruction: r[0], input: { url: r[1] } }));
const res = UrlFetchApp.fetch(API + "/formats/acme/product-promo/bulk-runs", {
method: "post",
contentType: "application/json",
headers: {
Authorization: "Bearer " + props.getProperty("SUME_API_KEY"),
"Idempotency-Key": "sheet-batch-" + props.getProperty("BATCH"),
},
payload: JSON.stringify({ concurrency: 4, items: items }),
muteHttpExceptions: true,
});
if (res.getResponseCode() !== 202) throw new Error(res.getContentText());
props.setProperty("QUEUE_ID", JSON.parse(res.getContentText()).data.id);
dropTrigger(); // a rerun must not leave a second polling trigger behind
const trigger = ScriptApp.newTrigger("pollQueue").timeBased().everyMinutes(5).create();
props.setProperty("TRIGGER_ID", trigger.getUniqueId());
}오래 실행되는 스크립트 없이 큐를 어떻게 폴링하나요?
submitSheet 안에서 기다리지 마세요. Google은 실행 한 번당 6분이 지나면 스크립트를 중지하고, Sume 문서에 따르면 Format이 영상을 만드는 경우 자식 실행 하나도 몇 분짜리 작업입니다. 그래서 submitSheet는 시간 기반 트리거를 설치하고, pollQueue는 트리거가 실행될 때마다 GET /v1/format-run-queues/{queue_id}를 읽습니다.
everyMinutes(n)은 1, 5, 10, 15, 30만 받습니다(ClockTriggerBuilder). Sume 문서는 큐를 매초 폴링해도 얻는 것은 없고 요청 한도만 소모한다고 설명합니다.- 큐의
completed는 모든 항목이 성공했다는 뜻이 아니라 모든 항목이 종료됐다는 뜻입니다. 실행이 실패한 행에는 URL 대신 항목 상태가 기록됩니다. 실패 이유는GET /v1/format-runs/{run_id}의 자식 실행 영수증에서 확인하세요. - 폴링 중의
429나503은 일시적이고 큐는 계속 동작하므로, 함수는 그대로 반환하고 다음 트리거 실행 때 다시 시도합니다. 그 밖의 오류는 예외를 던지므로 실패 알림 이메일로 여러분에게 전달됩니다. primary_output_url은 내구성 있는media.sume.comURL입니다. 만료되지 않고 URL을 가진 누구에게나 공개되므로, 시트를 읽을 수 있는 사람은 누구나 영상을 열 수 있습니다.
function pollQueue() {
const auth = { Authorization: "Bearer " + props.getProperty("SUME_API_KEY") };
const read = (path) => {
const res = UrlFetchApp.fetch(API + path, { headers: auth, muteHttpExceptions: true });
const code = res.getResponseCode();
if (code === 429 || code === 503) return undefined; // transient: try the next tick
if (code !== 200) throw new Error(res.getContentText()); // Apps Script emails the failure
return JSON.parse(res.getContentText()).data;
};
const queue = read("/format-run-queues/" + props.getProperty("QUEUE_ID"));
if (!queue || queue.status !== "completed") return; // a 429/503, or still running
const sheet = SpreadsheetApp.openById(props.getProperty("SHEET_ID")).getSheetByName("Videos");
for (const item of queue.items) {
const run = item.run_id ? read("/format-runs/" + item.run_id) : null;
if (run === undefined) return; // a 429/503: rewrite every row on the next tick
sheet.getRange(item.index + 2, 3).setValue((run && run.primary_output_url) || item.status);
}
dropTrigger(); // every row is written
}
function dropTrigger() {
for (const t of ScriptApp.getProjectTriggers()) {
if (t.getUniqueId() === props.getProperty("TRIGGER_ID")) ScriptApp.deleteTrigger(t);
}
}대신 Sume가 Apps Script 웹 앱을 호출하게 하면 안 되나요?
큐 자체에는 웹훅이 없고, 웹훅은 각 항목의 communication.webhook_url에만 있습니다. 이 URL을 Apps Script 웹 앱으로 지정할 수는 있지만, 콘텐츠 서비스가 반환하는 콘텐츠는 script.googleusercontent.com의 일회용 URL로 리다이렉트됩니다. Sume는 리다이렉트를 따라가지 않으며 3xx를 실패한 전달 시도로 셉니다.
폴링하는 트리거에는 공개 엔드포인트가 필요 없으므로, Apps Script만으로 동작하는 패턴은 이쪽입니다. 실행별 웹훅이 필요하다면 Sume Format 실행 수명주기에서처럼 Apps Script 밖에서 수신기를 운영하세요.
양쪽에는 각각 어떤 한도가 있나요?
Google 할당량은 사용자별로 적용되고 첫 요청 후 24시간이 지나면 초기화됩니다. 또한 설치 가능한 트리거는 항상 그 트리거를 만든 사람의 계정으로 실행됩니다.
- 트리거로 실행된 함수가 예외를 던져도 화면에는 오류가 표시되지 않습니다. 대신 Apps Script가 실패 요약 이메일을 보내며, 이 이메일에는 트리거를 비활성화하거나 다시 구성하는 링크가 들어 있습니다.
- 실패한 행만 다시 큐에 넣으려면 AI 영상 배치 실패 항목 재시도를 참고하세요.
| 한도 | 값 | 구분 |
|---|---|---|
| 대량 실행 요청당 항목 | 1–100 | Sume |
동시에 진행하는 자식 실행(concurrency) | 1–16 | Sume |
| 스크립트 실행 시간 | 실행당 6분 | |
| 트리거 총 실행 시간 | 하루 90분(개인 계정), 하루 6시간(Workspace) | |
| URL Fetch 호출 | 하루 20,000회(개인 계정), 하루 100,000회(Workspace) | |
| 트리거 | 스크립트별 사용자당 20개 |
출처
- 대량 실행
- 실행과 결과 (영문)
- Format 쿡북
- 인증
- Google Apps Script: UrlFetchApp 클래스 (2026-09-27 확인)
- Google Apps Script: Google 서비스 할당량 (2026-09-27 확인)
- Google Apps Script: ClockTriggerBuilder 클래스 (2026-09-27 확인)
- Google Apps Script: 설치 가능한 트리거 (2026-09-27 확인)
- Google Apps Script: 속성 서비스 (2026-09-27 확인)
- Google Apps Script: 콘텐츠 서비스 (2026-09-27 확인)
- Google Apps Script: SpreadsheetApp 클래스 (2026-09-27 확인)
관련 글
연동 카테고리의 다른 글
- Gradio 영상 생성 앱: Sume API 키는 Space 시크릿에
Sume API로 Gradio 영상 생성 앱을 만드세요. 키는 Hugging Face Space 시크릿에 두고, 제너레이터가 Job을 폴링하고, gr.Video가 영상을 재생합니다.
- Inngest 이벤트 대기: Sume 영상 실행이 끝나면 재개
step.run에서 Sume 실행을 시작하고, transform으로 웹훅을 Inngest 이벤트로 바꾼 뒤, 실행 id를 기준으로 2시간 타임아웃을 둔 step.waitForEvent로 기다리세요.
- Sume Format을 실행하는 LangChain 영상 생성 도구
LangChain @tool은 Sume Format 실행을 시작하고, 지출 상한을 두고, 안전한 재시도용 키를 붙이고, 영상이 준비될 때까지 에이전트가 확인할 실행 id를 돌려줄 수 있습니다.
- LlamaIndex 이미지 생성 도구: Sume Image API
POST /v1/images를 LlamaIndex FunctionTool로 감싸세요. sume/auto와 프롬프트를 보내고, 200이면 URL을, 202이면 Job id를 돌려주면 됩니다.
작성자 Sume