SuperAPI AI Directory

poetry-cinema-page

General & other

View repository

Updated 10-16 09:44

About this skill

Poetry Cinema Page

Create a complete webpage, not a mockup. Preserve the poem exactly, generate a coherent image set, implement scroll-driven scene transitions, explain the poem clearly, build the project, and visually inspect it.

Non-negotiable quality bar

  • Treat imagery as the poem's emotional world, not decoration.
  • Prefer cinematic realism, high-end historical photography, crafted diorama realism, or restrained ink-inspired cinematography according to the poem. Never default to low-poly, cartoon, plastic-toy, or generic “ancient style.”
  • Use one visual bible across every generated image: same geography, characters, era, palette, materials, weather, camera language, and time progression.
  • Keep image files free of text, calligraphy, logos, seals, signatures, and watermarks. Add typography in HTML.
  • Never replace or overwrite an existing poetry page unless the user explicitly asks. Create a new route/page and link the pages.
  • State textual variants instead of silently “correcting” the user's poem.

Required workflow

1. Inspect the project

Identify the framework, build scripts, existing pages, design system, dev-server state, and dirty files. Reuse the current stack. For Vite multi-page sites, add a new HTML entry and configure build.rollupOptions.input when needed.

2. Build the literary scene map

Read references/poetry-analysis.md. Produce internally:

  • verified title, author, era, genre/ci tune;
  • 5–8 visual beats based on imagery, action, time, and emotional turns—not equal line counts;
  • for every beat: original text, plain meaning, core images, technique, emotional function, and proposed scene;
  • the overall arc, such as landscape → history → hero → self → release.

Use the supplied text verbatim in the page. If a common textual variant matters, mention it in explanatory copy without derailing the experience.

3. Choose an art direction

Read references/image-direction.md. Select a visual form from the poem itself:

  • intimate travel, village, still life → realistic handcrafted diorama or macro historical photography;
  • war, rivers, mountains, political history → large-scale prestige historical cinema;
  • dream, myth, celestial, highly metaphorical work → restrained painterly cinema with physically credible light;
  • quiet philosophical poem → minimal photographic landscape with negative space.

Default to a hero plus one image per major beat. Six to eight total images usually balances immersion, consistency, and load time.

4. Generate and persist the image set

Images are generated through the bundled CLI scripts/ark_image.py, which can talk to either Volcengine Ark Doubao Seedream 5.0 or a third-party GPT-Image gateway — two providers configured side by side and selected per tier. One call per distinct asset; never one generic prompt for all images. Full parameter reference: references/ark-api.md.

Verify credentials and endpoint before spending any generation time:

python scripts/ark_image.py probe

probe resolves the key of every provider (see Configuration), reports each endpoint with its models, and then verifies every configured model id by sending one request that is rejected on purpose by validation — no image is generated and nothing is billed. Ark model ids are fully proved this way, because Ark validates size and resolves the model too; for gpt-2 / gpt-2.5 the report says model id NOT verified; use --live for that, since the gateway validates the request body before the model — only probe --live, which does generate one image per model, proves those ids. Fix credentials before continuing; do not start a poem on an untested key.

Pick the tier by role. The tier is the only thing that selects a provider, so mixing providers inside one poem is normal. pro (doubao-seedream-5.0-pro) and lite (doubao-seedream-5.0-lite) are Volcengine Ark: hero and every beat use pro (highest quality), drafts and repairs use lite (cheaper and faster). gpt-2 (gpt-image-2) and gpt-2.5 (gpt-image-2.5) are the GPT-Image gateway — use them when you deliberately want that provider for the hero or for individual beats. Role routing lives in the config file, so --role is normally the only selector needed; override per call with --tier, --provider, or --model.

Generate the hero with text-to-image:

python scripts/ark_image.py t2i \
  --role hero \
  --size 2560x1440 \
  --prompt "<hero paragraph>" \
  --out public/generated/<poem-slug>/hero.jpg

Then generate every beat with image-to-image, passing the hero as a reference:

python scripts/ark_image.py i2i \
  --role beat \
  --ref public/generated/<poem-slug>/hero.jpg \
  --prompt "<beat paragraph>" \
  --out public/generated/<poem-slug>/scene-1.jpg

The hero reference is what makes the set one world: geography, period, recurring characters, wardrobe, materials, palette, and lens language come from the reference image instead of from prose alone. The chain also crosses providers — an Ark hero can be the reference for a beat generated on the gateway, and the reverse works too. When a beat introduces a new recurring character, generate that character deliberately, then pass its file as an extra --ref for later beats that include it. Reserve negative space on the side where page copy will sit.

