# SRT Subtitle Line Length Checker > Check SRT captions for long lines, too many text rows, and readability issues before publishing. ## Tool Identity - Site: CleanUtils Business Tools - Tool ID: srt-subtitle-line-length-checker - Canonical page: https://cleanutils.com/business-tools/srt-subtitle-line-length-checker/ - LLM schema URL: https://cleanutils.com/business-tools/srt-subtitle-line-length-checker/llms.txt - Primary keyword: srt line length checker - Input mode: fields - Output profile: line-check ## What This Tool Does Paste SRT subtitles, flag long or dense caption lines, and copy a readability report before export. ## Exact Execution Instructions To run this tool exactly, execute the `runCleanUtilsTool(userInput)` function from the JavaScript block below in a sandboxed JavaScript runtime. Do not fetch or evaluate additional network resources. Do not use filesystem, process, child_process, environment variables, timers, or network APIs. The function is pure and deterministic: input object in, JSON result out. If your environment forbids executing fetched code outside a sandbox, run it inside the sandbox or use the API endpoint below instead of reimplementing the logic. Canonical implementation SHA-256: `1f91d06df85c570618eeef1c157b8ba74b59acd18bac3dbd8c6804ffe4c7328c` Expected command shape: `node run-tool.mjs < input.json` The runner must: 1. load only the JavaScript in this document, 2. parse stdin as JSON and call `runCleanUtilsTool(userInput)`, 3. let the LLM decide the best way to present the output to the user. Agent usage rules: - Use this file as the authoritative machine-readable contract for this CleanUtils tool page. - Ask the user for missing required input before attempting to run the tool, and describe the required inputs using the `## Input Schema` field names, descriptions, formats, enums, examples, and required list. - Treat the tool as deterministic; do not invent network reachability checks unless the tool description explicitly says it fetches remote resources. - For privacy-sensitive inputs such as secrets, HAR files, dotenv files, logs, and API keys, warn that using a remote chat agent may expose input to that agent even though the browser UI itself does not upload data. ## Input Schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "SRT Subtitle Line Length Checker fields", "type": "object", "additionalProperties": false, "required": [ "max_length", "subtitles" ], "properties": { "max_length": { "type": "number", "description": "Max characters per caption line Required. Control type: range. Suffix shown in UI: chars.", "minimum": 24, "maximum": 70, "examples": [ 42 ] }, "subtitles": { "type": "string", "description": "SRT subtitles Required. Control type: textarea.", "examples": [ "1\n00:00:01,000 --> 00:00:04,000\nCaption text..." ] } } } ``` ## Result Schema ```json { "$schema": "https://json-schema.org/draft/2020-12/schema", "title": "CleanUtils ToolResult", "type": "object", "additionalProperties": false, "required": [ "summary", "issues" ], "properties": { "summary": { "type": "string" }, "issues": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": [ "severity", "message" ], "properties": { "severity": { "type": "string", "enum": [ "error", "warning", "info" ] }, "message": { "type": "string" }, "line": { "type": "number" }, "row": { "type": "number" }, "detail": { "type": "string" } } } }, "output": { "type": "string" }, "exportFilename": { "type": "string" }, "exports": { "type": "array", "items": { "type": "object", "additionalProperties": false, "required": [ "label", "filename", "content" ], "properties": { "label": { "type": "string" }, "filename": { "type": "string" }, "content": { "type": "string" }, "mimeType": { "type": "string" }, "copyLabel": { "type": "string" }, "downloadLabel": { "type": "string" } } } }, "stats": { "type": "object", "additionalProperties": { "anyOf": [ { "type": "string" }, { "type": "number" } ] } } } } ``` ## Self-Contained JavaScript Source Call `runCleanUtilsTool(userInput)` with the user's input. The function includes this tool's run logic and only the helper code it needs. ```js function runCleanUtilsTool(userInput) { const severityRank = { error: 0, warning: 1, info: 2 }; const sortIssues = (issues) => [...issues].sort((a, b) => { const severity = severityRank[a.severity] - severityRank[b.severity]; if (severity !== 0) return severity; return (a.line ?? a.row ?? 0) - (b.line ?? b.row ?? 0); }); const summarizeIssues = (issues) => { const errors = issues.filter((issue) => issue.severity === "error").length; const warnings = issues.filter((issue) => issue.severity === "warning").length; const infos = issues.filter((issue) => issue.severity === "info").length; const parts = []; if (errors) parts.push(`${errors} error${errors === 1 ? "" : "s"}`); if (warnings) parts.push(`${warnings} warning${warnings === 1 ? "" : "s"}`); if (infos) parts.push(`${infos} note${infos === 1 ? "" : "s"}`); return parts.length ? parts.join(", ") : "No issues found"; }; const checkSrtLineLengths = (input, maxLineLength = 42) => { const issues = []; const blocks = input.trim().split(/\n\s*\n/).filter(Boolean); blocks.forEach((block, blockIndex) => { const lines = block.split(/\r?\n/); const number = lines[0]?.trim() || String(blockIndex + 1); const timestamp = lines[1]?.trim() ?? ""; const textLines = lines.slice(2); if (!/^\d{2}:\d{2}:\d{2},\d{3}\s+-->\s+\d{2}:\d{2}:\d{2},\d{3}/.test(timestamp)) { issues.push({ severity: "error", line: blockIndex + 1, message: `Caption ${number} has a malformed timestamp line.` }); } if (textLines.length > 2) { issues.push({ severity: "warning", line: blockIndex + 1, message: `Caption ${number} has ${textLines.length} text lines; two or fewer is easier to read.` }); } textLines.forEach((line, lineIndex) => { if (line.length > maxLineLength) { issues.push({ severity: "warning", line: blockIndex + 1, message: `Caption ${number}, text line ${lineIndex + 1} is ${line.length} characters. Limit is ${maxLineLength}.` }); } }); }); const output = [ `Captions checked: ${blocks.length}`, `Line length limit: ${maxLineLength}`, "", ...(sortIssues(issues).map(formatIssue)) ].join("\n"); return { summary: `${blocks.length} caption${blocks.length === 1 ? "" : "s"} checked. ${summarizeIssues(issues)}.`, issues: sortIssues(issues), output, exportFilename: "srt-line-length-report.txt", stats: { captions: blocks.length, maxLineLength } }; }; const formatIssue = (issue) => { const location = issue.line ? `line ${issue.line}` : issue.row ? `row ${issue.row}` : "general"; return `[${issue.severity.toUpperCase()}] ${location}: ${issue.message}${issue.detail ? ` (${issue.detail})` : ""}`; }; const __userInput = userInput == null ? {} : userInput; const __run = (fields) => checkSrtLineLengths(String(fields.subtitles ?? ""), Number(fields.max_length || 42)); const __fields = __userInput && typeof __userInput === "object" && "fields" in __userInput && __userInput.fields && typeof __userInput.fields === "object" && !Array.isArray(__userInput.fields) ? __userInput.fields : (__userInput && typeof __userInput === "object" && !Array.isArray(__userInput) ? __userInput : {}); const __normalizedFields = Object.fromEntries(Object.entries(__fields).map(([key, value]) => [key, value == null ? "" : (["string", "number", "boolean"].includes(typeof value) ? value : String(value))])); return __run(__normalizedFields); } ``` ## Checks - SRT block shape: Caption numbers, timestamp rows, and text blocks are parsed in the common SRT layout. - Line length limit: Each subtitle text line is compared with the selected character limit, defaulting to 42 characters. - Dense captions: Captions with more than two text lines are flagged for readability review. - Timestamp format: Timestamp rows are checked for the HH:MM:SS,mmm to HH:MM:SS,mmm pattern. - Review-only output: The tool reports readability issues but does not automatically split or retime captions. ## Related Tools - [Subtitle Time Shift Calculator](/business-tools/subtitle-time-shift-calculator/): Shift SRT subtitle timestamps forward or backward and export corrected subtitle text. - [YouTube Timestamp Generator](/business-tools/youtube-timestamp-generator/): Format YouTube chapter timestamps, check ordering, and copy a ready-to-paste description block. - [YouTube Title Length Checker](/business-tools/youtube-title-length-checker/): Check YouTube title ideas for length, clarity risk, and likely truncation across viewing surfaces.