{"slug": "i-counted-150-ai-video-prompts-then-built-an-n8n-workflow-that-posts-one-a-day", "title": "I counted 150 AI video prompts, then built an n8n workflow that posts one a day", "summary": "A developer built an n8n workflow that automatically posts one AI video prompt per day, complete with the clip it generated, sourced from a public library of 150 Seedance 2 video prompts. The workflow scrapes JSON-LD schema for stability and rotates prompts by day index. Analysis of the 150 prompts found a median length of 152 characters, with 46% specifying camera details and 34% splitting prompts by time ranges, suggesting that concise, structured prompts are more effective than long ones.", "body_md": "Most \"prompt of the day\" bots are a random line of text in a Slack channel. Nobody reads them, because a prompt with no output next to it is just a sentence.\n\nI wanted the opposite: one prompt a day, **with the clip that prompt actually produced**, and no credentials to set up. It turned into a small n8n workflow and a much more interesting question — what does a prompt that actually works look like, statistically?\n\nSix nodes, no API key, no account:\n\n`sitemap.xml`.` day % total`.` h1`, the `pre` blocks, and the JSON-LD `script` tags.`VideoObject` schema, assemble a Slack-flavoured message.\nThe source is a [public library of Seedance 2 video prompts](https://emaki.ai/prompt?ref=devto) — 150 of them, each with the clip it generated.\n\n**Rotate, don't randomize.** `Math.floor(Date.now() / 86400000) % urls.length` gives you one prompt per day that is stable across re-runs. `Math.random()` gives you duplicates within a week and a different result every time you debug.\n\n``` js\nconst urls = [...xml.matchAll(/<loc>([^<]+)<\\/loc>/g)]\n  .map((m) => m[1].trim())\n  .filter((u) => u.includes('/prompt/'))\n  .filter((u) => !u.includes('/prompt/category/'));\n\nconst dayIndex = Math.floor(Date.now() / 86400000);\nconst url = urls[dayIndex % urls.length];\n```\n\n**Read the schema, not the layout.** Every prompt page ships a `VideoObject` in JSON-LD with `name`, `description` and `contentUrl`. That is a stable contract; the rendered markup is not. Scraping the schema means a CSS refactor on their side does not silently break my workflow.\n\n``` js\nfor (const raw of item.structuredData || []) {\n  const parsed = JSON.parse(raw);\n  const blocks = Array.isArray(parsed) ? parsed : [parsed];\n  const found = blocks.find((b) => b['@type'] === 'VideoObject');\n  if (found) { video = found; break; }\n}\n```\n\n**Count your selectors before you trust index 0.** Each page has *two* `<pre>` blocks: the Japanese original and the English version. `cssSelector: \"pre\"` with `returnArray: false` silently gives you the first one — so my first run posted Japanese into an English channel and looked completely fine. Set `returnArray: true` and choose explicitly.\n\nSince I had all 150 in a list, I counted them. Median prompt length is **152 characters**. Longest is 215.\n\nThat is roughly one sentence each for style, place, subject and motion. Every \"advanced prompting guide\" I have read implies the opposite — that control comes from length. In this corpus, it doesn't exist. Long prompts tend to contain contradicting instructions, and the model drops one of them, non-deterministically.\n\nElement frequency across the 150:\n\n| Element | Appears in | \n|---|---|\n| Camera / lens / framing | 69 / 150 (46%) | \n| Duration stated in seconds | 63 / 150 (42%) | \n| Lighting | 55 / 150 (37%) | \n| Cut structure | 22 / 150 (15%) | \n| Audio (ambience, SFX, dialogue, ASMR) | 22 / 150 (15%) | \n| Resolution (4K / 8K) | 14 / 150 (9%) | \n| Slow motion | 4 / 150 (3%) | \n\nTwo readings I'd stand behind:\n\nA third of the corpus (34/150) splits the prompt by **time range** rather than describing one continuous action:\n\n```\n[00:00-00:05] intro, camera enters from behind the subject\n[00:05-00:10] turn, light source switches\n[00:10-00:15] wide, full scene\n```\n\nThat form clusters hard: sci-fi (9), cinematic (7), people (5) — and it is almost absent from scenery (2) and food (0). It shows up exactly where **order carries meaning**. For a single continuous shot, stating total duration is enough.\n\nAnd 32 of 150 need a reference image rather than text alone. The tell is simple: the moment a prompt points at *a specific person or a specific frame* instead of a *kind* of thing, text can no longer specify it. That is the line between [text-to-video](https://emaki.ai/video?ref=devto) and [image-to-video](https://emaki.ai/image-to-video?ref=devto).\n\n`/slack` to the webhook URL — it then accepts the same `{ \"text\": ... }` payload.\nThat's the whole thing. Everything it reads is public, so there is no credential step and nothing to rotate.\n\nThe prompts themselves are written against [Seedance 2.5](https://emaki.ai/seedance-2-5?ref=devto); if you have not run one before, the [walkthrough](https://emaki.ai/how-to-use-seedance?ref=devto) is shorter than this post.\n\nI wrote the full breakdown of all 150 — element frequency, duration patterns, the reference-image split by category — as a [standalone reference](https://hanshs474.gitbook.io/seedance-2-prompt-guide/) (Japanese). There is also a [Japanese write-up of the implementation](https://qiita.com/hanshs474/items/9781f2a83abac5f260ae) on Qiita if that is your reading language.\n\nIf you build something similar against another corpus, the transferable part is not the scraping — it is checking whether the thing you are scraping publishes structured data first. It usually does, and it is usually more stable than the HTML around it.", "url": "https://wpnews.pro/news/i-counted-150-ai-video-prompts-then-built-an-n8n-workflow-that-posts-one-a-day", "canonical_source": "https://dev.to/kavel/i-counted-150-ai-video-prompts-then-built-an-n8n-workflow-that-posts-one-a-day-3jme", "published_at": "2026-09-07 14:00:21+00:00", "updated_at": "2026-09-07 14:28:33.910500+00:00", "lang": "en", "topics": ["developer-tools", "generative-ai", "ai-tools"], "entities": ["n8n", "Seedance 2", "emaki.ai"], "alternates": {"html": "https://wpnews.pro/news/i-counted-150-ai-video-prompts-then-built-an-n8n-workflow-that-posts-one-a-day", "markdown": "https://wpnews.pro/news/i-counted-150-ai-video-prompts-then-built-an-n8n-workflow-that-posts-one-a-day.md", "text": "https://wpnews.pro/news/i-counted-150-ai-video-prompts-then-built-an-n8n-workflow-that-posts-one-a-day.txt", "jsonld": "https://wpnews.pro/news/i-counted-150-ai-video-prompts-then-built-an-n8n-workflow-that-posts-one-a-day.jsonld"}}