Create Instagram Carousel Post (Topaz Enhanced)
End-to-end pipeline: itinerary URL → photo sourcing → Topaz AI enhance → text overlays → Instagram carousel publish.
Identical to itinerary-carousel-post except Sub-agent 1 includes a Topaz enhancement step after selecting the best photo for each subject.
Parameters
- - itinerary_url (required): tabiji.ai itinerary URL (e.g.
https://tabiji.ai/i/thaw-dome/) - destination (required): City/region name (e.g. "Kuala Lumpur")
- attractions (required): List of 5 attraction names + short descriptions
- caption (optional): Custom caption. If omitted, generate one with destination name, attraction list, CTA to link in bio, and relevant hashtags.
Pipeline (3 chained sub-agents recommended)
Split into 3 sub-agents for reliability. Each writes outputs to /tmp/ig-carousel/.
Sub-agent 1: Photo Finding + Topaz Enhancement
Use the instagram-photo-find skill workflow for each subject (1 destination + 5 attractions = 6 total).
For each subject:
- 1.
web_search: site:instagram.com/p/ "{subject}" photo (10 results) - Download top 5 candidates: INLINECODE6
- Vision-score each with: "Rate 1-10 as hero destination photo for {subject}. Description + score only."
- Keep best per subject → INLINECODE7
5. Topaz Enhance each best image:
CODEBLOCK0
If the sync endpoint times out or returns a process_id instead of image bytes, use the async flow:
CODEBLOCK1
Model choice: Low Resolution V2 — designed for web-sourced images (exactly our use case). Handles JPEG compression artifacts, low resolution, and general softness. Fast and cheap.
Parameters explained:
- -
output_scale_factor=2 — doubles the input resolution (2x upscale). For typical IG-sourced images (~1080px), this produces ~2160px which gives the overlay step plenty of resolution to work with. - INLINECODE11 — keeps file size reasonable for IG's 8MB limit
Output: 6 enhanced images at /tmp/ig-carousel/{slug}-enhanced.jpg + JSON manifest at /tmp/ig-carousel/manifest.json:
CODEBLOCK2
Sub-agent 2: Text Overlays
Read manifest from sub-agent 1. Run overlay script for each enhanced image.
Slide 1 (cover) — clean style:
CODEBLOCK3
Slides 2–6 — quote style per attraction with insider tip:
CODEBLOCK4
Output: 6 overlay images at INLINECODE14
Sub-agent 3: Publish to Instagram
- 1. Host images publicly — copy slides to tabiji repo (
img/instagram/), git push, use raw GitHub URLs (https://raw.githubusercontent.com/psyduckler/tabiji/main/img/instagram/slide-{N}.jpg). Wait ~30s after push for GitHub CDN.
- 2. Create carousel item containers (one per slide):
CODEBLOCK5
- 3. Create carousel container with all children + caption:
CODEBLOCK6
- 4. Publish:
CODEBLOCK7
- 5. Get permalink (or verify publish on rate-limit error):
If media_publish returns a POST_ID, get the permalink directly:
CODEBLOCK8
If media_publish returns error 2207051 (rate limit / action blocked): Instagram sometimes processes the request despite returning an error. Always verify by checking the account's recent media before declaring failure:
curl -s "https://graph.facebook.com/v21.0/${IG_USER}/media?fields=id,timestamp,permalink&limit=1&access_token=${IG_TOKEN}"
If the most recent post timestamp is within the last few minutes, the publish likely succeeded — grab that permalink.
- 6. Cleanup hosted images — after publish is confirmed, delete the images from the tabiji repo and push:
cd /path/to/tabiji/repo
git rm img/instagram/slide-*.jpg
git commit -m "cleanup: remove instagram carousel images after publish"
git push
Also clean up local temp files:
CODEBLOCK11
Output: Instagram post URL
Instagram API Auth
Keys from macOS Keychain:
- -
instagram-access-token — Graph API token - INLINECODE21 — IG user ID (17841449394591017)
Topaz API Auth
Key from macOS Keychain:
- -
topaz-api-key — Topaz Labs API key
Caption Template
CODEBLOCK12
Tips
- - Raw GitHub URLs work for IG image_url; tabiji.ai Cloudflare CDN may trigger format validation errors.
- Add
sleep 1 between container creation calls to avoid rate limits. - If a subject yields low photo scores (<5), broaden search: try Unsplash/Flickr or more specific landmark names.
- Islamic/cultural museums tend to have fewer quality IG photos — try searching the museum's official IG handle.
- Topaz sync endpoint may return image bytes directly (check Content-Type header). If it returns JSON with
process_id, switch to async flow. - Topaz rate limits: If you get HTTP 429, use exponential backoff. Processing 6 images sequentially should be fine.
- Keep originals: The manifest stores both
path (enhanced) and original so you can compare quality or fall back if Topaz fails on a specific image.
创建Instagram轮播帖子(Topaz增强版)
端到端流程:行程URL → 照片获取 → Topaz AI增强 → 文字叠加 → Instagram轮播发布。
与itinerary-carousel-post相同,不同之处在于子代理1在为每个主题选择最佳照片后增加了Topaz增强步骤。
参数
- - itinerary_url(必填):tabiji.ai行程URL(例如https://tabiji.ai/i/thaw-dome/)
- destination(必填):城市/地区名称(例如吉隆坡)
- attractions(必填):5个景点名称+简短描述列表
- caption(可选):自定义文案。如果省略,则自动生成包含目的地名称、景点列表、个人简介链接引导和相关话题标签的文案。
流程(建议3个链式子代理)
为提高可靠性,分为3个子代理。每个子代理将输出写入/tmp/ig-carousel/。
子代理1:照片查找 + Topaz增强
对每个主题(1个目的地 + 5个景点 = 共6个)使用instagram-photo-find技能工作流。
对每个主题:
- 1. web_search:site:instagram.com/p/ {subject} photo(10个结果)
- 下载前5个候选:curl -s -L -o /tmp/ig-carousel/raw-{slug}-{n}.jpg https://www.instagram.com/p/{shortcode}/media/?size=l
- 对每张图片进行视觉评分:以1-10分评价作为{subject}的封面目的地照片。仅返回描述和评分。
- 每个主题保留最佳图片 → /tmp/ig-carousel/{slug}-best.jpg
5. 对每张最佳图片进行Topaz增强:
bash
TOPAZAPIKEY=$(security find-generic-password -s topaz-api-key -w)
curl --request POST \
--url https://api.topazlabs.com/image/v1/enhance \
--header X-API-Key: ${TOPAZAPIKEY} \
--header accept: image/jpeg \
--header content-type: multipart/form-data \
--form model=Low Resolution V2 \
--form outputscalefactor=2 \
--form output_format=jpeg \
--form image=@/tmp/ig-carousel/${slug}-best.jpg \
--output /tmp/ig-carousel/${slug}-enhanced.jpg
如果同步端点超时或返回process_id而非图片字节,则使用异步流程:
bash
异步:提交
RESPONSE=$(curl -s --request POST \
--url https://api.topazlabs.com/image/v1/enhance/async \
--header X-API-Key: ${TOPAZ
APIKEY} \
--header content-type: multipart/form-data \
--form model=Low Resolution V2 \
--form output
scalefactor=2 \
--form output_format=jpeg \
--form image=@/tmp/ig-carousel/${slug}-best.jpg)
PROCESSID=$(echo $RESPONSE | jq -r .processid)
轮询状态直至完成
while true; do
STATUS=$(curl -s --header X-API-Key: ${TOPAZ
APIKEY} \
https://api.topazlabs.com/image/v1/status/${PROCESS_ID} | jq -r .status)
[ $STATUS = Completed ] && break
sleep 3
done
下载结果
curl -s --header X-API-Key: ${TOPAZ
APIKEY} \
https://api.topazlabs.com/image/v1/download/${PROCESS_ID} \
--output /tmp/ig-carousel/${slug}-enhanced.jpg
模型选择: Low Resolution V2 — 专为网络来源图片设计(正是我们的使用场景)。处理JPEG压缩伪影、低分辨率和整体模糊效果。快速且经济。
参数说明:
- - outputscalefactor=2 — 将输入分辨率翻倍(2倍放大)。对于典型的IG来源图片(约1080px),可产生约2160px的图片,为叠加步骤提供充足的分辨率空间。
- output_format=jpeg — 保持文件大小合理,不超过IG的8MB限制
输出:6张增强图片位于/tmp/ig-carousel/{slug}-enhanced.jpg + JSON清单位于/tmp/ig-carousel/manifest.json:
json
[{slug: kuala-lumpur, subject: Kuala Lumpur, score: 7, path: /tmp/ig-carousel/kuala-lumpur-enhanced.jpg, original: /tmp/ig-carousel/kuala-lumpur-best.jpg, source: instagram.com/p/XXX/, topaz_enhanced: true}]
子代理2:文字叠加
读取子代理1的清单。对每张增强图片运行叠加脚本。
幻灯片1(封面) — 简洁风格:
bash
python3 skills/instagram-photo-text-overlay/scripts/overlay.py \
--input /tmp/ig-carousel/{dest-slug}-enhanced.jpg \
--output /tmp/ig-carousel/slide-1.jpg \
--title {N}天{DESTINATION}行程亮点 \
--style clean --watermark tabiji.ai
幻灯片2–6 — 每个景点引用风格+内行贴士:
bash
python3 skills/instagram-photo-text-overlay/scripts/overlay.py \
--input /tmp/ig-carousel/{slug}-enhanced.jpg \
--output /tmp/ig-carousel/slide-{N}.jpg \
--title {ATTRACTION} \
--quote {关于此景点的具体内行贴士——必须直接引用标题中的地点,而非通用旅行建议} \
--author tabiji.ai \
--style quote --watermark tabiji.ai
输出:6张叠加图片位于/tmp/ig-carousel/slide-{1-6}.jpg
子代理3:发布到Instagram
- 1. 公开托管图片 — 将幻灯片复制到tabiji仓库(img/instagram/),git推送,使用原始GitHub URL(https://raw.githubusercontent.com/psyduckler/tabiji/main/img/instagram/slide-{N}.jpg)。推送后等待约30秒让GitHub CDN生效。
- 2. 创建轮播项目容器(每张幻灯片一个):
bash
curl -s -X POST https://graph.facebook.com/v21.0/${IG_USER}/media \
-d image
url=${PUBLICURL} \
-d is
carouselitem=true \
-d access
token=${IGTOKEN}
- 3. 创建轮播容器,包含所有子项+文案:
bash
curl -s -X POST https://graph.facebook.com/v21.0/${IG_USER}/media \
--data-urlencode caption=${CAPTION} \
-d media_type=CAROUSEL \
-d children=${CHILD_IDS} \
-d access
token=${IGTOKEN}
- 4. 发布:
bash
curl -s -X POST https://graph.facebook.com/v21.0/${IG
USER}/mediapublish \
-d creation
id=${CAROUSELID} \
-d access
token=${IGTOKEN}
- 5. 获取永久链接(或在速率限制错误时验证发布):
如果mediapublish返回POSTID,直接获取永久链接:
bash
curl -s https://graph.facebook.com/v21.0/${POSTID}?fields=permalink&accesstoken=${IG_TOKEN}
如果media_publish返回错误2207051(速率限制/操作被阻止): Instagram有时会在返回错误的情况下处理请求。在宣布失败前,务必通过检查账户的最近媒体来验证:
bash
curl -s https://graph.facebook.com/v21.0/${IGUSER}/media?fields=id,timestamp,permalink&limit=1&accesstoken=${IG_TOKEN}
如果最近发布的时间戳在几分钟内,则发布很可能成功——获取该永久链接。
- 6. 清理托管的图片 — 确认发布后,从tabiji仓库删除图片并推送:
bash
cd /path/to/tabiji/repo
git rm img/instagram/slide-*.jpg
git commit -m cleanup: remove instagram carousel images after publish
git push
同时清理本地临时文件:
bash
rm -rf /tmp/ig-carousel/
输出:Instagram帖子URL
Instagram API认证
从macOS钥匙串获取密钥:
- - instagram-access-token — Graph API令牌
- instagram-account-id — IG用户ID