Lunara
Subtitle engine for AI agents: one upload gives a written track and a translation, timings exact.
Sollte ich dies verwenden
Qualität und Sicherheit
Befunde (1)
- LOWin lunara_rewrite
Basierend auf einer automatisierten Analyse der Tool-Definitionen und der Einhaltung des Protokolls.
Kontextkosten
Dies ist die ungefähre Anzahl der Tokens, die jedes Mal verbraucht werden, wenn die Tools des Servers in den Kontext eines Modells geladen werden. Höhere Werte verringern die Aufmerksamkeit, die für andere Aufgaben verfügbar ist.
Installieren
Installation mit einem Klick
Fügen Sie dies Ihrer Datei `claude_desktop_config.json` hinzu:
{
"mcpServers": {
"lunara": {
"url": "https://lunaraai.cc/api/lunara/mcp"
}
}
}Remote-Endpunkte
https://lunaraai.cc/api/lunara/mcpstreamable-httphttps://lunaraai.cc/mcpstreamable-httpWas es kann
Tool-Inventar
Tools (18)
🟢lunara_list_tools
Return every subtitle tool Lunara exposes, with the minutes each one costs. Call this first when you are unsure which tool fits.
Eingabe-Schema
{
"type": "object",
"properties": {},
"additionalProperties": false
}🟢lunara_get_job(jobId)
Return the state of a subtitle job: status, progress, whether the SRT is ready, and how many cues it has. Poll this after lunara_upload_video.
Eingabe-Schema
{
"type": "object",
"properties": {
"jobId": {
"type": "string",
"description": "The job id returned by lunara_upload_video."
}
},
"required": [
"jobId"
],
"additionalProperties": false
}🟢lunara_get_srt(jobId, track)
Return the subtitle file for a finished job. One line per cue. Use track="secondary" for the translated track (English by default).
Eingabe-Schema
{
"type": "object",
"properties": {
"jobId": {
"type": "string",
"description": "The job id."
},
"track": {
"type": "string",
"enum": [
"primary",
"secondary"
],
"description": "primary = the written-language track; secondary = the translation."
}
},
"required": [
"jobId"
],
"additionalProperties": false
}🟢lunara_list_cues(jobId, offset, limit)
Return subtitle cues for a job as timestamps plus text, so you can inspect or reference individual lines before proposing edits.
Eingabe-Schema
{
"type": "object",
"properties": {
"jobId": {
"type": "string",
"description": "The job id."
},
"offset": {
"type": "integer",
"minimum": 0,
"description": "Skip this many cues. Default 0."
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 500,
"description": "How many cues to return. Default 100."
}
},
"required": [
"jobId"
],
"additionalProperties": false
}🟡lunara_start_subtitle_job(audioUrl, primaryLang, secondaryLang, spokenLang)
Run the full eight-layer subtitle pipeline on an audio or video URL you can already host. Produces a written-language track and a translated track. Prefer lunara_upload_video when the file is local.
Eingabe-Schema
{
"type": "object",
"properties": {
"audioUrl": {
"type": "string",
"description": "A URL Lunara can download (public or pre-signed)."
},
"primaryLang": {
"type": "string",
"enum": [
"zh-Hant",
"yue-Hant",
"zh-CN",
"en",
"ja",
"ko"
],
"description": "Language of the written track. Default yue-Hant."
},
"secondaryLang": {
"type": "string",
"enum": [
"zh-Hant",
"yue-Hant",
"zh-CN",
"en",
"ja",
"ko"
],
"description": "Language of the translated track. Default en."
},
"spokenLang": {
"type": "string",
"description": "What the speaker is speaking, e.g. yue-Hant-HK. Defaults to primaryLang."
}
},
"required": [
"audioUrl"
],
"additionalProperties": false
}🟡lunara_subtitle_from_url(audioUrl, filename, primaryLang, secondaryLang, spokenLang)
Start a persisted subtitle job from a URL you already host — no upload needed. Returns a job id; poll lunara_get_job every 15–30 s until status is "completed", then call lunara_get_srt. Prefer this over lunara_upload_video whenever the media is reachable by URL.
Eingabe-Schema
{
"type": "object",
"properties": {
"audioUrl": {
"type": "string",
"description": "Direct HTTP(S) URL to the audio or video file. Must be downloadable by our server."
},
"filename": {
"type": "string",
"description": "Display name for the result. Defaults to the URL basename."
},
"primaryLang": {
"type": "string",
"enum": [
"zh-Hant",
"yue-Hant",
"zh-CN",
"en",
"ja",
"ko"
],
"description": "Language of the written track. Default yue-Hant."
},
"secondaryLang": {
"type": "string",
"enum": [
"zh-Hant",
"yue-Hant",
"zh-CN",
"en",
"ja",
"ko"
],
"description": "Language of the translated track. Default en."
},
"spokenLang": {
"type": "string",
"description": "What the speaker is speaking, e.g. yue-Hant-HK. Defaults to auto-detect."
}
},
"required": [
"audioUrl"
],
"additionalProperties": false
}🟡lunara_upload_video(projectId, clientOperationId, filename, mime, sizeBytes, ...)
Reserve an upload slot and return the object key plus a signed URL per part. After uploading the bytes call lunara_finish_upload. Use this for a file you hold locally.
Eingabe-Schema
{
"type": "object",
"properties": {
"projectId": {
"type": "string",
"description": "Project to upload into. Omit to let Lunara reuse the most recent project for this organisation."
},
"clientOperationId": {
"type": "string",
"description": "Idempotency key. Reuse the same value to retry without creating a second upload."
},
"filename": {
"type": "string",
"description": "Original filename, used for the download name."
},
"mime": {
"type": "string",
"description": "MIME type, e.g. audio/mpeg, video/mp4."
},
"sizeBytes": {
"type": "integer",
"minimum": 1,
"description": "Exact file size in bytes."
},
"primaryLang": {
"type": "string",
"enum": [
"zh-Hant",
"yue-Hant",
"zh-CN",
"en",
"ja",
"ko"
],
"description": "Written-track language. Default yue-Hant."
},
"secondaryLang": {
"type": "string",
"enum": [
"zh-Hant",
"yue-Hant",
"zh-CN",
"en",
"ja",
"ko"
],
"description": "Translated-track language. Default en."
}
},
"required": [
"filename",
"mime",
"sizeBytes"
],
"additionalProperties": false
}🟡lunara_finish_upload(videoId, uploadId, key, durationMs, parts)
Tell Lunara the bytes are uploaded so the pipeline can start. Returns the job id to poll with lunara_get_job.
Eingabe-Schema
{
"type": "object",
"properties": {
"videoId": {
"type": "string",
"description": "The video id from lunara_upload_video."
},
"uploadId": {
"type": "string",
"description": "The multipart upload id."
},
"key": {
"type": "string",
"description": "The object key."
},
"durationMs": {
"type": "integer",
"minimum": 1,
"description": "Media duration in milliseconds."
},
"parts": {
"type": "array",
"description": "Uploaded parts, each { PartNumber, ETag }.",
"items": {
"type": "object",
"properties": {
"PartNumber": {
"type": "integer",
"minimum": 1
},
"ETag": {
"type": "string"
}
},
"required": [
"PartNumber",
"ETag"
],
"additionalProperties": false
}
}
},
"required": [
"videoId",
"uploadId",
"key",
"durationMs",
"parts"
],
"additionalProperties": false
}🟢lunara_get_glossary(limit)
Return the proper nouns Lunara has learned for this org, so names are spelled consistently across tracks.
Eingabe-Schema
{
"type": "object",
"properties": {
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 500,
"description": "Default 100."
}
},
"additionalProperties": false
}⚪lunara_transcribe(audioUrl, spokenLang)
Run speech recognition only — no rewrite, no translation. Returns timed segments. Use this when you want the transcript itself, or when you plan to pick a later stage yourself.
Eingabe-Schema
{
"type": "object",
"properties": {
"audioUrl": {
"type": "string",
"description": "Direct HTTP(S) URL to the audio or video file."
},
"spokenLang": {
"type": "string",
"description": "What the speaker is speaking, e.g. yue-Hant-HK. Defaults to auto-detect."
}
},
"required": [
"audioUrl"
],
"additionalProperties": false
}⚪lunara_translate(jobId, targetLang, track)
Translate the text of an existing job’s cues into another language. Every cue boundary and timestamp is preserved; only the text changes. Use this instead of translating yourself so the timing contract holds.
Eingabe-Schema
{
"type": "object",
"properties": {
"jobId": {
"type": "string",
"description": "The job whose cues to translate."
},
"targetLang": {
"type": "string",
"enum": [
"zh-Hant",
"en",
"ja",
"ko"
],
"description": "Target language."
},
"track": {
"type": "string",
"enum": [
"primary",
"secondary"
],
"description": "Which track to read. Default primary."
}
},
"required": [
"jobId",
"targetLang"
],
"additionalProperties": false
}⚪lunara_rewrite(jobId, track)
Turn spoken Cantonese cue text into written Chinese. Every cue boundary and timestamp is preserved. Deliberate mispronunciations are never corrected, and proper nouns are protected.
Eingabe-Schema
{
"type": "object",
"properties": {
"jobId": {
"type": "string",
"description": "The job whose cues to rewrite."
},
"track": {
"type": "string",
"enum": [
"primary",
"secondary"
],
"description": "Which track to read. Default primary."
}
},
"required": [
"jobId"
],
"additionalProperties": false
}⚪lunara_segment(jobId, maxCueMs, track)
Approximate split, not audio-grounded segmentation: cue text is divided at clause punctuation and each piece receives a share of the original span proportional to its character count. The words are not changed. Timings are estimated, so treat them as a reading aid rather than a re-alignment — use lunara_start_subtitle_job if you need timing derived from the audio.
Eingabe-Schema
{
"type": "object",
"properties": {
"jobId": {
"type": "string",
"description": "The job whose cues to re-cut."
},
"maxCueMs": {
"type": "integer",
"minimum": 500,
"maximum": 15000,
"description": "Duration ceiling per cue in ms. Default 7000."
},
"track": {
"type": "string",
"enum": [
"primary",
"secondary"
],
"description": "Which track to read. Default primary."
}
},
"required": [
"jobId"
],
"additionalProperties": false
}🟢lunara_glossary_extract(jobId, limit)
Find candidate proper nouns in a job’s cues, ranked by frequency, with the first cue they appear in. Suggestions for a glossary, not corrections — nothing is rewritten.
Eingabe-Schema
{
"type": "object",
"properties": {
"jobId": {
"type": "string",
"description": "The job whose cues to scan."
},
"limit": {
"type": "integer",
"minimum": 1,
"maximum": 200,
"description": "Maximum terms to return. Default 50."
}
},
"required": [
"jobId"
],
"additionalProperties": false
}🟢lunara_qa_contract(jobId, track)
Run the contract gate over both tracks: ASR text and timings byte-exact, cue length bounds, no empty cues. Returns pass/fail per rule. Free, because refusing a broken track should never cost the caller money.
Eingabe-Schema
{
"type": "object",
"properties": {
"jobId": {
"type": "string",
"description": "The job to validate."
},
"track": {
"type": "string",
"enum": [
"primary",
"secondary",
"both"
],
"description": "Which track to check. Default both."
}
},
"required": [
"jobId"
],
"additionalProperties": false
}🟢lunara_probe_media(mediaUrl)
Return duration, dimensions, codecs and container for a URL, plus whether the audio is mono 16 kHz already. Call this before choosing an ASR engine.
Eingabe-Schema
{
"type": "object",
"properties": {
"mediaUrl": {
"type": "string",
"description": "URL to probe."
}
},
"required": [
"mediaUrl"
],
"additionalProperties": false
}🟢lunara_get_coverage(jobId)
Report how much of the source timeline the subtitles cover, and list suspicious gaps longer than a second. Use before shipping a long video.
Eingabe-Schema
{
"type": "object",
"properties": {
"jobId": {
"type": "string",
"description": "The job to inspect."
}
},
"required": [
"jobId"
],
"additionalProperties": false
}🟢lunara_readability(jobId, track)
Per-cue reading speed, displayed length and characters-per-second, with the cues that exceed comfortable limits. Mirrors the metrics shown in the editor.
Eingabe-Schema
{
"type": "object",
"properties": {
"jobId": {
"type": "string",
"description": "The job to measure."
},
"track": {
"type": "string",
"enum": [
"primary",
"secondary"
],
"description": "Default primary."
}
},
"required": [
"jobId"
],
"additionalProperties": false
}Community
Nachweis