Never move a reference call to the gateway's /images/generations endpoint: the image, image_url and images fields are silently ignored there, so the call returns 200 with a fresh text-to-image picture and the reference chain is quietly gone. Image-to-image on the gateway is multipart POST /images/edits with the reference in a field literally named image; the CLI already does exactly that — do not "optimise" the edits call away.

Drive the whole set from one batch plan, so a poem is one command and one manifest. Write plan.json:

{
  "out_dir": "public/generated/<poem-slug>",
  "images": [
    {"name": "hero",    "role": "hero", "prompt": "..."},
    {"name": "scene-1", "role": "beat", "ref": ["hero"], "prompt": "..."}
  ]
}
python scripts/ark_image.py batch --plan plan.json

"ref": ["hero"] means “use the already-generated hero image inside out_dir as the image-to-image reference”, so the hero comes first and the beats follow in poem order. batch also writes prompts.json (every request and response) and contact-sheet.html into out_dir.

Then:

  1. Keep the delivered files under public/generated/<poem-slug>/, with prompts.json and contact-sheet.html beside them.
  2. Inspect the contact sheet — all images together, before any page work.
  3. Reject or repair images with style drift, accidental text/seals, wrong era, malformed focal subjects, or mismatched recurring characters. Re-run the offenders with --role repair (lite), or regenerate a failed beat while still passing the hero as --ref.
  4. Keep the delivered files. Ark returns JPEG at 2560x1440, roughly 250–500 KB each, already inside the web delivery budget, so no re-encode step is required; the gateway returns PNG at roughly 2 MB, so add lighter derivatives when the page needs them. The extension follows the format actually returned — a .png result is never written under a .jpg name, and the CLI prints a note: when it rewrites one — so take the real filenames from prompts.json, not from the path you typed.

Size note: 2560x1440 is the only 16:9 value both Ark tiers accept. Never pass a shorthand such as "2K" — it silently returns a non-16:9 frame. The gateway accepts custom sizes and even auto, but it validates nothing (nonsense sizes come back 200), so the skill enforces its own min_edge_px / max_edge_px band there rather than relying on the API to reject a bad size.

Do not integrate uninspected generated assets.

5. Generate the narration

The narration track is generated, not borrowed; use a user-supplied or project-provided track only when the user actually brought one. Two engines are selectable through narration.engine in the config, or --engine on any command:

  • edge-tts — Microsoft edge-tts, runs locally, free, no key; native output mp3.
  • doubao-seed-tts — Volcengine Doubao seed-tts-2.0 over the Ark plan gateway, using the same Ark key step 4 already resolves; native output wav, which the script transcodes to mp3.

Full comparison and configuration walkthrough: references/narration.md.

Verify engines and credentials first. probe really speaks one short phrase on each configured engine, so it is not free; --dry-run reports and synthesizes nothing:

python scripts/narration.py probe

If the voice is not decided yet, do not guess from an id. Audition the catalog and listen:

python scripts/narration.py audition --text "君不见,黄河之水天上来,奔流到海不复回"

audition writes one clip per voice plus an index.html with an <audio> player for each (default public/audio/audition/). Have the user pick, then pin the id in narration.engines.<engine>.voice or pass --voice.

Write the narration script next to the page: # lines are comments, a blank line starts a new paragraph (longer pause), and every other line is one spoken segment — one verse line per line. Keep the poem verbatim.

python scripts/narration.py build \
  --text-file narration.txt \
  --out public/audio/<poem-slug>.mp3 \
  --srt public/audio/<poem-slug>.srt

build writes the joined mp3, a timing sidecar (public/audio/<poem-slug>.mp3.json, with per-line start / end / duration), and the SRT when --srt is given. Point poem.audioSrc at the mp3 in the next step.

6. Implement the webpage

Read references/page-pattern.md. Prefer the bundled files in assets/page-template/ as the starting point when the project has no stronger existing pattern.

Required page anatomy:

  1. Hero: title, author/era, a defining line, a short invitation, and a scroll cue.
  2. One full-viewport section per visual beat.
  3. Each section: original line(s), literal meaning, close reading, and one compact visual device such as keywords, contrast, verb rhythm, emotional scale, or timeline.
  4. Closing interpretation: genre/tune, structure, imagery, techniques, emotional arc, and central meaning.
  5. Navigation between poetry pages when more than one exists.
  6. A narration control. Generate the track with scripts/narration.py (step 5) unless the user supplied their own audio, then point poem.audioSrc at the produced mp3. Attempt autoplay, and always keep an accessible play/pause switch because browsers commonly block audible autoplay.

Use a fixed image stage with two overlapping texture planes or image layers. Crossfade when the active section changes; add only subtle zoom or pointer parallax. The image is the protagonist—keep cards translucent, readable, and smaller than half the viewport on desktop.

Do not use paid video generation unless the user explicitly asks. A high-quality image sequence with crossfades is the default.

