关于 PrismPoster Creator Tools
PrismPoster Creator Tools 是为视频和社交媒体创作者提供的 TypeScript 工具集,也包含本地 MCP 服务。它提供带来源的社交平台安全区域数据,以及字幕、编码、比例和媒体元数据处理功能。
主要功能
- 01计算画面比例与裁切方案
- 02查询平台尺寸及有来源的安全区域
- 03解析、转换和调整字幕时间
- 04计算码率、文件大小和时间码
- 05提取调色板并读取图像元数据
- 06检测 C2PA 与 AI 来源标记
适用场景
- 01为不同社交平台准备视频画幅
- 02转换或校准字幕文件
- 03估算满足文件大小限制的码率
- 04检查上传媒体中的来源信息
MCP 相关
该项目包含零运行依赖的 stdio MCP 服务,向 AI 客户端提供平台尺寸与安全区域、比例裁切、码率和字幕转换等只读工具。计算在本地执行,无网络请求。
配置
远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。
https://www.prismposter.com/api/mcpclaude mcp add --transport http com-prismposter-creator-tools https://www.prismposter.com/api/mcp{"mcpServers":{"com-prismposter-creator-tools":{"type":"http","url":"https://www.prismposter.com/api/mcp"}}}在 Cursor 中打开{"servers":{"com-prismposter-creator-tools":{"type":"http","url":"https://www.prismposter.com/api/mcp"}}}在 VS Code 中打开{"mcpServers":{"com-prismposter-creator-tools":{"type":"http","url":"https://www.prismposter.com/api/mcp"}}}{"mcpServers":{"com-prismposter-creator-tools":{"serverUrl":"https://www.prismposter.com/api/mcp"}}}命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。
工具
详细介绍
creator-tools
面向视频和社交媒体创作者的零依赖 TypeScript 工具:宽高比计算、敲击测节拍、字幕解析与转换、带有来源依据的各平台画面尺寸和安全区域、编码计算器、调色板提取、GIF 编码、图像元数据,以及 C2PA / AI 来源检测。
无运行时依赖。不进行网络调用。可在浏览器、Node 和 worker 中运行。返回的每个数值都可以手动核验;如果平台没有公布某个数值,工具会如实说明,而不会凭空编造。
npm install @prismposter/creator-tools
为什么要做这个项目
这些计算大多散落在互相引用的博客文章中,而且不少引用的数字都是错的。促成这个库诞生的一点是:**网上所有“TikTok 安全区域”像素表都是编造的。**TikTok 发布的是叠加模板,而非固定边距——被遮挡的区域会随画面尺寸、字幕长度和正在投放的广告格式而变化。不存在正确的固定值,因此这个库会返回 null 并解释原因,而不是提供一个看似合理的数字。
整个软件包都遵循这条原则:
- **推导出的数值就应由计算得出。**宽度为 1080 的 9:16 画面,高度是 1920,因为这就是比例所决定的。测试套件会验证
social-sizes中的每种尺寸是否符合其声明的比例。 - **引用的数值会注明来源。**每个安全区域都链接到其数据来源的官方页面。
safeAreaSourceUrl(placement)会返回该 URL。 - **未知也是一种值,而非空白。**未公布任何数据的平台会获得明确的
kind: 'unpublished',并附上原因。
模块
aspect-ratio
用于即将编码的画面的比例运算。处理非整数电影比例(2.39:1)的方式与处理 16:9 相同。
import {
simplifyRatio, cropToRatio, padToRatio, alignToBlock,
} from '@prismposter/creator-tools/aspect-ratio';
simplifyRatio({ width: 1920, height: 1080 }); // { w: 16, h: 9 }
cropToRatio({ width: 1920, height: 1080 }, { w: 9, h: 16 });
// { result: { width: 608, height: 1080 },
// removed: { top: 0, right: 656, bottom: 0, left: 656 },
// areaKept: 0.3167 }
// Codecs want even dimensions; H.264 chroma subsampling makes an odd
// width an encoder error or a silent rescale.
alignToBlock({ width: 1081, height: 607 }); // { width: 1082, height: 608 }
alignToBlock({ width: 1080, height: 1920 }, 16); // { width: 1088, height: 1920 }
裁剪后多出的奇数像素始终分配到下边缘或右边缘。这是人为规定的,但能保持一致——如果每次调用时分配方式不同,一批片段最终就会出现一像素的错位。
social-sizes
各平台的画面尺寸和安全区域,以及对应来源。
import {
getPlacement, frameSize, safeAreaPx, safeAreaBox, safeAreaSourceUrl,
} from '@prismposter/creator-tools/social-sizes';
const reels = getPlacement('instagram-reels')!;
frameSize(reels); // { width: 1080, height: 1920 }
safeAreaPx(reels); // { top: 269, bottom: 672, left: 65, right: 65 }
safeAreaBox(reels); // { width: 950, height: 979 }
safeAreaSourceUrl(reels); // Meta's Reels ads-guide page
const tiktok = getPlacement('tiktok-video')!;
safeAreaPx(tiktok); // null — and that is the correct answer
tiktok.safeArea.reason; // explains why no fixed table can be right
Meta 公布的 Reels 和 Stories 安全区域为顶部 14%、底部 35%、左右各 6%。在 1080×1920 的画面上,分别是 269 / 672 / 65 px。底部占三分之一不是笔误。
safeAreaPx 返回 null 是有意义的——应向用户说明“该平台未公布固定安全区域”。不要用零替代,也不要借用其他平台的数据。
subtitles
支持 SRT、WebVTT 和 ASS/SSA 的解析、转换与时间编辑。所有格式都会先转换为统一的中性 Cue 结构,而不是直接在格式之间互转:否则六种格式需要三十个转换器,而每个转换器都可能悄悄采用不同的舍入规则。
import { convert, parse, shift, scale, deoverlap }
from '@prismposter/creator-tools/subtitles';
const { output, warnings } = convert(srtText, 'vtt');
// Fix subtitles authored against a different frame rate.
scale(parse(srtText).cues, 23.976 / 25);
// Nudge everything 500ms later; cues pushed before zero clamp to zero.
shift(cues, 500);
// Clip overlaps so only one cue is ever on screen.
deoverlap(cues);
解析过程具有容错性:格式错误的区块会产生警告并被跳过,不会因此丢失文件中其他 899 条字幕。支持处理 UTF-8 BOM 和 CRLF 行尾。会移除 VTT 的 NOTE / STYLE 区块和内联标签(<v Roger>、<i>),也会移除 ASS 覆盖区块({\an8})。
ASS 使用厘秒,因此往返转换 ASS 格式时,精度会损失到 10 ms 以下。convert() 会在 warnings 中告知你这一点,而不是让你事后才发现。
tempo
敲击测节拍,以及编辑时间线所需的节拍计算。
import { estimateTempo, beatMs, noteMs, beatGrid, snapToBeat }
from '@prismposter/creator-tools/tempo';
estimateTempo(tapTimestamps);
// { bpm: 128.02, taps: 16, spreadMs: 8.4, discarded: 1 }
beatMs(120); // 500
noteMs(120, 'quarter', { triplet: true }); // 333.333
beatGrid(120, 10_000); // [0, 500, 1000, … 10000]
snapToBeat(480, 120); // { timeMs: 500, deltaMs: 20 }
估算器取滑动窗口内的中位数,而非平均值。敲击序列有两种情况会让平均值表现不佳:用户寻找节拍时,最初几次敲击会偏晚;漏敲一次则会产生约为真实周期两倍的间隔。异常值会依据中位数剔除,因为平均值早已被拖偏,足以让错误间隔落入容差范围。
spreadMs 会告知你结果的可信程度——低于约 20 ms 表示敲击节奏稳定,高于 60 ms 则说明估算结果不够可靠。beatGrid 会根据每个位置的索引计算数值,而非累加,因此长序列不会产生漂移。
encoding
文件大小、比特率、时间码和帧数。
import { fileSizeBytes, targetBitrateKbps, bitsPerPixel, toDropFrame }
from '@prismposter/creator-tools/encoding';
fileSizeBytes(60, 8_000); // 60_000_000 bytes
targetBitrateKbps(120, 50_000_000); // kbps to hit a 50 MB cap
bitsPerPixel(1920, 1080, 30, 8_000); // 0.1286
toDropFrame(1_800, 29.97); // '00:01:00;02'
单位约定,仅说明一次:比特率使用十进制(1 Mbps = 1,000,000
位/秒,所有编码器和平台规范都是如此),文件大小使用二进制
(1 MiB = 1,048,576 字节,所有操作系统的报告方式都是如此)。混用两者
正是在线计算器结果相差约 5% 的原因。formatBytesBinary 和 formatBytesDecimal
是两个独立函数,因此始终明确选择所用单位。
丢帧时间码跳过的是标签,而非帧:每分钟开始时都会省略编号 00 和 01, 但每十分钟一次除外。这样才能让 29.97 时间码与实际时间保持一致;不丢帧时间码 每小时会偏差约 3.6 秒。
palette
中值切割颜色量化,以及在其返回的颜色上放置文本时所需的对比度计算。
import { extractPalette, toHex, readableTextOn } from '@prismposter/creator-tools/palette';
const swatches = extractPalette(pixels, 5); // pixels: { r, g, b }[]
swatches.map(toHex); // ['#1b2430', '#3f6d8e', ...]
readableTextOn(swatches[0]); // { onColour: 'black' | 'white', ratio: 8.7 }
选择的切分位置是主导轴上最宽的间隙,而非像素数量的中位数。教科书式的中值切分会让每个色框包含相同数量的像素,这对于照片来说恰恰是错误的:大片纯色天空会被反复细分,而小块高饱和度点缀色——设计师真正想要的那种颜色——则会与相邻颜色取平均后消失。按间隙切分就能保留它。
如果源图像的不同颜色少于请求的色块数,返回的色块就会更少。用相近颜色填充结果,只会得到一份无法如实反映图像的调色板。
provenance
这个文件是否带有来源信息?其中是否表明该素材由 AI 生成?
import { inspectProvenance } from '@prismposter/creator-tools/provenance';
inspectProvenance(bytes);
// { hasC2paManifest: true, hasIptcSourceType: true, hasProvenance: true,
// declaresAiGenerated: true, declaresCapture: false,
// digitalSourceTypes: ['.../digitalsourcetype/trainedAlgorithmicMedia'],
// assertionLabels: ['c2pa.actions.v2', 'c2pa.claim.v2'],
// manifestOffset: 41, signatureVerified: false }
目前有两种标记,常常被混为一谈:
- C2PA 清单——JUMBF 容器中的加密签名内容凭证。
- IPTC 数字来源类型——普通的 XMP/EXIF 字符串,没有任何签名,任何人都可以用
exiftool写入。
文件可能带有其中一种、两种,或两种都没有。之所以分别报告,是因为它们的证明力截然不同;许多“AI 检测器”的介绍却把第二种说得仿佛是第一种。
它不会验证签名。signatureVerified 始终为 false,这是有意为之。要证明清单有效,需要完整的 C2PA 信任列表和证书链验证——这正是
c2patool 和 c2pa-node 的用途;如果你要判断可信度,就应该使用它们。此处回答的是一个成本更低的问题,而那些工具对于这个问题又显得过于强大;在无法携带原生二进制文件的无服务器运行时中,这个问题往往也无从解决:是否存在凭证?它声称了什么?
当你在处理上传队列、只把值得关注的文件转交给真正的验证器时,这正是你需要的检查。
**清单存在,不代表清单可信。**任何人都可以用自签名证书签署任何内容,包括谎言。
image-metadata
读取文件对自身的描述——更重要的是,留意它何时什么也没说。
import { readImageMetadata, isStripped } from '@prismposter/creator-tools/image-metadata';
const meta = readImageMetadata(bytes);
meta.format; // 'jpeg' | 'png' | 'webp' | 'gif' | ...
meta.fields; // parsed EXIF / XMP / text fields
isStripped(meta);
大多数平台在上传时都会剥除元数据,因此没有元数据的图像才是常态,并非可疑情况。isStripped 的存在就是为了让你能向用户解释这一点,而不是给他们显示一张空表。
gif
动画 GIF 编码器:全局调色板、LZW、子块,应有尽有。
import { encodeGif, buildGlobalPalette, indexFrame } from '@prismposter/creator-tools/gif';
const palette = buildGlobalPalette(frames, 256);
const bytes = encodeGif({ width, height, palette, frames });
GIF 最多支持 256 种颜色,且所有帧共用一个全局调色板,因此量化器比编码器更重要——这也是它沿用 palette 的中值切割算法,而不另行实现的原因。
mcp(Model Context Protocol 服务)
@prismposter/creator-tools 提供零依赖的 MCP stdio 服务,让 AI 助手(Claude Desktop、Cursor、Windsurf、Cline)能够查询经过验证的平台安全区域、纵横比裁切、比特率和字幕格式转换,而不会凭空编造像素尺寸。
添加到 claude_desktop_config.json 或 .cursor/mcp.json:
{
"mcpServers": {
"prismposter-creator-tools": {
"command": "npx",
"args": ["-y", "@prismposter/creator-tools"]
}
}
}
提供的 MCP 工具(均为只读工具,执行纯本地计算并提供输出架构):
get_social_media_placement— 某个版位的画面尺寸、以像素为单位的安全区域内边距、可用框和第一方文档 URL(instagram-reels、youtube-shorts、tiktok-video等),以及针对源尺寸的裁切/加黑边方案list_social_media_placements— 列出所有版位或某个平台的版位,供浏览和比较check_safe_area— 检查字幕、徽标或按钮框是否位于某个版位的安全区域内,以及超出各边缘多少像素;TikTok 会说明原因并返回unknowncalculate_aspect_ratio— 简化任意比例、对齐到编解码器块,并计算任意目标比例的中心裁切/加黑边方案estimate_video_bitrate— 编码后文件大小(字节、MiB、MB)、符合大小上限的比特率,以及每像素比特密度convert_subtitles— 在 SRT、WebVTT 和 ASS/SSA 之间转换,支持格式检测和时间偏移estimate_tempo— 根据点击时间戳计算 BPM,或计算已知 BPM 对应的节拍和小节长度
调用错误会返回 MCP 工具错误(isError: true),错误消息会说明如何修正,例如提供未知版位的有效 ID。
托管版本运行于 https://www.prismposter.com/api/mcp(Streamable HTTP,无需安装)。
它使用 prismposter.com 更大的版位数据集作答(也接受网站使用的 camelCase ID),比特率工具接受 videoKbps 和 targetCapMb,仅转换 SRT 和 WebVTT,并新增 get_prismposter_capabilities 工具。
这两个版本都已列入官方 MCP Registry,名称为 com.prismposter/creator-tools。
设计规则
- 纯函数,无副作用,无 I/O。 所有操作均为同步且确定性的。
- 无效输入返回
null,不会抛出异常。 这些函数处理的是文本输入,用户输入一半就停下很常见,并非异常情况。 - 只在边界处进行一次舍入。 尺寸以整像素表示,因为编码器需要这样的值。
null表示“没有可用答案”,且始终可以与零区分。- 错误的类型仍会抛出异常。 规则 2 针对的是用户可能输入的值,并不意味着调用方把字符串传给读取字节的函数时,函数就应该猜测调用方的意图。
开发
npm install
npm test # 173 tests
npm run typecheck
npm run build
欢迎贡献 — 请参阅 CONTRIBUTING.md。新增常量的门槛是要有第一方来源;新增函数的门槛是要有一个没有它就会失败的测试。
同样的数学逻辑,也可以作为浏览器工具使用
此处的每个模块都为一个免费工具提供支持,访问 prismposter.com/tools 即可使用——无需账户,也无需 上传或提供电子邮件。如果你想直接获取答案,而不是函数,请从这里开始:
| 宽高比计算器 | BPM 节拍器 | 字幕转换器 |
| 社交媒体尺寸 | Instagram 帖子尺寸 | 视频计算器 |
| 调色板提取器 | 图像元数据查看器 | 视频转 GIF |
| 视频帧提取器 | 视频裁剪图像 | 人声消除器 |
| 热门视频复刻 | 镜头清单模板 | 歌词生成器 |
| 视频比特率计算器 | SRT 字幕清理器 | YouTube 缩略图预览器 |
维护者
PrismPoster 是一个 AI 内容工作空间,包含图像、视频、复刻、角色和音乐工作室,它们共享同一个项目、素材库和一条真正能完成的时间线。
这个库是该产品中枯燥的那一半:工作室底层的算术逻辑。我们将其提取出来,是因为它确实可以复用,而且字幕解析器并非竞争优势。provenance 则出于相反的原因而存在——在媒体产品中构建 AI 披露功能,让我们认识到 C2PA 工具链还不完善;而缺失的恰恰是一个不依赖任何依赖项的存在性检查。
许可证
MIT © PrismLabs OÜ
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。