一键导入
generate-story
Generate and publish a bedtime story for James with consistent text, cover art, and video.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Generate and publish a bedtime story for James with consistent text, cover art, and video.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | generate-story |
| description | Generate and publish a bedtime story for James with consistent text, cover art, and video. |
| metadata | {"short-description":"Generate and publish a bedtime story for James."} |
Use this skill when the user wants a new bedtime story for James or wants to refresh media for an existing story.
Expect some combination of:
YYYY-MM-DD).If the user provides a long synopsis, movie plot, or article-like background, treat it as inspiration only. Do not retell it beat-by-beat.
Always return:
titlestory_contentimage_keyvideo_keystory_idWhen relevant, also return the resolved date.
Required env vars:
STORY_API_TOKENREPLICATE_API_TOKEN for default replicate media generationOPENAI_API_KEY for openai-media, openai-image, or openai-video
OPENAI_BEDTIME_STORY_KEY is also accepted as a local alias by the bundled scriptsSTORY_API_BASE_URL (optional, defaults to https://bedtimestories.bruce-hart.workers.dev)STORY_API_USER_AGENT (optional, defaults to a browser-like user agent for Cloudflare Browser Integrity Check compatibility)The bundled scripts will also auto-load $HOME/.config/secrets/codex.env when these vars are not already exported.
For any Python step, activate the venv first:
source ~/scripts/.venv/bin/activate
Prefer this path unless blocked:
run-generate-story.py.Use the manual image/video/upload steps only if the runner cannot satisfy the task.
Run this first:
source ~/scripts/.venv/bin/activate
set -a
source "$HOME/.config/secrets/codex.env"
set +a
python -c 'import os; assert os.getenv("STORY_API_TOKEN"), "STORY_API_TOKEN missing"'
python -c 'import os; assert os.getenv("REPLICATE_API_TOKEN") or os.getenv("OPENAI_API_KEY") or os.getenv("OPENAI_BEDTIME_STORY_KEY"), "REPLICATE_API_TOKEN or OpenAI key missing"'
command -v ffmpeg >/dev/null
command -v curl >/dev/null
Use this order:
YYYY-MM-DD, use that.YYYY-MM-DD, use that.America/New_York.Preferred helper:
source ~/scripts/.venv/bin/activate
python .codex/skills/generate-story/scripts/next-open-date.py
Relevant env vars:
STORY_API_TOKEN requiredSTORY_API_BASE_URL optionalSTORY_CALENDAR_DAYS optional, default 365STORY_TIMEZONE optional, default America/New_YorkWrite a bedtime story for James.
Hard requirements:
story_content.180-260 words.8-14 short paragraphs.If the user provides complex source material:
1-3 child-friendly ideas.Only include people or pets that matter to the specific story.
Reference details:
Image requirements:
16:9Video requirements:
16:95 secondsKeep prompts short and scene-specific.
Character fidelity requirements:
Mom or Dad, when a physical description is available in Character rulesImage prompt template:
Landscape 16:9 cartoon bedtime scene. {scene}. Include only {relevant_characters_with_physical_descriptions}. Setting details: {visual_setting_details}. Warm storybook mood. No text, letters, or signage.
Video prompt template:
Gentle cartoon motion scene: {action}. Show {relevant_characters_with_physical_descriptions}. Setting details: {visual_setting_details}. Keep it cozy, readable, and simple. No text or letters.
Do not dump the whole story into the media prompt. Use one scene only.
Default runner mode:
replicate uses Replicate for both image and video.Bundled Replicate defaults:
google/nano-banana-2, landscape 16:9, resolution=1Kwan-video/wan-2.2-i2v-fast, 81 frames, 16 fps, go_fast=true, resolution=480p--video-model pixverse/pixverse-v5.Optional runner modes:
--media-provider openai-media uses OpenAI for both steps.--media-provider openai-image uses OpenAI for image and Replicate for video.--media-provider openai-video uses Replicate for image and OpenAI for video.Bundled OpenAI defaults:
gpt-image-2, 1280x720, quality=low, output_format=jpegsora-2, 1280x720, 4 secondsCurrent OpenAI video caveat:
input_reference must match the target video size, and input images with human faces may be rejected. If openai-video or openai-media fails on a people-focused scene, retry with the default provider.After writing the story, save the body to a temp file such as /tmp/story.txt, then run:
source ~/scripts/.venv/bin/activate
python .codex/skills/generate-story/scripts/run-generate-story.py \
--title "TITLE" \
--content-file /tmp/story.txt \
--date YYYY-MM-DD \
--ref-image /path/to/reference-image
Useful flags:
--date YYYY-MM-DD to force a date--ref-image /path/to.jpg repeatable--media-provider replicate|openai-media|openai-image|openai-video to choose the media backend mix--video-model pixverse/pixverse-v5 to use PixVerse instead of the default Replicate video modelSTORY_VIDEO_MODEL=pixverse/pixverse-v5 to make that override persistent for Replicate video runs--image-prompt "..." to override the default image prompt--video-prompt "..." to override the default video prompt--json for machine-readable outputUse this when the user wants to keep the story record but regenerate media:
source ~/scripts/.venv/bin/activate
python .codex/skills/generate-story/scripts/run-generate-story.py \
--title "TITLE" \
--content-file /tmp/story.txt \
--story-id ID \
--ref-image /path/to/reference-image
This regenerates media, uploads it, and updates image_url and video_url for the existing record.
Use the manual path only if the runner is not suitable.
Generate image:
source ~/scripts/.venv/bin/activate
IMAGE_PATH=$(python .codex/skills/generate-story/scripts/generate-image.py \
--image "/path/to/reference.jpg" \
"IMAGE_PROMPT")
Add --provider openai to use gpt-image-2.
Generate video:
source ~/scripts/.venv/bin/activate
VIDEO_PATH=$(python .codex/skills/generate-story/scripts/generate-video.py \
"$IMAGE_PATH" \
"VIDEO_PROMPT")
Add --provider openai to use sora-2.
Add --model pixverse/pixverse-v5 to use the older PixVerse v5 video model.
Re-encode for iPhone compatibility:
ffmpeg -y -i "$VIDEO_PATH" \
-c:v libx264 -profile:v high -level 4.0 -pix_fmt yuv420p \
-c:a aac -b:a 128k -movflags +faststart \
/tmp/story-video-encoded.mp4
Upload media:
curl -s "${STORY_API_BASE_URL:-https://bedtimestories.bruce-hart.workers.dev}/api/media" \
-A "${STORY_API_USER_AGENT:-Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36}" \
-H "X-Story-Token: $STORY_API_TOKEN" \
-F "file=@/path/to/image.jpg"
curl -s "${STORY_API_BASE_URL:-https://bedtimestories.bruce-hart.workers.dev}/api/media" \
-A "${STORY_API_USER_AGENT:-Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36}" \
-H "X-Story-Token: $STORY_API_TOKEN" \
-F "file=@/tmp/story-video-encoded.mp4"
Create story:
curl -s "${STORY_API_BASE_URL:-https://bedtimestories.bruce-hart.workers.dev}/api/stories" \
-A "${STORY_API_USER_AGENT:-Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36}" \
-H "X-Story-Token: $STORY_API_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "TITLE",
"content": "STORY_CONTENT",
"date": "YYYY-MM-DD",
"image_url": "IMAGE_KEY",
"video_url": "VIDEO_KEY"
}'
Before finishing, verify: