一键导入
srt
Extract subtitles (SRT) from video/audio/URLs and translate them into other languages (Perso AI STT).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Extract subtitles (SRT) from video/audio/URLs and translate them into other languages (Perso AI STT).
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
| name | srt |
| description | Extract subtitles (SRT) from video/audio/URLs and translate them into other languages (Perso AI STT). |
| allowed-tools | Bash(node scripts/srt.mjs *), Bash(node ../dubbing/scripts/resolve_key.mjs *), Bash(node ../dubbing/scripts/billing.mjs *), Bash(node ${CLAUDE_SKILL_DIR}/scripts/*), Bash(node ${CLAUDE_SKILL_DIR}/../dubbing/scripts/*) |
A skill that extracts the source-language subtitles of a video/audio via the Perso AI STT API — and then you (the agent) translate them into the requested languages.
Read, echo it, or pass it as a command-line argument. Workers send it in the XP-API-KEY header only.scripts/srt.mjs handles upload · transcription · SRT download by itself.srt.mjs in the background. Transcription takes minutes; a foreground shell timeout kills the run mid-way.en.--transcribe-only instead of --target. The downloaded original SRT is the final deliverable — skip the Translate section entirely.--target en,ja) — one subtitle project is created per input regardless of how many languages, and you translate its single original SRT into each of them.[progress] lines to chat, verbatim or summarized. The indented stderr detail logs don't need relaying. For a batch the worker streams a [progress] line per input and prints a [status] heartbeat (subtitles 3/20, with a next check ~Nm hint) — check the background output ~3 minutes after launch, then on the hinted interval, relaying new lines. Never invent percentages or ETAs.--host <claude-code|codex|cursor|antigravity|gemini> to the worker command, naming the agent you are running as, if you can tell. It only tags usage telemetry — never surface it to the user and never ask them about it. Omit it if unsure.dubbing folder must be installed next to srt (every install method ships them together; only a manual copy of the srt folder alone breaks this).Same as /dubbing — the first run registers the key itself (browser flow, file fallback); relay the worker's printed instructions. Never paste the key into chat.
After the key gate, collect the input (local path or URL — re-ask if missing) and run in the background:
node scripts/srt.mjs "<file|URL>" [--target en] [--space "space name"] [--out folder]node scripts/srt.mjs "<URL>" "<file>" --target en,janode scripts/srt.mjs "<folder>" [--target en] [--recursive] [--out folder]node scripts/srt.mjs "<file|URL>" --transcribe-onlyExtracted original SRT files are saved next to each source (or into --out), keeping the server's file name (…_OriginalSubtitle_….srt).
Save location — same policy as /dubbing: default is next to each source file; don't ask. On the session's first job, state it in the kickoff line and start right away. A folder the user named earlier in this session keeps applying (--out "<folder>") until they change it; translated SRTs go to the same folder as their originals. Exception: when every input is a URL, ask where to save before starting.
Space selection — with several workspaces the worker stops before uploading, prints [space-select] lines (name | (plan) | remaining credits) and stops. Show the user ONLY those options (no internal numbers), ask which one, and re-run with --space "<space name>". One dubbing-capable space → no question; PERSO_SPACE_SEQ pins it.
Media over the plan limit — this skill does not auto-split. If the worker reports the media exceeds the plan's length/size limit, relay its message: the user can split/trim the file themselves or upgrade the plan, then retry.
Credits — each subtitle project consumes credits in proportion to the media length (one project per input). The server's billing is authoritative; don't quote exact prices.
When extraction finishes, the worker prints one line per input, carrying every target language:
[srt-original] {"input":"video.mp4","langs":["en","ja"],"path":"C:\\clips\\video_OriginalSubtitle_2026-07-15.srt","seq":389259}
If langs is null (a --transcribe-only run), there is nothing to translate: deliver that file to the user as-is and stop here.
Show translation progress. STT extraction is done, but translating into each language takes time too — make it visible. Before you start, post one line naming the languages you'll produce (e.g. "자막 추출 완료 — 이제 일본어·영어로 번역합니다"). After you finish and save each language's file, post a one-line update (e.g. 일본어 ✓ (1/2)), so the user sees per-language progress like a multi-language dub. A long file may stay quiet within a single language while you batch its sections — that's fine.
For each [srt-original] line, translate the one file at path into every language in langs:
Step 1 — read the whole file first and build context. Read the SRT at path end to end before translating anything, and pin down:
Step 2 — translate into each language in langs, section by section (batch long files, but apply the tone and terms fixed in Step 1 to every batch; Step 1 is done once per file, not per language):
-->), blank lines, and the cue count exactly as they are — never alter timestamps or merge/split cues while translating (retiming is a separate later pass, Step 5).Step 3 — save: UTF-8, in the same folder, one file per language named {stem}_{lang}_Subtitle.srt, where stem is the input's file name without its extension — take it from the input field of the [srt-original] line (e.g. "input":"video.mp4" + ["en","ja"] → video_en_Subtitle.srt and video_ja_Subtitle.srt; for URL inputs use the media title or a short slug). Do NOT derive the stem from the downloaded file's name — the server builds that from the project title. Keep the original SRT file — don't delete or overwrite it.
Step 4 — verify each saved file (offline — no key, no network, no credits):
node scripts/srt.mjs --check "<translated.srt>" --source "<original .srt>"
[check] FAIL lines mean the file breaks cue alignment, the 2×42 layout, or the reading-speed cap. Rewrite ONLY the listed cues (same meaning-first priority), save, and re-run until no FAIL remains. WARN lines are optional polish. Run this before Step 5 — after retiming, the cue count no longer matches the source by design.
Step 5 — readability retiming (offline; once per delivered file, after the check passes):
node scripts/srt.mjs --retime "<translated.srt>"
It extends too-fast cues into the following silence and merges short neighbouring cues into one 2-line event (Netflix-style), rewriting the file in place — cue numbering may change; the untouched original SRT keeps the 1:1 timing map. Then:
[retime] merged lines: if a merge shows a punchline early or completes an intentionally interrupted line, restore those two cues with their original timings from the pre-merge state.Report the saved translated file paths to the user, mentioning the originals are kept alongside. If the user wants to open the subtitle project on Perso, build the link from the [srt-original] line's seq: https://perso.ai/en/workspace/vt/stt/<seq>.
The worker saves a state file (*.srtresume.json, next to the source or in --out) from the moment the plan is known and after every completed piece, so a run that dies for ANY reason (credits, crash, killed shell) resumes without redoing paid work:
node scripts/srt.mjs --resume "<state-file>"
Completed inputs are skipped (their [srt-original] lines are re-printed), and the state file is deleted when everything finishes.
Re-running the original command while a state file exists is blocked — the worker prints [resume-check] lines instead of re-billing. Relay the printed --resume command and run that. Delete the state file only if the user explicitly chooses to pay for the completed parts again — never on your own.
On an insufficient-credits stop: deliver the completed SRTs (and translate them), then relay the worker's guidance and resume command verbatim — plain stdout (not [progress]), so don't drop it while summarizing. The guidance points to the dubbing skill's billing.mjs (node ../dubbing/scripts/billing.mjs options) for a payment link — the flow is described in the dubbing SKILL.md's "Plan upgrade & credits" section. You only ever hand the link to the user — never open it or complete payment yourself.
The dubbing skill's environment variables apply unchanged (PERSO_API_BASE/PERSO_MEDIA_BASE — https perso.ai hosts only, PERSO_SPACE_SEQ, XP_API_KEY, PERSO_NO_WATCH, PERSO_NO_OPEN, PERSO_QUEUE_WAIT_MS, PERSO_NO_UPDATE_CHECK, PERSO_NO_TELEMETRY).