7. Responsive and accessible behavior

  • Use semantic headings, sections, buttons, and navigation.
  • Keep the full focal subject visible on phones; prefer contain with a blurred full-bleed backdrop when a crop would destroy meaning.
  • Support prefers-reduced-motion by disabling smooth scrolling, parallax, and long fades.
  • Maintain readable contrast without dimming the artwork into obscurity.
  • Do not load every full-resolution master up front; serve lighter derivatives where the page needs them.
  • Give the narration button a visible text label, aria-pressed, keyboard focus styling, and a local error state. Do not hide the control merely because autoplay failed.

8. Verify the result

Run the production build. Then use a real browser to inspect:

  • hero after assets finish loading;
  • at least two middle sections after the crossfade settles;
  • closing interpretation;
  • one mobile viewport;
  • narration source availability, autoplay fallback, and play/pause state;
  • console warnings/errors.

The page fails QA if the generated images are not visibly switching, cards cover the main subjects, text is clipped, the page remains on a loading screen, or the imagery feels unrelated to the poem.

9. Deliver

Report:

  • the local/page URL;
  • source files changed;
  • image asset directory;
  • contact sheet path;
  • narration asset URL or path, together with the engine and voice actually used;
  • build and browser-QA result;
  • the image tiers, providers and model ids actually used (for example pro on ark and gpt-2 on gpt-image);
  • the config file path (config/ark.config.json);
  • the prompt-manifest path (public/generated/<poem-slug>/prompts.json).

Keep the dev server running when the user wants to review locally.

10. Voiceover video (optional, on request)

When the user asks to turn the page's images and narration into a 口播视频 (narrated video), read references/video.md and run scripts/video.py. The video reuses what steps 4–6 already produced — scene images, the narration mp3 and its per-line timing sidecar, and the page's design tokens — and pins them onto a Remotion timeline (1920×1080, 30fps): one shot per literary beat, hard-cut subtitles in two roles (verse for the original text, prose for interpretation), a title card, an end card, film grain and vignette.

Motion is not decoration here, it is the difference between a video and a slideshow. Four layers carry it, and a film that skips them reads flat no matter how good the images are:

  1. Camera — 13 moves, all with a baseline scale ≥ 1.15 so there is real travel room (±7%, not the ±1.4% that made earlier cuts invisible). Each move is two-phase: it covers 90% of its travel in the first ~66% of the shot, then barely creeps — so every shot arrives and then breathes, instead of sliding uniformly to a stop. Plus a 3.4px handheld sway.
  2. Inside the frame — deterministic dust/snow/ember particles in two depth layers, drifting mist, a one-time light sweep, and a ±2.2% brightness breathe. This is what makes a still photograph feel alive; camera motion alone does not.
  3. Between shots — five transitions, not one: crossfade, dip-black, flash-warm, push-through, light-leak. Assign them along the poem's emotional arc (a dip-to-black where the feeling breaks, a warm flash on the declarative line), never as an even round-robin.
  4. Text — the verse layer lights up character by character in time with the voice, with the not-yet-spoken remainder held at 42% opacity; captions develop in from blur; the title card converges its tracking and grows its rule.

Write a video-plan.json (the storyboard release) — per-shot move, transition, fx — then probe → init → build → still → render → frames, reviewing stills and re-extracted frames before delivering. Full command surface, plan schema, move/transition/fx vocabulary, and the QA checklist of known failure modes: references/video.md.

Configuration

config/ark.config.json is the single place to change the image providers, the models, the role routing, the sizes, and the timeouts. Do not hard-code those values anywhere else.

Image settings live under image:

  • image.provider — the default provider (ark in the shipped file). It applies to any tier that does not name its own provider.
  • image.providers.<name> — one block per provider: ark (kind ark, Volcengine Ark Doubao Seedream) and gpt-image (kind openai-images, the third-party GPT-Image gateway). Each block carries its own base_url, endpoint paths, key settings, timeouts and limits.

Provider-level knobs, all per provider: timeout_seconds, max_retries, retry_backoff_seconds, reference_transport (inline for Ark, multipart for the gateway), reference_max_edge (bounds the size of a reference before an upload), user_agent (mandatory on the gateway, which sits behind Cloudflare), and limits (Ark's area band versus the gateway's edge band).

models maps a tier name to {provider, id} — pro and lite on ark, gpt-2 and gpt-2.5 on gpt-image — and a tier may still be written as a bare model-id string, which then uses the default provider. A config written entirely in the old shape (a top-level api block, plus a top-level limits, with no image block) is still read as a single provider, so nobody has to migrate anything to keep working.

Select a provider with --provider <name> on t2i, i2i or batch; in a batch plan an individual entry may carry its own "provider", "tier" or "model", which is how one poem mixes providers image by image. probe takes no --provider: it follows the tier→provider mapping in models, or --tier.

