← Speak AICONTENT HISTORY
WHAT CHANGED
Update to Speak AI
Snapshot Nov 2, 2026 · 18:11 UTC · version 1.41.1
Collection source: downloaded plugin package.
First saved snapshot
No earlier snapshot is available to establish a change.
Save Speak AI and check future changes in Following.
Up to 10 plugins free · no card required.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"description": "Turn Speak AI recordings into shareable output. Use this when someone asks for a highlight clip, a soundbite, a reel, subtitles, a caption track, an SRT or VTT file, a transcript exported as PDF, DOCX, TXT, CSV, MD, HTML or JSON, a merged export across several recordings, or an embeddable player or transcript widget for a website. Walks through finding the moment in a timestamped transcript, cutting the clip, waiting for it to finish processing, exporting captions in a supported format, and publishing an embed. Covers search_media, list_media, get_media_status, get_transcript, get_captions, create_clip, get_clips, update_clip, delete_clip, export_media, export_multiple_media, create_embed, check_embed, update_embed and get_embed_iframe_url.",
"included_files": [
{
"relative_path": "agents/openai.yaml",
"size_in_bytes": 286
}
],
"name": "clips-and-captions",
"skill_md_contents": "---\nname: clips-and-captions\ndescription: Turn Speak AI recordings into shareable output. Use this when someone asks for a highlight clip, a soundbite, a reel, subtitles, a caption track, an SRT or VTT file, a transcript exported as PDF, DOCX, TXT, CSV, MD, HTML or JSON, a merged export across several recordings, or an embeddable player or transcript widget for a website. Walks through finding the moment in a timestamped transcript, cutting the clip, waiting for it to finish processing, exporting captions in a supported format, and publishing an embed. Covers search_media, list_media, get_media_status, get_transcript, get_captions, create_clip, get_clips, update_clip, delete_clip, export_media, export_multiple_media, create_embed, check_embed, update_embed and get_embed_iframe_url.\nlicense: MIT\nmetadata:\n server-version: \"1.41.1\"\n categories: \"clips, exports, media, embed-other\"\n---\n\n# Clips and captions\n\nThe user's explicit instructions take priority over this skill. When they ask for something different from the steps below, do what they asked, and confirm with them before any action that deletes, overwrites, or sends data outside Speak AI.\n\nThis skill covers the tools that produce something a person can watch, read, or\npublish. Four categories matter here: clips (4 tools), exports (2 tools), media\n(19 tools), and embed-other (7 tools).\n\nEvery step below needs a `mediaId`. Get one from `search_media` or `list_media`\nbefore you do anything else.\n\nPer-tool reference pages follow the pattern\n`https://docs.speakai.co/mcp/tools/<category-id>/<tool_name>/`, for example\n<https://docs.speakai.co/mcp/tools/clips/create_clip/>.\n\n## Step 1: Find the media\n\nUse `search_media` when you are looking for a topic, a phrase, or a theme across\nthe whole library. It searches transcripts, insights, and metadata, and returns\nmatching media with excerpts, tags, and sentiment.\n\n```sh\nspeakai-mcp call search_media '{\n \"query\": \"pricing objection\",\n \"startDate\": \"2026-01-01T00:00:00Z\",\n \"endDate\": \"2026-08-07T00:00:00Z\"\n}'\n```\n\n`search_media` scopes results by date range and defaults to the current year. If\nyou get nothing back, widen `startDate` before you conclude the phrase is not\nthere.\n\nUse `list_media` instead when you already know the folder, the name, or the date\nrange and you just want the ids.\n\n## Step 2: Confirm the media is ready\n\nCall `get_media_status` with `mediaId`. The states are `queued`,\n`preparing`, `processing`, `preparingAnalysis`, `processed`, and `failed`. Only `processed` media\nhas a complete transcript, and a clip or export built from anything earlier is\nincomplete or empty.\n\nIf the state is not `processed` and not `failed`, wait and poll again. If the\nstate is `failed`, stop and tell the user. Do not create a clip from failed\nmedia.\n\n## Step 3: Find the moment\n\nCall `get_transcript` with `mediaId`. It takes no other parameters. The response\ncarries speaker labels and timestamps, so you read it to pick the start and end\nof the segment you want. Times you pass to `create_clip` are in seconds and\naccept decimals.\n\nYou can also read the same transcript through the resource\n`speakai://media/{mediaId}/transcript`.\n\nTwo rules when you pick a range:\n\n- Start a little before the first word and end a little after the last one.\n Cutting exactly on the timestamps clips the first and last syllable.\n- Check that the speaker labels are right first. If they are wrong, fix them\n with `update_transcript_speakers` before you export anything that shows\n speaker names.\n\nDuring a live meeting recording `get_transcript` returns the partial transcript\nso far. Use `get_live_meeting_transcript` if you only want the sentences added\nsince your last call. Do not clip from a meeting that is still recording, since\nthe timestamps you read may shift once the final transcript is written.\n\n## Step 4: Create the clip\n\nCall `create_clip`:\n\n| Field | Required | Notes |\n| --- | --- | --- |\n| `title` | yes | Non-empty string. |\n| `mediaType` | yes | Either `audio` or `video`. Nothing else is accepted. |\n| `timeRanges` | yes | Array with at least one entry. Each entry is `{ mediaId, startTime, endTime }` in seconds, and `endTime` must be greater than `startTime`. |\n| `description` | no | Free text. |\n| `tags` | no | Array of strings. |\n| `mergeStrategy` | no | Only `CONCATENATE`. This is the default. |\n\nBecause `timeRanges` accepts a different `mediaId` per entry, you stitch\nsegments from several recordings into one clip in a single call. The maximum\ntotal clip duration is 30 minutes across all ranges.\n\n```sh\nspeakai-mcp call create_clip '{\n \"title\": \"Pricing objection highlights\",\n \"mediaType\": \"video\",\n \"timeRanges\": [\n { \"mediaId\": \"media_example_0001\", \"startTime\": 412.5, \"endTime\": 448.0 },\n { \"mediaId\": \"media_example_0002\", \"startTime\": 95.0, \"endTime\": 121.25 }\n ],\n \"tags\": [\"pricing\", \"objections\"]\n}'\n```\n\nThe same call over HTTP. Send your API key on every call, in `x-speakai-key` or as\n`Authorization: Bearer <key>`. There is no access token to fetch.\n\n```sh\ncurl -X POST https://api.speakai.co/v1/clips \\\n -H \"x-speakai-key: speak_sk_example_000000000000\" \\\n -H \"Content-Type: application/json\" \\\n -d '{\n \"title\": \"Pricing objection highlights\",\n \"mediaType\": \"video\",\n \"timeRanges\": [\n { \"mediaId\": \"media_example_0001\", \"startTime\": 412.5, \"endTime\": 448.0 }\n ]\n }'\n```\n\n## Step 5: Wait for the clip, then get the download URL\n\nClips process asynchronously. The states are `queued`, `processing`,\n`completed`, and `failed`. `create_clip` returns as soon as the job is accepted,\nso the response does not contain a playable file.\n\nCall `get_clips` with the `clipId` to poll. A single-clip lookup returns the\ndownload URL once the clip is processed. Listing without a `clipId` returns the\nset and is meant for browsing, not for fetching a file.\n\n```sh\nspeakai-mcp call get_clips '{ \"clipId\": \"clip_example_0001\" }'\n```\n\n`get_clips` also accepts `folderId` and `mediaIds` to filter the list.\n\nTo rename a clip or fix its tags afterwards, use `update_clip` with `clipId`\nplus any of `title`, `description`, or `tags`.\n\n`delete_clip` is destructive. It permanently removes the clip and the media file\ncreated for it. Confirm with the user before you call it.\n\n## Step 6: Captions and subtitle files\n\nThere are two different things here, and they are not interchangeable.\n\n**`get_captions`** takes only `mediaId` and returns the caption records for a\nmedia file as data. Captions are stored separately from the full transcript and\nare already formatted for display and subtitling. Use this when you want the\ncaption text inside the conversation.\n\n```sh\nspeakai-mcp call get_captions '{ \"mediaId\": \"media_example_0001\" }'\n```\n\n**`export_media`** is what you use when the user wants an actual subtitle file.\nThe subtitle formats in the export enum are `srt`, `vtt`, and `ttml`.\n\n```sh\nspeakai-mcp call export_media '{\n \"mediaId\": \"media_example_0001\",\n \"fileType\": \"vtt\",\n \"isSpeakerNames\": true,\n \"isTimeStamps\": true\n}'\n```\n\nThere is no format parameter on `get_captions`, and there is no way to export\ncaptions for only a time range. Exports always cover the whole media file. If\nyou need a subtitle file for a segment, create the clip first. A clip has its own\nassociated media file, which is why `delete_clip` removes both, so read the\n`get_clips` response for that file and export against it.\n\n## Step 7: Exports\n\n`export_media` takes one `mediaId` and a `fileType`. The `fileType` field is\nbacked by the shared `ExportFormatType` enum, so these are the accepted values:\n\n`csv`, `csv-insights`, `csv-transcript`, `csv-transcript-sentiment`,\n`csv-text-sentiment`, `docx`, `html`, `json`, `md`, `pdf`, `sourceFile`, `srt`,\n`ttml`, `txt`, `vtt`, `mp4`.\n\nThe tool description and the CLI help both call out the six common ones, which\nare `pdf`, `docx`, `srt`, `vtt`, `txt`, and `csv`. Prefer those unless the user\nasks for something specific. Do not offer a format that is not on the list\nabove.\n\nOptional flags on `export_media`:\n\n- `isSpeakerNames`, `isSpeakerEmail`, `isTimeStamps` control what appears in the\n output.\n- `isInsightVisualized` includes insight visualizations.\n- `isRedacted` applies PII redaction, and `redactedCategories` narrows it to\n specific categories.\n\n`export_multiple_media` takes `mediaIds` (an array) and the same `fileType`,\nplus `isMerged` to combine everything into one file and `folderId` to say where\nthe merged export belongs. It accepts `isRedacted` but not `redactedCategories`,\nso per-category redaction is single-media only.\n\n```sh\nspeakai-mcp call export_multiple_media '{\n \"mediaIds\": [\"media_example_0001\", \"media_example_0002\"],\n \"fileType\": \"docx\",\n \"isSpeakerNames\": true,\n \"isMerged\": true\n}'\n```\n\n## Step 8: Embeds\n\nAn embed is a player and transcript widget you put on a web page. It is reachable\nfrom outside the workspace, so treat creating one as publishing. Ask the user\nbefore you create an embed for media you did not just create with them.\n\n1. Call `check_embed` with `mediaId` first. It tells you whether an embed already\n exists and returns its configuration. Creating a second embed for the same\n media leaves you with two live widgets.\n2. Call `create_embed` with either `mediaId` for a single recording or\n `folderIds` for a folder or library view. Both fields are optional in the\n schema, so send at least one or you get an embed with no scope.\n3. Call `get_embed_iframe_url` with `mediaId` to get the URL you paste into the\n page. It only takes `mediaId`, so it resolves single-media embeds, not\n folder embeds.\n4. Call `update_embed` with `embedId` to change appearance and behaviour. The\n `meta` object holds the toggles: `backgroundImg`, `logo`, `logoDark`\n (dark-mode logo; must be an uploaded logo, the MCP cannot upload\n it), `theme` (`light` or `dark` forces the viewer theme), `backgroundColor`\n (hex), `fontFamily` (a Google Fonts name), `primaryColor`, `titleColor`,\n `chatWelcomeMessage`, `assistantTemplateId`, `isTitle`, `isDescription`, `isRemarks`, `isDataVizDownloadable`, `isSEOIndexing`,\n `isPromptAsk`, `isPromptHistory`, `isMediaExport`, `callToActionButtons`, and\n `features`. `update_embed` also accepts `mediaId`, `folderIds`,\n `privacyMode`, and `embedType`.\n\n```sh\nspeakai-mcp call create_embed '{ \"mediaId\": \"media_example_0001\" }'\nspeakai-mcp call get_embed_iframe_url '{ \"mediaId\": \"media_example_0001\" }'\n```\n\nSet `isSEOIndexing` deliberately. Turning it on means search engines index the\ntranscript of the recording.\n\n## Edge cases that actually bite\n\n**Media is still processing.** This is the most common failure. `get_transcript`\non unprocessed media returns little or nothing, so the clip you build from it\nlands on the wrong seconds and the export is empty. Always check\n`get_media_status` first, and poll rather than retrying the clip call.\n\n**Clip states are not errors.** A `queued` or `processing` clip with no download\nURL is normal. Poll `get_clips` with the `clipId`. Only treat `failed` as a\nfailure, and re-create the clip rather than retrying the same job.\n\n**Time ranges are validated.** `endTime` must be greater than `startTime`, and\nthe total across all ranges cannot exceed 30 minutes. A long recording will not\nfit in one clip, so split it.\n\n**Empty search results.** `search_media` defaults to the current year. A search\nthat finds nothing usually needs a wider `startDate`, not a different query.\n\n**Pagination.** `list_media` uses 0-based `page` with `pageSize` defaulting to 25\nand capped at 100. Page through results instead of raising `pageSize`, because\n`include: [\"transcription\"]` puts a full transcript on every row and an oversized\nresponse is rejected.\n\n**Permissions.** Clip, export, and embed calls all write. If the API key is\nread-only or the user does not have access to the folder, you get an\nauthorization error rather than an empty result. Report it instead of retrying.\n\n**Deleting is permanent.** `delete_clip` removes the clip and its media file.\nThere is no undo and no separate archive step.\n\n**Speaker names are baked in.** Once you export with `isSpeakerNames: true`, the\nfile carries whatever the labels were at export time. Fix labels first with\n`update_transcript_speakers`, then export.\n\n**Redaction is opt-in.** Exports are not redacted unless you set `isRedacted`.\nIf the user mentions customer names, personal details, or anything regulated,\nset it.\n"
}SHA-256 of public snapshot: 934e4a1a64b58e34eb7e4bba04ff6e1b197252fcaa876ab6fdb8347ab6dfe23d