{"id":48126,"plugin_id":"plugin_asdk_app_6abf2f857c3c8191817ac3af7ff6e68a","kind":"skill","collection_source":"plugin_package","comparison_source":null,"observed_at":"2026-10-24T13:35:32.618Z","digest":"fffb830ee477f12289c2558aac58092281d18347d17edc2dae24d594a8d48cae","against":null,"payload":{"description":"Transcribe speech in an audio or video file with Hopper speech-to-text (Nemotron ASR), with word timestamps. Takes WAV, MP3, M4A, voice memos and video such as MP4 or MOV (decoded with ffmpeg). Needs no setup: the first use registers a key for the agent itself. Use when the user says \"transcribe this\", \"what does this recording say\", \"check my video\", \"what's said in this video\", \"review the voiceover in my launch video\", \"captions for my video\", \"subtitles\", \"caption this\", \"meeting notes from this recording\", \"summarize this call\", \"pull quotes from this interview\", \"speech to text\" or \"STT\". Works from the spoken words only, not the visuals. Not for generating audio (hopper-speak) or running an LLM (hopper-try).","included_files":[{"relative_path":"agents/openai.yaml","size_in_bytes":215},{"relative_path":"scripts/hopper_voice.py","size_in_bytes":20060}],"name":"hopper-transcribe","skill_md_contents":"---\nname: hopper-transcribe\ndescription: 'Transcribe speech in an audio or video file with Hopper speech-to-text (Nemotron ASR), with word timestamps. Takes WAV, MP3, M4A, voice memos and video such as MP4 or MOV (decoded with ffmpeg). Needs no setup: the first use registers a key for the agent itself. Use when the user says \"transcribe this\", \"what does this recording say\", \"check my video\", \"what''s said in this video\", \"review the voiceover in my launch video\", \"captions for my video\", \"subtitles\", \"caption this\", \"meeting notes from this recording\", \"summarize this call\", \"pull quotes from this interview\", \"speech to text\" or \"STT\". Works from the spoken words only, not the visuals. Not for generating audio (hopper-speak) or running an LLM (hopper-try).'\n---\n\n# Transcribe with Hopper\n\n**Pick the path first.** In ChatGPT, or wherever the shell can't reach Hopper's API, use the Hopper connector's `transcribe` tool: pass an attached file as it is (`audio_file`), or a public URL. ChatGPT's sandbox can't resolve Hopper's domains, so the script fails there. Where you can run commands with network access (Codex CLI, Claude Code), use this skill's script instead: it reads files on this machine directly, in any format, and uses this agent's own Hopper key, so its usage can move to the user's account later.\n\n`${CLAUDE_SKILL_DIR}` is the folder holding this file (if your host doesn't fill it in, use that folder's absolute path). The script needs network access to `withhopper.com` and `api.withhopper.com`, and writes the agent's key to `~/.config/hopper/`. In a sandbox (Codex), request escalated permissions for the first command, with the reason \"Use Hopper transcription: create this agent's own Hopper key and transcribe the audio (network to withhopper.com; writes ~/.config/hopper)\", and suggest allowing commands that start with `python3` and this script's path so later calls don't ask again. Exit code 3 (`HOPPER_SANDBOX_BLOCKED`) means the sandbox blocked it: rerun the same command with escalation. If the user declines, say Hopper couldn't run and ask how to continue; don't switch to another tool silently. Explicit instructions from the user override these steps.\n\n## Transcribe\n\n```bash\npython3 ${CLAUDE_SKILL_DIR}/scripts/hopper_voice.py transcribe path/to/recording.m4a          # plain text\npython3 ${CLAUDE_SKILL_DIR}/scripts/hopper_voice.py transcribe call.wav --json                # text, words with start/end seconds\n```\n\n- **Formats:** 16-bit mono WAV goes up as is. Anything else (MP3, M4A, AIFF, FLAC, MP4, MOV) is decoded with `ffmpeg`; if it's missing, tell the user the one install command the script prints.\n- **Length:** long recordings are split into uploads under the 25 MB limit and the timestamps are joined back, so any length works; it's about $0.05 per hour of audio.\n- **A URL:** download it to a temp file first, then transcribe the file.\n- **Output:** answer what the user asked (a summary, action items, a quote) from the transcript, and quote it exactly when they want exact words. Use `--json` for captions, timestamps or who-said-when questions. The model writes lowercase text without punctuation, English only, and can mishear names and brands: say so when a name matters.\n- `no speech detected` means the file has no audible speech, not an error.\n\n## Key\n\nThe first run with no `HOPPER_API_KEY` (environment or the project's `.env`) registers a key for the agent itself with a small trial credit (no sign-up, [agent registration](https://withhopper.com/auth.md)) and saves it to `~/.config/hopper/credentials.json`, mode 600. Never print it or copy it into the project. `status` says where the key comes from without showing it.\n\nTo move it to the user's account, see the next section.\n\n## When the trial credit runs low\n\nThe agent's own key starts with a small trial credit. When it runs low the script prints `HOPPER_HANDOVER low_credit` (exit 0), and when it runs out, `HOPPER_HANDOVER out_of_credit` (exit 4). Either way:\n\n1. Tell the user once, in a line or two, what Hopper has done for this task (the `used=` text) and that the agent's Hopper key is running low, and offer to keep it on their own Hopper account. Don't mention it again in the same task if they decline.\n2. If they agree, confirm their email (`git config user.email` is a good guess) and run `claim <email> --no-wait`. Show the link and the 6-digit code; the user enters the code on withhopper.com, never in this chat.\n3. Run `claim <email>` to wait. When it prints `Claimed`, carry on: the script uses the account key from then on, with the same history.\n\n## In an application's code\n\nTo add Hopper speech-to-text (Nemotron ASR) to an application, follow https://docs.withhopper.com/stt: `POST https://api.withhopper.com/v1/audio/transcriptions` (`model: nemotron-asr`, 16-bit PCM or WAV) for files, or the WebSocket stream for live audio.\n"},"changes":[],"summary":"First saved snapshot. No earlier version is available for comparison.","summary_kind":"deterministic","summary_metadata":{}}