Keys never live in that file — it is committed to a public repository. Each provider resolves its own key, in this order:

  1. that provider's environment variable — ARK_API_KEY for ark, GPT_IMAGE_API_KEY for gpt-image;
  2. that provider's local override file — config/ark.local.json or config/gpt-image.local.json, both git-ignored;
  3. that provider's api_key field in ark.config.json, for throwaway local experiments only.

Local override files, one per provider. config/ark.local.json:

{ "api_key": "ark-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" }

config/gpt-image.local.json:

{ "api_key": "lupi_xxxxxxxxxxxxxxxxxxxx" }

See references/ark-api.md for the full parameter reference, the provider comparison, the verified size limits, error handling, and the config-file walkthrough.

scripts/extract_imagegen_results.py is a legacy fallback only, for environments still running Codex's built-in ImageGen; the Ark path above does not need it.

Narration

The same config/ark.config.json carries the narration settings, under narration:

  • narration.engine — the active engine: edge-tts (default; local, free, no key) or doubao-seed-tts (Doubao seed-tts-2.0 through the same Ark key the images use). Change this one key to switch, or pass --engine per command.
  • narration.engines.edge-tts — voice, rate ("+0%"; -20% reads slower), volume, pitch (-8Hz reads lower).
  • narration.engines.doubao-seed-tts — voice, speed (integer percent delta, −50..100), emotion (empty = natural), resource_id (seed-tts-2.0), url, sample_rate.
  • narration.audio — output dir, format, bitrate, channels, sample_rate, the line_gap_seconds / paragraph_gap_seconds pauses, and loudness normalisation.
  • narration.script — open_with_title, title_template, include_original, include_literal, include_analysis: which text layers a structured .json narration source contributes. With a plain .txt script the file is spoken verbatim instead, and --include overrides the config for one run.
  • narration.voice_catalog — the selectable voices per engine, each {id, gloss}; gloss is a gloss of the romanised id, not an official description.
  • narration.known_rejected — voice ids that failed the engine's resource-id check, with the reason.

Change the voice in narration.engines.<engine>.voice or with --voice <id>, and do not pick one by reading its id — run audition and listen. Full command surface, catalogs, and troubleshooting: references/narration.md.

Video

The same config file carries the video settings, under video: fps / width / height, crossfade_frames, grain_opacity, tail_seconds, workspace, template_dir, plus the motion knobs — motion_gain (global camera amplitude; 1 standard, 1.3 bolder, 0.6 more restrained), handheld_px (sway amplitude, 0 disables), caption_reveal (whether the verse layer lights up per character), default_transition — and two environment-specific knobs: node_modules (point it at any directory that already has remotion@4 installed and init copies it offline instead of running npm install) and browser_executable (left empty, the CLI auto-detects a local Chrome/Edge, which Remotion needs to render). Details and the plan-file schema: references/video.md.

Bundled resources

  • references/poetry-analysis.md: textual segmentation and explanation rules.
  • references/image-direction.md: visual bible, Seedream-shaped prompt patterns, and the reference-image chain.
  • references/ark-api.md: the image provider reference — Ark Doubao Seedream and the GPT-Image gateway side by side, provider/tier selection, request/response schemas, verified size rules, error codes, config walkthrough, and CLI reference.
  • references/page-pattern.md: page architecture and QA details.
  • references/narration.md: narration engines, CLI reference, script format, timing sidecar, voice catalogs, config walkthrough, and troubleshooting.
  • assets/page-template/: generic HTML, TypeScript, CSS, and config starter.
  • config/ark.config.json: image providers, models, routing, sizes, retries, and timeouts; config/ark.local.json and config/gpt-image.local.json each hold one local key only.
  • scripts/ark_image.py: the image CLI for both providers — Ark and the GPT-Image gateway — with probe (add --live to prove gateway model ids), t2i, i2i, batch.
  • scripts/narration.py: the narration CLI — voices, probe, audition, say, build, with edge-tts and doubao-seed-tts engines.
  • scripts/video.py: the voiceover-video CLI — probe, init, build, render, still, frames, run, driving the bundled Remotion template from a video-plan.json. init copies the whole template src/ tree (so new components ship automatically) and never overwrites an already-built timeline.
  • assets/video-template/: the Remotion project. lib/motion.ts (13 moves, two-phase travel, handheld, safety clamp), lib/fx.tsx (motes / haze / light sweep / breathe — CSS-only, no SVG filters), lib/transitions.tsx (five transitions), lib/scene-stage.tsx, lib/captions.tsx (per-character reveal), lib/cards.tsx, lib/atmosphere.tsx (grain + vignette).
  • scripts/extract_imagegen_results.py: legacy fallback for environments still on Codex's built-in ImageGen.