复制下面这句话,粘贴给 Claude Code、Codex、Cursor 等 AI 编程工具,它会读取安装说明并在你确认后完成安装。
请阅读 https://ai.atlankj.com/install/asset/gh-ai-presenter-video-988e4fad78fa ,按照其中的说明把「ai-presenter-video」安装到你(当前 AI 工具)中。执行前先告诉我将运行的命令和写入的位置,等我确认。
查看 AI 将读取的安装说明正在读取 GitHub 原文…
内容来自 GitHub 原始文件,由原作者维护。在 GitHub 查看
Turn a topic (or finished script) plus ONE authorized adult presenter image into a complete, publish-ready presenter-led video: locked narration, avatar generation with lip-sync QA, captions, deterministic editing, loudness-normalized master/share encodes, and machine + visual acceptance reports.
Use this skill for new presenter videos AND for continuing, revising,
captioning, lip-sync-repairing, or re-exporting an existing presenter-video
job. The workflow is provider-neutral: pick generation capabilities from what
is actually available in the session (FAL video/image models via
image_generate and the video-gen plugin, TTS via text_to_speech, ASR via
the whisper/STT tooling, ffmpeg for everything deterministic).
Ported from cclank/lanshu-create-ai-presenter-video (MIT). Upstream body kept substantively verbatim in
references/; Hermes adaptations live in this hub file. Scripts are deterministic (no network, no credentials).
Skill dir resolution — upstream hardcoded its own agent's skills path.
In Hermes the loader expands ${HERMES_SKILL_DIR} to this skill's installed
directory, so every command below uses that token directly:
SKILL_DIR="${HERMES_SKILL_DIR}"
Shell variables do not persist between tool calls — re-paste the assignment (or the expanded path) in each terminal call that uses it.
Capability mapping — where the references say "a voice generation
capability", use text_to_speech (OpenAI/Edge/ElevenLabs per user config);
"presenter/avatar generation" → FAL image-to-video families (Kling, Wan,
MiniMax H3 etc.) through the configured video tooling, or an avatar/lipsync
endpoint the user has access to; "word-timestamp ASR" → whisper via the STT
tooling or faster-whisper in a venv; "deterministic compositor" → ffmpeg
filtergraphs, or the hyperframes skill when installed (the editing
reference has a HyperFrames section that maps directly onto it).
Visual QA — do the "normal-speed visual review" steps with
vision_analyze on the generated contact sheet plus sampled frames
(identity, mouth timing, hands, blinking, continuity). Numeric checks come
from the scripts' ffprobe output.
Paid-generation consent — remote avatar/TTS generation is billable.
Follow the upstream operating rules: before the first paid call state the
uploaded assets, requested seconds, known cost, pilot size, and retry
ceiling, and get the user's explicit go-ahead. Never upload the presenter
image to a remote provider before remote_upload_approved is true in
job.json.
Consent flags live under input — rights_confirmed,
adult_presenter_confirmed, remote_upload_approved, and
voice_clone_approved sit inside the input object of job.json (init
flags set them; hand-editing must target input.*, not the job root).
manual_input_review.* sits at the root. preflight.py distinguishes
errors (block everything) from remote_blockers (block only remote
generation) — local script/audio work may proceed while remote is blocked.
Start or resume a job. New job:
python3 "$SKILL_DIR/scripts/init_job.py" \
--job-dir ~/Videos/my-presenter-video \
--presenter-image /path/to/presenter.png \
--topic "explain context engineering in one minute" \
--duration 60 --aspect 9:16 \
--rights-confirmed --adult-presenter-confirmed
Use --script for an existing script file; other flags: --voice-sample,
--supporting-media, --width, --height, --fps, --watermark,
--cta. For an existing job, read job.json + QA reports and resume from
the earliest unfinished state — never regenerate accepted work.
Manual input review. Actually look at the presenter image
(vision_analyze) and listen to any voice sample; record findings by
setting the manual_input_review booleans in job.json, e.g.:
python3 - <<'PY'
import json
p = "~/Videos/my-presenter-video/job.json" # expand ~ or use an absolute path
import os; p = os.path.expanduser(p)
j = json.load(open(p))
j["manual_input_review"].update(image_viewed=True, single_clear_face=True,
image_has_no_unwanted_text=True)
json.dump(j, open(p, "w"), indent=2)
PY
Then gate:
python3 "$SKILL_DIR/scripts/preflight.py" ~/Videos/my-presenter-video/job.json
Proceed only when ok: true; do remote generation only when
remote_ready: true. Note: preflight also updates job.json in place
(records the report path) — re-read it after running rather than editing
a stale copy.
Lock content and audio — read references/generation.md. Script →
full narration via text_to_speech → ASR-verify the narration against the
script → record real durations. The locked audio is the master clock for
everything downstream.
Plan and generate the presenter — read references/generation.md.
Short low-cost pilot first; full run only after the pilot passes identity
and mouth-timing review.
Edit — read references/editing.md. Deterministic timeline driven by
the locked audio; captions and keyword callouts only after audio and media
are final.
Verify and deliver — read references/qa-recovery.md, render, then:
9:16, 1080×1920, 30fps; topic-derived videos target 45–75s; stock voice when no authorized sample; presenter-led layout with hook → 2–4 beats → close; no music/CTA unless requested; language inferred from the request.
references/generation.md — intake, content, voice, capability selection,
presenter prompts, paid generation, provider changes.references/editing.md — timeline contract, openings/closes, captions,
keyword-callout presets, HyperFrames composition, exports.references/qa-recovery.md — technical acceptance, visual acceptance, and
recovery for lip-sync/identity/hands/exposure/freeze/caption/audio faults.preflight.py requires ffprobe; on a bare box install ffmpeg first.input.*; editing them
at the job-json root silently does nothing (preflight keeps blocking).finalize_delivery.sh needs bash + jq + awk and a fully decodable input —
a truncated render fails the decode check by design, not by accident.Validated hands-on (Aug 2026): init_job.py → job.json with correct state
machine; preflight.py correctly blocked on unreviewed inputs, flipped to
ok: true after review booleans, and kept remote_ready: false until
input.remote_upload_approved; finalize_delivery.sh on a synthetic 5s
1080×1920 render produced decode-verified master (631kbit/s) + share encodes,
delivery-report JSON, and a 9-frame contact sheet, exit 0.
bash "$SKILL_DIR/scripts/finalize_delivery.sh" \
~/Videos/my-presenter-video/renders/rendered.mp4 \
~/Videos/my-presenter-video/outputs my-video
The finalizer preserves aspect ratio, runs two-pass loudness normalization
(program ≈ −16 LUFS), produces master + share encodes, decode-verifies
both, writes a delivery report JSON, and emits a nine-frame contact sheet.
Inspect the contact sheet with vision_analyze before claiming completion.