Servidor MCP

Caption File Check

com.powmcp/caption-file-check
Medios y contenido Público y accesible MCP 2025-11-25

Qué hace este MCP

Validates and compares WebVTT, SRT, and TTML caption files for structure, timing, overlaps, encoding, and readability constraints.

caption_check
Preflight one caption or subtitle file before delivery. Attach a WebVTT (.vtt), SRT (.srt), or TTML/IMSC (.ttml/.xml) caption file in chat or give a publicly fetchable URL and it downloads the artifact under an SSRF-guarded, 2 MB-capped fetch, detects the format by content and the byte encoding and BOM, then parses it with the real spec engine (the WebVTT spec parser, a dedicated SRT parser, or the imscJS TTML/IMSC profile engine) and returns deterministic evidence: pass/fail, cue count, structural spec and IMSC profile-conformance errors, overlapping / negative / out-of-order / empty cues, per-line length, and per-cue and summary reading speed (CPS) against a named platform profile (netflix-adult-20, netflix-children-17, youtube, ebu-tt). It reports only source-file conformance, timing, encoding, and reading-speed facts against a dated profile. It does not judge translation quality, transcription accuracy, or synchronization against the video. An arbitrary XML or text file that is not a caption track returns an explicit unsupported-format error. Fetching and parsing a full-length track can take up to 60 seconds. WebVTT limitation: the parser drops payload-less cues; cue counts, indices, timing checks and comparisons cover retained cues only, not those omitted cues.
Solo lectura Acceso externo
Esquema de entrada
{'type': 'object', 'properties': {'url': {'type': 'string', 'pattern': '^https?://', 'maxLength': 2048, 'minLength': 1, 'description': 'A publicly fetchable HTTP(S) URL of a WebVTT, SRT, or TTML/IMSC caption file, detected by content not extension. Provide either this or an attached file, never both. Query strings are allowed but never logged. Pasted caption bodies, data URLs, FTP/SFTP, and URLs needing credentials, headers, or cookies are not supported.\n\nSTRICT RULE: Caption check failed — provide either a caption URL or an attached caption file, not both\nSTRICT RULE: Caption check failed — provide a public caption URL or attach the caption file'}, 'file': {'type': 'object', 'required': ['download_url', 'file_id'], 'properties': {'file_id': {'type': 'string', 'description': 'ChatGPT file id for the attached file'}, 'file_name': {'type': 'string', 'description': 'Original file name when ChatGPT knows it'}, 'mime_type': {'type': 'string', 'description': 'MIME type when ChatGPT knows it'}, 'download_url': {'type': 'string', 'description': 'Temporary authorized download URL supplied by ChatGPT; fetch it only while handling this tool call'}}, 'description': 'A caption file attached in chat (WebVTT, SRT, or TTML/IMSC), detected by content not extension. Provide either this or url, never both.', 'additionalProperties': False}, 'profile': {'anyOf': [{'type': 'string', 'const': 'netflix-adult-20', 'description': 'Named reading-speed profile to judge CPS and line length against. netflix-adult-20 (default, 20 CPS) and netflix-children-17 (17 CPS) are spec-backed; youtube and ebu-tt are advisory ~17 CPS heuristics.'}, {'type': 'string', 'const': 'netflix-children-17', 'description': 'Named reading-speed profile to judge CPS and line length against. netflix-adult-20 (default, 20 CPS) and netflix-children-17 (17 CPS) are spec-backed; youtube and ebu-tt are advisory ~17 CPS heuristics.'}, {'type': 'string', 'const': 'youtube', 'description': 'Named reading-speed profile to judge CPS and line length against. netflix-adult-20 (default, 20 CPS) and netflix-children-17 (17 CPS) are spec-backed; youtube and ebu-tt are advisory ~17 CPS heuristics.'}, {'type': 'string', 'const': 'ebu-tt', 'description': 'Named reading-speed profile to judge CPS and line length against. netflix-adult-20 (default, 20 CPS) and netflix-children-17 (17 CPS) are spec-backed; youtube and ebu-tt are advisory ~17 CPS heuristics.'}], 'description': 'Named reading-speed profile to judge CPS and line length against. netflix-adult-20 (default, 20 CPS) and netflix-children-17 (17 CPS) are spec-backed; youtube and ebu-tt are advisory ~17 CPS heuristics.'}}, 'additionalProperties': False}
Esquema de salida
{'type': 'object', 'required': ['url', 'checkedAt', 'detectedFormat', 'encoding', 'bom', 'pass', 'cueCount', 'rawCueCount', 'profile', 'timing', 'lineLength', 'cps', 'structuralErrors', 'structuralErrorCounts', 'specUsed', 'truncation'], 'properties': {'bom': {'type': 'string', 'description': 'Byte-order-mark detected: utf-8, utf-16le, utf-16be, or none'}, 'cps': {'type': 'object', 'required': ['profileId', 'limit', 'advisory', 'measured', 'max', 'mean', 'breaches'], 'properties': {'max': {'type': 'number', 'description': 'Highest per-cue characters-per-second'}, 'mean': {'type': 'number', 'description': 'Mean characters per second across measured nonempty cues with positive duration'}, 'limit': {'type': 'number', 'description': 'Profile maximum characters per second'}, 'advisory': {'type': 'boolean', 'description': 'Whether the profile reading-speed limit is advisory'}, 'breaches': {'type': 'array', 'items': {'type': 'object', 'required': ['cue', 'cps'], 'properties': {'cps': {'type': 'number', 'description': 'Measured reading speed for the cue in characters per second'}, 'cue': {'type': 'number', 'description': 'Index of the affected caption cue'}}, 'additionalProperties': False}, 'description': 'Cues whose reading speed exceeds the profile limit'}, 'measured': {'type': 'boolean', 'description': 'At least one cue had positive duration and text, distinguished from not-measured'}, 'profileId': {'type': 'string', 'description': 'Identifier of the profile supplying the reading-speed limit'}}, 'description': 'Per-cue and summary reading-speed measurements', 'additionalProperties': False}, 'url': {'type': 'string', 'description': "The checked caption source: the submitted URL query- and fragment-stripped, or the attached file's name"}, 'pass': {'type': 'boolean', 'description': 'True when the file passes all checked format, timing, line-length and reading-speed criteria for the selected profile. False can include an advisory readability threshold breach, not just a specification error; this is not a platform-acceptance verdict'}, 'timing': {'type': 'object', 'required': ['checked', 'clean', 'overlapping', 'negative', 'outOfOrder', 'empty'], 'properties': {'clean': {'type': 'boolean', 'description': 'Checked and no overlapping, negative, out-of-order, or empty retained cue found, distinguished from not-checked; omitted payload-less WebVTT cues are not assessed'}, 'empty': {'type': 'array', 'items': {'type': 'object', 'required': ['cue'], 'properties': {'cue': {'type': 'number', 'description': 'Index of the affected caption cue'}}, 'additionalProperties': False}, 'description': 'Cues whose text is empty after trimming whitespace'}, 'checked': {'type': 'boolean', 'description': 'Cue timing could be analysed (at least one cue)'}, 'negative': {'type': 'array', 'items': {'type': 'object', 'required': ['cue', 'durationMs'], 'properties': {'cue': {'type': 'number', 'description': 'Index of the affected caption cue'}, 'durationMs': {'type': 'number', 'description': 'Cue end time minus start time in milliseconds'}}, 'additionalProperties': False}, 'description': 'Cues whose end time is at or before their start time'}, 'outOfOrder': {'type': 'array', 'items': {'type': 'object', 'required': ['cue'], 'properties': {'cue': {'type': 'number', 'description': 'Index of the affected caption cue'}}, 'additionalProperties': False}, 'description': 'Cues that start before the preceding cue starts'}, 'overlapping': {'type': 'array', 'items': {'type': 'object', 'required': ['cue', 'previousCue'], 'properties': {'cue': {'type': 'number', 'description': 'Index of the affected caption cue'}, 'previousCue': {'type': 'number', 'description': 'Index of the preceding overlapping cue'}}, 'additionalProperties': False}, 'description': 'Cues that start before the preceding cue ends'}}, 'description': 'Measured retained-cue timing and empty-text findings; WebVTT indices refer to retained cues, not original source positions', 'additionalProperties': False}, 'profile': {'type': 'object', 'required': ['id', 'date', 'label', 'maxCps', 'maxLineLength', 'advisory', 'source'], 'properties': {'id': {'type': 'string', 'description': 'Identifier of the applied caption profile'}, 'date': {'type': 'string', 'description': 'Review month recorded for the profile'}, 'label': {'type': 'string', 'description': 'Display name of the applied caption profile'}, 'maxCps': {'type': 'number', 'description': 'Maximum characters per second specified by the profile'}, 'source': {'type': 'string', 'description': 'Source or advisory basis recorded for the profile'}, 'advisory': {'type': 'boolean', 'description': 'The reading-speed limit is an industry heuristic, not a spec-mandated number'}, 'maxLineLength': {'type': 'number', 'description': 'Maximum characters per line specified by the profile'}}, 'description': 'Reading-speed and line-length profile applied to the caption checks', 'additionalProperties': False}, 'cueCount': {'type': 'number', 'description': 'Number of caption cues retained for checking; payload-less WebVTT cues are omitted by the parser'}, 'encoding': {'type': 'string', 'description': 'Detected byte encoding of the caption file'}, 'specUsed': {'type': 'string', 'description': 'The dated spec identifier the detected format was checked against'}, 'checkedAt': {'type': 'string', 'description': 'ISO timestamp when the caption result was produced'}, 'lineLength': {'type': 'object', 'required': ['limit', 'maxObserved', 'overLimit'], 'properties': {'limit': {'type': 'number', 'description': 'Profile maximum characters per line'}, 'overLimit': {'type': 'array', 'items': {'type': 'object', 'required': ['cue', 'line', 'length'], 'properties': {'cue': {'type': 'number', 'description': 'Index of the affected caption cue'}, 'line': {'type': 'number', 'description': 'One-based line number within the cue'}, 'length': {'type': 'number', 'description': 'Number of Unicode characters on the affected line'}}, 'additionalProperties': False}, 'description': 'Caption lines exceeding the profile character limit'}, 'maxObserved': {'type': 'number', 'description': 'Largest character count observed on a caption line'}}, 'description': 'Per-line character counts checked against the profile limit', 'additionalProperties': False}, 'truncation': {'type': 'array', 'items': {'type': 'string', 'description': 'Machine-checkable truncation markers, e.g. cue-cap'}, 'description': 'Markers identifying checks truncated by configured limits'}, 'rawCueCount': {'type': 'number', 'description': 'Cues parsed before the 20,000-cue cap; excludes payload-less WebVTT cues dropped by the parser'}, 'ttmlProfile': {'type': 'string', 'description': 'IMSC/TTML profile designator declared in the file, when present'}, 'detectedFormat': {'type': 'string', 'description': 'webvtt, srt, or ttml (covers IMSC), detected by content'}, 'structuralErrors': {'type': 'array', 'items': {'type': 'object', 'required': ['severity', 'code', 'message'], 'properties': {'cue': {'type': 'number', 'description': 'Index of the affected caption cue'}, 'code': {'type': 'string', 'description': 'Machine-readable structural finding code'}, 'message': {'type': 'string', 'description': 'Parser diagnostic describing the structural finding'}, 'severity': {'type': 'string', 'description': 'Severity assigned by the caption parser'}}, 'additionalProperties': False}, 'description': 'Spec-parser and IMSC/TTML profile-conformance findings'}, 'structuralErrorCounts': {'type': 'object', 'required': ['error', 'warning'], 'properties': {'error': {'type': 'number', 'description': 'Number of error-severity structural findings'}, 'warning': {'type': 'number', 'description': 'Number of warning-severity structural findings'}}, 'description': 'Counts of structural findings grouped by severity', 'additionalProperties': False}}, 'additionalProperties': False}
caption_compare
Compare exactly two caption or subtitle files under identical bounded checks: an original versus its translated track, before versus after a timing fix, or a format migration. Attach two WebVTT, SRT, or TTML/IMSC caption files in chat or give two publicly fetchable URLs and it runs the same SSRF-guarded, 2 MB-capped preflight as caption_check on each, then aligns them by cue index and reports side-by-side pass status, detected-format and encoding differences, the cue-count delta, timing drift and overlap differences, reading-speed (CPS) regressions, structural-error deltas, and a winner only when the measured checks separate the two. Use caption_check for a single file. It reports only source-file conformance, timing, encoding, and reading-speed facts against a dated profile: never translation quality, transcription accuracy, or sync against the video. Fetching and parsing two live files can take up to 60 seconds. WebVTT limitation: the parser drops payload-less cues; cue counts, indices, timing checks and comparisons cover retained cues only, not those omitted cues.
Solo lectura Acceso externo
Esquema de entrada
{'type': 'object', 'properties': {'urls': {'type': 'array', 'items': {'type': 'string', 'pattern': '^https?://', 'maxLength': 2048, 'minLength': 1, 'description': 'A publicly fetchable HTTP(S) WebVTT, SRT, or TTML/IMSC caption URL, detected by content.'}, 'maxItems': 2, 'minItems': 2, 'description': 'Exactly two public caption URLs to compare, in the order they should appear side by side (for example original then translated). Provide either this or files, never both.\n\nSTRICT RULE: Caption compare failed — provide either two caption URLs or two attached caption files, not both\nSTRICT RULE: Caption compare failed — provide two public caption URLs or attach two caption files'}, 'files': {'type': 'array', 'items': {'type': 'object', 'required': ['download_url', 'file_id'], 'properties': {'file_id': {'type': 'string', 'description': 'ChatGPT file id for the attached file'}, 'file_name': {'type': 'string', 'description': 'Original file name when ChatGPT knows it'}, 'mime_type': {'type': 'string', 'description': 'MIME type when ChatGPT knows it'}, 'download_url': {'type': 'string', 'description': 'Temporary authorized download URL supplied by ChatGPT; fetch it only while handling this tool call'}}, 'description': 'A caption file attached in chat (WebVTT, SRT, or TTML/IMSC), detected by content.', 'additionalProperties': False}, 'maxItems': 2, 'minItems': 2, 'description': 'Exactly two caption files attached in chat to compare, in the order they should appear side by side (for example original then translated). Provide either this or urls, never both.'}, 'profile': {'anyOf': [{'type': 'string', 'const': 'netflix-adult-20', 'description': 'Named reading-speed profile applied to both tracks. netflix-adult-20 (default), netflix-children-17, youtube, ebu-tt.'}, {'type': 'string', 'const': 'netflix-children-17', 'description': 'Named reading-speed profile applied to both tracks. netflix-adult-20 (default), netflix-children-17, youtube, ebu-tt.'}, {'type': 'string', 'const': 'youtube', 'description': 'Named reading-speed profile applied to both tracks. netflix-adult-20 (default), netflix-children-17, youtube, ebu-tt.'}, {'type': 'string', 'const': 'ebu-tt', 'description': 'Named reading-speed profile applied to both tracks. netflix-adult-20 (default), netflix-children-17, youtube, ebu-tt.'}], 'description': 'Named reading-speed profile applied to both tracks. netflix-adult-20 (default), netflix-children-17, youtube, ebu-tt.'}}, 'description': 'STRICT RULE: Caption compare failed — the two caption files are the same; provide two distinct caption files.', 'additionalProperties': False}
Esquema de salida
{'type': 'object', 'required': ['checkedAt', 'profile', 'tracks', 'notes'], 'properties': {'notes': {'type': 'array', 'items': {'type': 'string'}, 'description': 'Notes about incomplete checks or completion under identical limits'}, 'tracks': {'type': 'array', 'items': {'type': 'object', 'required': ['url', 'ok'], 'properties': {'ok': {'type': 'boolean', 'description': 'Whether the caption file could be fetched and preflighted'}, 'bom': {'type': 'string', 'description': 'Detected byte-order mark, or none'}, 'cps': {'type': 'object', 'required': ['profileId', 'limit', 'advisory', 'measured', 'max', 'mean', 'breaches'], 'properties': {'max': {'type': 'number', 'description': 'Highest per-cue characters-per-second'}, 'mean': {'type': 'number', 'description': 'Mean characters per second across measured nonempty cues with positive duration'}, 'limit': {'type': 'number', 'description': 'Profile maximum characters per second'}, 'advisory': {'type': 'boolean', 'description': 'Whether the profile reading-speed limit is advisory'}, 'breaches': {'type': 'array', 'items': {'type': 'object', 'required': ['cue', 'cps'], 'properties': {'cps': {'type': 'number', 'description': 'Measured reading speed for the cue in characters per second'}, 'cue': {'type': 'number', 'description': 'Index of the affected caption cue'}}, 'additionalProperties': False}, 'description': 'Cues whose reading speed exceeds the profile limit'}, 'measured': {'type': 'boolean', 'description': 'At least one cue had positive duration and text, distinguished from not-measured'}, 'profileId': {'type': 'string', 'description': 'Identifier of the profile supplying the reading-speed limit'}}, 'description': 'Per-cue and summary reading-speed measurements', 'additionalProperties': False}, 'url': {'type': 'string', 'description': "The checked caption source: the submitted URL query- and fragment-stripped, or the attached file's name"}, 'pass': {'type': 'boolean', 'description': 'Whether the track passes structural, timing, line-length, and reading-speed checks'}, 'failed': {'type': 'string', 'description': 'Reason the caption file could not be preflighted'}, 'timing': {'type': 'object', 'required': ['checked', 'clean', 'overlapping', 'negative', 'outOfOrder', 'empty'], 'properties': {'clean': {'type': 'boolean', 'description': 'Checked and no overlapping, negative, out-of-order, or empty cue found, distinguished from not-checked'}, 'empty': {'type': 'array', 'items': {'type': 'object', 'required': ['cue'], 'properties': {'cue': {'type': 'number', 'description': 'Index of the affected caption cue'}}, 'additionalProperties': False}, 'description': 'Cues whose text is empty after trimming whitespace'}, 'checked': {'type': 'boolean', 'description': 'Cue timing could be analysed (at least one cue)'}, 'negative': {'type': 'array', 'items': {'type': 'object', 'required': ['cue', 'durationMs'], 'properties': {'cue': {'type': 'number', 'description': 'Index of the affected caption cue'}, 'durationMs': {'type': 'number', 'description': 'Cue end time minus start time in milliseconds'}}, 'additionalProperties': False}, 'description': 'Cues whose end time is at or before their start time'}, 'outOfOrder': {'type': 'array', 'items': {'type': 'object', 'required': ['cue'], 'properties': {'cue': {'type': 'number', 'description': 'Index of the affected caption cue'}}, 'additionalProperties': False}, 'description': 'Cues that start before the preceding cue starts'}, 'overlapping': {'type': 'array', 'items': {'type': 'object', 'required': ['cue', 'previousCue'], 'properties': {'cue': {'type': 'number', 'description': 'Index of the affected caption cue'}, 'previousCue': {'type': 'number', 'description': 'Index of the preceding overlapping cue'}}, 'additionalProperties': False}, 'description': 'Cues that start before the preceding cue ends'}}, 'description': 'Measured cue timing and empty-text findings', 'additionalProperties': False}, 'cueCount': {'type': 'number', 'description': 'Number of caption cues retained for checking'}, 'encoding': {'type': 'string', 'description': 'Detected byte encoding of the caption file'}, 'lineLength': {'type': 'object', 'required': ['limit', 'maxObserved', 'overLimit'], 'properties': {'limit': {'type': 'number', 'description': 'Profile maximum characters per line'}, 'overLimit': {'type': 'array', 'items': {'type': 'object', 'required': ['cue', 'line', 'length'], 'properties': {'cue': {'type': 'number', 'description': 'Index of the affected caption cue'}, 'line': {'type': 'number', 'description': 'One-based line number within the cue'}, 'length': {'type': 'number', 'description': 'Number of Unicode characters on the affected line'}}, 'additionalProperties': False}, 'description': 'Caption lines exceeding the profile character limit'}, 'maxObserved': {'type': 'number', 'description': 'Largest character count observed on a caption line'}}, 'description': 'Per-line character counts checked against the profile limit', 'additionalProperties': False}, 'detectedFormat': {'type': 'string', 'description': 'Caption format detected from file content'}, 'structuralErrorCounts': {'type': 'object', 'required': ['error', 'warning'], 'properties': {'error': {'type': 'number', 'description': 'Number of error-severity structural findings'}, 'warning': {'type': 'number', 'description': 'Number of warning-severity structural findings'}}, 'description': 'Counts of structural findings grouped by severity', 'additionalProperties': False}}, 'additionalProperties': False}, 'description': 'The two tracks in input order'}, 'winner': {'type': 'object', 'required': ['url', 'reason'], 'properties': {'url': {'type': 'string', 'description': 'Reported source identifier of the track with fewer measured problems'}, 'reason': {'type': 'string', 'description': 'Measured findings supporting the fewer-problems track'}}, 'description': 'Track with fewer weighted structural, timing, reading-speed, and line-length problems', 'additionalProperties': False}, 'profile': {'type': 'object', 'required': ['id', 'date', 'label', 'maxCps', 'maxLineLength', 'advisory', 'source'], 'properties': {'id': {'type': 'string', 'description': 'Identifier of the applied caption profile'}, 'date': {'type': 'string', 'description': 'Review month recorded for the profile'}, 'label': {'type': 'string', 'description': 'Display name of the applied caption profile'}, 'maxCps': {'type': 'number', 'description': 'Maximum characters per second specified by the profile'}, 'source': {'type': 'string', 'description': 'Source or advisory basis recorded for the profile'}, 'advisory': {'type': 'boolean', 'description': 'The reading-speed limit is an industry heuristic, not a spec-mandated number'}, 'maxLineLength': {'type': 'number', 'description': 'Maximum characters per line specified by the profile'}}, 'description': 'Reading-speed and line-length profile applied to the caption checks', 'additionalProperties': False}, 'checkedAt': {'type': 'string', 'description': 'ISO timestamp when the caption result was produced'}, 'comparison': {'type': 'object', 'required': ['cueCountDelta', 'formatDiffers', 'encodingDiffers', 'passDiffers', 'timingDrift', 'overlapDelta', 'cpsRegression', 'structuralErrorDelta'], 'properties': {'passDiffers': {'type': 'boolean', 'description': 'Whether the two caption pass results differ'}, 'timingDrift': {'type': 'object', 'required': ['alignedCues', 'maxStartDriftMs', 'meanStartDriftMs', 'driftingCues'], 'properties': {'alignedCues': {'type': 'number', 'description': 'Cue positions compared by index, min of the two counts'}, 'driftingCues': {'type': 'number', 'description': 'Aligned positions whose start times differ by more than 500 ms'}, 'maxStartDriftMs': {'type': 'number', 'description': 'Largest absolute cue-start drift in milliseconds'}, 'meanStartDriftMs': {'type': 'number', 'description': 'Mean absolute cue-start drift in milliseconds'}}, 'description': 'Absolute cue-start drift across positions aligned by cue index', 'additionalProperties': False}, 'overlapDelta': {'type': 'number', 'description': 'Second track overlapping-cue count minus first'}, 'cpsRegression': {'type': 'object', 'required': ['firstMax', 'secondMax', 'delta'], 'properties': {'delta': {'type': 'number', 'description': 'Second track max CPS minus first: positive means the second reads faster'}, 'firstMax': {'type': 'number', 'description': 'Maximum reading speed of the first track in characters per second'}, 'secondMax': {'type': 'number', 'description': 'Maximum reading speed of the second track in characters per second'}}, 'description': 'Change in maximum reading speed from the first track to the second', 'additionalProperties': False}, 'cueCountDelta': {'type': 'number', 'description': 'Second track cue count minus first'}, 'formatDiffers': {'type': 'boolean', 'description': 'Whether the detected caption formats differ'}, 'encodingDiffers': {'type': 'boolean', 'description': 'Whether the detected byte encodings differ'}, 'structuralErrorDelta': {'type': 'object', 'required': ['error', 'warning'], 'properties': {'error': {'type': 'number', 'description': 'Second-track structural error count minus first-track count'}, 'warning': {'type': 'number', 'description': 'Second-track structural warning count minus first-track count'}}, 'description': 'Second-track structural finding counts minus first-track counts', 'additionalProperties': False}}, 'description': 'Measured differences between the two successfully preflighted tracks', 'additionalProperties': False}}, 'additionalProperties': False}
Modificado
caption_compare
27 de September de 2026 a las 02:53
Modificado
caption_check
27 de September de 2026 a las 02:53
Añadido
caption_compare
17 de September de 2026 a las 12:36
Añadido
caption_check
17 de September de 2026 a las 12:36