aimakeall-mcp 0.11.0 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +48 -5
- package/lib/api-client.mjs +21 -3
- package/lib/cloud-tools.mjs +230 -81
- package/lib/companion-tools.mjs +6 -0
- package/lib/composer-tools.mjs +1 -1
- package/lib/config.mjs +1 -1
- package/lib/production-context.mjs +3 -2
- package/lib/production-schemas.mjs +23 -2
- package/lib/review-full-analysis.mjs +302 -0
- package/lib/review-sources.mjs +106 -0
- package/lib/review-tools.mjs +285 -0
- package/lib/tts-workflow.mjs +88 -0
- package/lib/visual-production.mjs +56 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ Claude Code·Codex 같은 MCP 클라이언트에서 자연어로 AImakeAll 영
|
|
|
16
16
|
"mcpServers": {
|
|
17
17
|
"aimakeall": {
|
|
18
18
|
"command": "npx",
|
|
19
|
-
"args": ["-y", "aimakeall-mcp@0.
|
|
19
|
+
"args": ["-y", "aimakeall-mcp@0.13.0"],
|
|
20
20
|
"env": { "AIMAKEALL_PAT": "aio_pat_..." }
|
|
21
21
|
}
|
|
22
22
|
}
|
|
@@ -53,19 +53,38 @@ plan_shorts_video → (씬마다) generate_scene_image → get_generation_job(co
|
|
|
53
53
|
- 원가 가시화: 생성 전 `estimate_video_cost`로 견적을 내고, 작업 후 `get_cost_report`로 실제 지출을 확인하세요. 어두운/검은 컷 의심 시 `verify_render_darkness`로 완성본 휘도를 실측할 수 있습니다.
|
|
54
54
|
- 캐릭터 일관성: `plan_*`에 `characters`(이름·외모 앵커·의상 고정)를 넘기면 씬마다 identity lock 이 프롬프트에 강제 주입되고, `generate_scene_image`의 `identityLock`으로 재생성 시에도 유지됩니다.
|
|
55
55
|
|
|
56
|
-
## 제작 스타일 유지와 컷컴포저 편집 (0.
|
|
56
|
+
## 제작 스타일 유지와 컷컴포저 편집 (0.12.0)
|
|
57
57
|
|
|
58
|
-
|
|
58
|
+
아래의 이미지 소스·영상 표현 선택과 TTS 자동 우선순위는 MCP 0.12.0부터 지원합니다. 현재 설정은 `aimakeall-mcp@0.13.0`으로 바꾸고 클라이언트를 다시 연결하세요. 토큰은 그대로 사용할 수 있습니다. 대응 서버와 컴패니언 런타임도 필요하며, 컴패니언에서 렌더 기능 업데이트를 요청하면 최신 설치 프로그램으로 업데이트하세요.
|
|
59
59
|
|
|
60
60
|
- `plan_shorts_video({categoryId:"viral-shorts",durationTargetSec:40,...})`는 `productionProfile`과 `productionPath`를 반환합니다. 이후 추천·TTS·스티치에 **가장 최근 반환된 `productionPath`**를 전달하세요. 제작별 불변 파일이라 동시에 만든 다른 영상의 스타일과 섞이지 않습니다.
|
|
61
61
|
- 바이럴·커뮤니티 프로필은 `casual-social`을 사용합니다. 사건 소재라도 뉴스 브리핑형으로 자동 변경하지 않습니다. TTS의 `text`를 생략하면 저장된 기획 대본을 사용하며, 분명한 뉴스체 회귀는 과금 전 `422 NARRATION_STYLE_DRIFT`로 중단합니다. 자막은 실제 발화와 일치시켜야 하며 자극성을 위해 사실·인용·피해 내용을 꾸미면 안 됩니다.
|
|
62
|
-
-
|
|
62
|
+
- 보이스 공급자 자동 선택은 Typecast → ElevenLabs → Supertone → Edge TTS → Supertonic2 순서입니다. 키/실행 가능 상태를 먼저 확인하며, 0.13.0부터 확정된 일시 실패에 한해 아래의 안전한 폴백 규칙을 적용합니다. 명시한 목소리는 승인된 대체 보이스 없이 바꾸지 않습니다. 대화형/소셜 목소리를 우선하되 실제 청취 결과라고 주장하지 않습니다. ElevenLabs 외의 공급자 자막은 실제 오디오 길이 기반 추정 타이밍임을 표시하므로 최종 동기화를 확인하세요.
|
|
63
63
|
- `list_composer_presets`에서 실제 편집기의 프리셋과 모션을 조회하세요. `titleStylePresetId`, `subtitleStylePresetId`, `subtitleLines[].stylePresetId`, `titleStyle`, `subtitleStyle`, `subtitleLines[].style`로 서로 다른 제목/본문 계층과 장면별 강조를 설정합니다. 명시 스타일 > 선택 프리셋 > 프로필 기본값 순서입니다.
|
|
64
64
|
- `search_composer_assets` 또는 무료 `recommend_composer_overlays`로 관련 소재를 검토하고 선택한 `assetId`에 `startSec/endSec`, `xPct/yPct`, `widthPct`를 붙여 `stitch_timeline.overlays`로 전달하세요. 좌표는 화면의 백분율 중심점이며 `opacity`는 0~100입니다. SVG 아이콘·이모지, GIF/비디오, 효과음을 타임라인 레이어로 처리합니다. 사건·피해자에 조롱 밈을 강제로 붙이지 않으며, 출처·라이선스 확인이 필요한 소재는 공개 전에 검토해야 합니다.
|
|
65
65
|
- 목표 길이는 실제 TTS 길이로 덮어쓰지 않습니다. 허용 오차 `max(2초, 목표의 10%)`를 벗어나면 경고하고 렌더 전에 차단합니다. 자동 유료 재합성을 하지 않으며, 무음이나 억지 영상 늘이기로 통과시키지 마세요.
|
|
66
66
|
- 커뮤니티/바이럴 제작은 라이브러리 검토 없이 기본 자막만으로 끝내지 않습니다. 오버레이가 없으면 `decorationRationale`에 적합한 소재를 생략한 이유를 기록해야 렌더할 수 있습니다. 관련 없는 장식이나 부적절한 밈을 억지로 넣는 것은 해결이 아닙니다.
|
|
67
67
|
- `review_production`은 구조만 점검합니다. `render_result`의 `qualityStatus`가 `needs-visual-and-listening-review`이면 아직 시각·청취 검증 전입니다. 최종 영상에서 강조색/글자 크기/모션/소재 겹침과 목소리를 직접 확인한 뒤에만 완성 품질을 보고하세요.
|
|
68
68
|
|
|
69
|
+
## 공급자 폴백과 비용 기록 (0.13.0)
|
|
70
|
+
|
|
71
|
+
- `tts_narration`과 `tts_narration_with_captions`는 일반 합성에서 확정된 일시 거절(429/503 등)에 한해 다음 사용 가능한 공급자를 고려합니다. `allowProviderFallback:false`로 끌 수 있습니다. 자동 선택 전 사용자 키로 보이스 목록을 확인하며, 비용 견적만 요청할 때는 이 추가 검증을 하지 않습니다.
|
|
72
|
+
- 보이스를 명시했거나 제작 핸들에 캐스팅이 저장되어 있으면 공급자별 대체 보이스를 사용자가 허용해야 합니다. 예: `fallbackVoices:{elevenlabs:{voiceId:"사용자가-승인한-ID"}}`. 다른 공급자의 보이스/모델/스타일 ID를 그대로 재사용하지 않습니다. 커뮤니티형 제작은 기존처럼 먼저 `recommend_voice`를 사용하세요.
|
|
73
|
+
- 성공 응답의 `provider`, `primaryProvider`, `providerFallback`, `accountCostEvents`로 실제 합성 공급자와 비용을 확인합니다. 폴백 후 새 `productionPath`에 실제 보이스를 저장하며 이전 제작 핸들은 바꾸지 않습니다. 항상 최신 핸들을 다음 단계에 넘기세요.
|
|
74
|
+
- 제출 시간 초과·네트워크 단절·접수 후 결과 불명, 인증·입력·안전정책 오류에는 다른 유료 생성을 자동 실행하지 않습니다. 오류의 `fallbackStatus`, `fallbackReason`, `fallbackAvailable`, 접수된 비용을 확인하고 기존 작업부터 조회하세요. 실패했다고 비용이 없거나 환불되었다는 뜻은 아닙니다.
|
|
75
|
+
- ElevenLabs의 정확한 문자별 타임스탬프를 선택한 요청은 추정 자막으로 대체하지 않습니다. 다른 공급자 일반 합성이 ElevenLabs로 전환되더라도 `timingSource:"estimated-from-audio-duration"`인 자막이 정밀 타임스탬프로 바뀌지는 않습니다. 사용자 PC의 Companion 직접 Edge TTS는 서버 폴백 체인 밖입니다.
|
|
76
|
+
- 이미지·영상·LLM 폴백은 대응 서버가 지원하는 동일 기능/입력 경로에서만 동작합니다. SUNO, 음성 클로닝, 정밀 정렬 등 모든 독점 기능에 호환 대체가 있는 것은 아닙니다. 상태 조회만으로 미확인 유료 작업을 재생성하지 마세요.
|
|
77
|
+
|
|
78
|
+
## 장면 이미지 준비와 영상 표현 선택
|
|
79
|
+
|
|
80
|
+
다음 설정은 0.12.0부터 지원합니다. 기존 0.11.0 클라이언트는 위의 버전 고정 설정을 바꾸고 다시 연결해야 새 입력과 도구 안내를 사용할 수 있습니다. 이미지 모션 렌더에는 해당 기능을 지원하는 최신 컴패니언 런타임도 필요합니다.
|
|
81
|
+
|
|
82
|
+
- `plan_shorts_video`, `plan_commerce_video`, `plan_music_video`에서 `imageSourceMode: "web" | "ai" | "mixed"`와 `visualMotionMode: "image-motion" | "i2v"`를 독립적으로 선택합니다. 생략 시 기존 `ai + i2v`입니다. 반환된 `productionPath`를 이미지·영상·TTS·스티치에 계속 전달하면 다른 작업과 선택이 섞이지 않습니다.
|
|
83
|
+
- 웹은 사용자 계정의 Pexels/Pixabay 키로 장면별 `webSearchQuery`를 검색합니다. `web`은 결과가 없으면 중단하고, `mixed`만 결과가 없을 때 AI로 이어집니다. 검색 요청 자체가 실패하면 먼저 오류를 확인합니다. `ai`는 웹 검색을 실행하지 않습니다. 여기서 ‘AI만’은 주 장면 이미지 기준이며 편집용 아이콘·이모지 등은 별도입니다.
|
|
84
|
+
- 웹 결과는 즉시 `imageUrl`, `sceneVisual`, 출처·작가·이용 조건을 반환합니다. AI 생성만 `generationJobId`를 조회해야 합니다. `excludeImageUrls` 또는 직전 이미지 준비 결과의 `productionPath`로 웹 이미지 반복을 피하세요. 웹 사진이 실제 사건 사진이라는 뜻은 아니며, 최종 공개 전에 내용과 출처·사용 조건을 검토하세요.
|
|
85
|
+
- `image-motion`에서는 `generate_scene_video_prompt`와 `generate_scene_video`를 실행하지 않습니다. `stitch_timeline({productionPath,sceneVisuals:[{kind:"image",idx:0,url:imageUrl,durationSec:6,source:"web",sourcePage,attribution,license}],autoCompose:true})`처럼 이미지를 바로 넘깁니다. `list_composer_presets.imageMotions`의 ID와 0~100 강도를 `imageMotionPreset`/`imageMotionIntensity`로 지정할 수 있습니다. 기존 `sceneVideos` 입력도 유지합니다.
|
|
86
|
+
- `autoCompose:true`는 실제 인스펙터 모션·장면별 자막 계층·문맥에 맞는 안전한 라이브러리 소재를 자동 배치합니다. 명시한 스타일·오버레이가 우선이고, 필요하면 `false`로 수동 편집을 유지합니다. `compositionReport.autoComposition`에서 적용·생략 이유를 확인하세요. 모든 장면에 밈이나 효과음을 강제로 넣지 않으며 권리가 확인되지 않은 자산은 자동 삽입하지 않습니다.
|
|
87
|
+
|
|
69
88
|
## 채널 규격 지문 (벤치마킹)
|
|
70
89
|
|
|
71
90
|
```
|
|
@@ -86,7 +105,31 @@ detect_shots(원본별, 컴패니언) → analyze_edit_points(videos + shotsFile
|
|
|
86
105
|
- `analyze_edit_points`가 돌려주는 영상별 `burnedSubtitle`(박힌 자막 관측)을 `prepare_remake_timeline`의 `sourceVideos[].burnedSubtitle`로 그대로 넘기고 `subtitleCropMode: "auto"`를 주면 자막 박힌 소스만 하단 크롭됩니다.
|
|
87
106
|
- `[N]`/`[SN]` 행의 `audioContent`는 유료 TTS로 합성됩니다 — 실행 전 사용자 확인을 받으세요. 원본 다운로드·렌더는 이 PC의 컴패니언이 수행합니다.
|
|
88
107
|
|
|
89
|
-
##
|
|
108
|
+
## 영화·드라마 리뷰 제작 (0.13.0)
|
|
109
|
+
|
|
110
|
+
이 절은 0.13.0과 대응 서버·컴패니언 런타임에서 사용하는 경로입니다. 기존 설치된 0.12.0에 포함된 기능이 아니므로 위 설정의 버전을 바꾸고 클라이언트를 다시 연결하세요.
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
analyze_review_sources → resumePath → analyze_review_sources(resumePath) 반복
|
|
114
|
+
→ 원본 청크 분석 → 전체 서사 종합 → 원본 영상 재검증 → reviewSourcePath
|
|
115
|
+
→ plan_review_video → productionPath
|
|
116
|
+
→ recommend_voice(productionPath) → prepare_review_timeline(productionPath)
|
|
117
|
+
→ review_production → render_start → render_status → render_result → 시각·청취·스포일러 검토
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
- 원본은 YouTube ID/URL 또는 로컬 MP4/MOV/M4V/MKV/WebM, 최대 5편·원본별 24시간·총 500청크입니다. 기본 `analysisScope:"full"`은 Gemini 3.8로 처음부터 끝까지 영상과 오디오를 분석합니다. 컴패니언이 최대 300초/10MiB MP4로 압축하고 구간 사이 15초를 겹칩니다. 큰 원본 파일 하나를 직접 올리지는 않지만, **원작의 전체 내용이 압축 청크로 클라우드에 전송됩니다.** 사용자 업로드·과금 동의를 받은 뒤 `allowCloudVideoUpload:true`를 지정해야 합니다. 동의 없이는 샘플 분석으로 우회하지 않습니다.
|
|
121
|
+
- 시작 예: `analyze_review_sources({sources:[{kind:"local",videoPath:"/path/movie.mp4"}],workTitle:"작품명",allowCloudVideoUpload:true})`. YouTube는 `kind:"youtube",videoId:"URL 또는 ID"`입니다. 첫 호출은 원본·지원 기능 검사와 범위/예상 유료 단계 수만 보여 주고 과금하지 않습니다. 이후 `analyze_review_sources({resumePath,allowCloudVideoUpload:true})`를 `complete:true`까지 반복합니다. 기본 한 호출당 1단계이며 `progress`와 `review_analysis_status({resumePath})`로 진행 상황·누적 비용을 확인합니다.
|
|
122
|
+
- 체크포인트는 원본 식별자·전체 전사·장면·등장인물·서사·단계별 비용을 보존합니다. 오래된 `resumePath`로 재개해도 최신 영수증을 찾아 완료된 청크를 재호출하지 않습니다. 오디오 미검토/전사 누락, 원본 변경, 재검증 모순·근거 부족, 접수 여부가 불확실한 요청은 중단합니다. `failedStageResultPath`에 반환된 분석/반박 근거를 보존하며 자동 재시도하지 않습니다. 추가 비용을 사용자가 승인한 경우에만 `retryFailedStage:true`를 사용하세요.
|
|
123
|
+
- `resumePath`·`reviewSourcePath`·`productionPath` 및 실패 근거는 MCP의 임시 media 저장소에 있으며 기본 48시간 보존 정책의 정리 대상입니다. 첫 체크포인트 생성 후 48시간 안에 이어서 진행하세요. 장기 보관에는 연결된 체크포인트·근거 파일까지 별도 내보내기/백업이 필요하며 무기한 재개를 보장하지 않습니다.
|
|
124
|
+
- 전체 줄거리와 인물 주장은 관련 원본 MP4+음성을 다시 보내 검증합니다. 모든 대상 검증이 지지되어야 전체 분석 핸들이 나옵니다. 이는 모델 판정이며 모든 프레임의 관찰·전사 완전성·사실성을 보증하지 않습니다. 최종 영상·음성과 원본 근거는 사람이 확인해야 합니다.
|
|
125
|
+
- `analysisScope:"sample"`을 명시하면 예전 대표 프레임 점검(최대 18장)만 수행합니다. 원작 전체 이해가 아닙니다. `segments:[{startMs,endMs,note,dialogueText,spoilerLevel}]` 및 `transcriptSegments:[{startMs,endMs,text}]`를 제공할 수 있고, 구간에 완전히 포함된 대사만 인용 근거로 사용합니다. 이 자료로 부분 구간 리뷰를 만들려면 별도로 `allowPartialSourceReview:true`를 명시해야 합니다.
|
|
126
|
+
- 스포일러 등급은 자동으로 안전하다고 인증하지 않습니다. 미확인 구간은 `unknown`이며 `none`/`limited` 기획에서 제외됩니다. 장편의 편집 후보만 최대 500개/180,000자로 제한하고, 검증된 서사 근거 장면을 우선 선택한 내역을 `catalogSelection`으로 알려 줍니다. `sourceIds`로 직접 선택할 수도 있습니다. 전체 서사·전사는 자르지 않고 유지하며, 전편 맥락 한도를 넘으면 작품/회차 분리를 요청합니다.
|
|
127
|
+
- `plan_review_video({reviewSourcePath,workType:"film" 또는 "drama",workTitle,episode?,targetDurationSec:60..900,spoilerPolicy:"none"|"limited"|"full",reviewAngle,deliveryStyle})`로 리뷰 관점과 말투를 선택합니다. 사실·해석·가상 해석은 구분하며 실제 대사 인용은 제공한 원본 근거가 필요합니다.
|
|
128
|
+
- 내레이션 `[N]`, 원본 대사 `[S]`, 현장음 `[A]`를 편집할 수 있습니다. 리뷰 준비는 공통 자막 프리셋·아이콘/이모지 자동 배치를 사용하며 `autoCompose:false`와 명시 스타일/오버레이로 제어할 수 있습니다. 준비된 길이·실측 TTS가 맞지 않으면 자동 재합성이나 억지 늘이기 대신 오류를 확인하세요.
|
|
129
|
+
- TTS 공급자 우선순위는 Typecast → ElevenLabs → Supertone → Edge TTS → Supertonic2입니다. 보이스를 명시했으면 공급자도 지정하세요. 반환된 최신 `productionPath`를 계속 사용하면 동시 제작의 음성·원본이 섞이지 않습니다. 원본이 분석 후 바뀌면 다시 분석해야 합니다.
|
|
130
|
+
- 영상 및 음악의 사용 권리, 인용 내용, 대사·장면 타이밍, 스포일러, 최종 자막과 음성은 공개 전에 직접 검토해야 합니다. 자동 검토를 공개 허가나 품질 보증으로 표시하지 않습니다.
|
|
131
|
+
|
|
132
|
+
## 호출 한도
|
|
90
133
|
|
|
91
134
|
- 쓰기(생성) 호출 분당 20회, 조회 분당 120회, 동시 생성 2개 (서버 강제)
|
|
92
135
|
- 사용자당 활성 PAT 5개, 기본 만료 90일
|
package/lib/api-client.mjs
CHANGED
|
@@ -6,11 +6,21 @@ import { MCP_PROXY_VERSION } from "./config.mjs";
|
|
|
6
6
|
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
7
7
|
|
|
8
8
|
export class AimakeallApiError extends Error {
|
|
9
|
-
constructor(message, { errorCode = "", retryAfterSeconds = 0, status = 0 } = {}) {
|
|
9
|
+
constructor(message, { errorCode = "", retryAfterSeconds = 0, status = 0, accountCostEvents, acceptedTaskCosts, operationId, costUsd, usage, partialProviderUsage, fallbackMetadata } = {}) {
|
|
10
10
|
super(message);
|
|
11
11
|
this.errorCode = errorCode;
|
|
12
12
|
this.retryAfterSeconds = retryAfterSeconds;
|
|
13
13
|
this.status = status;
|
|
14
|
+
this.accountCostEvents = Array.isArray(accountCostEvents) ? accountCostEvents : [];
|
|
15
|
+
this.acceptedTaskCosts = Array.isArray(acceptedTaskCosts) ? acceptedTaskCosts : [];
|
|
16
|
+
this.operationId = typeof operationId === "string" ? operationId : "";
|
|
17
|
+
this.costUsd = Number.isFinite(costUsd) ? costUsd : 0;
|
|
18
|
+
this.usage = usage && typeof usage === "object" ? usage : null;
|
|
19
|
+
this.partialProviderUsage = partialProviderUsage === true;
|
|
20
|
+
for (const field of ["fallbackStatus", "fallbackReason", "capability", "provider"]) {
|
|
21
|
+
if (typeof fallbackMetadata?.[field] === "string") this[field] = fallbackMetadata[field].slice(0, 160);
|
|
22
|
+
}
|
|
23
|
+
if (typeof fallbackMetadata?.fallbackAvailable === "boolean") this.fallbackAvailable = fallbackMetadata.fallbackAvailable;
|
|
14
24
|
}
|
|
15
25
|
}
|
|
16
26
|
|
|
@@ -65,9 +75,13 @@ export function createApiClient({ apiBase, pat }) {
|
|
|
65
75
|
|
|
66
76
|
if (!response.ok) {
|
|
67
77
|
throw new AimakeallApiError(describeApiFailure(response.status, payload), {
|
|
68
|
-
errorCode: String(payload?.error || ""),
|
|
78
|
+
errorCode: String(payload?.code || payload?.error || ""),
|
|
69
79
|
retryAfterSeconds: Number(payload?.retryAfterSeconds) || Number(response.headers.get("retry-after")) || 0,
|
|
70
80
|
status: response.status,
|
|
81
|
+
accountCostEvents: payload?.accountCostEvents, acceptedTaskCosts: payload?.acceptedTaskCosts,
|
|
82
|
+
operationId: payload?.operationId, costUsd: payload?.costUsd,
|
|
83
|
+
usage: payload?.usage, partialProviderUsage: payload?.partialProviderUsage,
|
|
84
|
+
fallbackMetadata: payload,
|
|
71
85
|
});
|
|
72
86
|
}
|
|
73
87
|
return payload;
|
|
@@ -98,8 +112,12 @@ export function createApiClient({ apiBase, pat }) {
|
|
|
98
112
|
payload = null;
|
|
99
113
|
}
|
|
100
114
|
throw new AimakeallApiError(describeApiFailure(response.status, payload), {
|
|
101
|
-
errorCode: String(payload?.error || ""),
|
|
115
|
+
errorCode: String(payload?.code || payload?.error || ""),
|
|
102
116
|
status: response.status,
|
|
117
|
+
accountCostEvents: payload?.accountCostEvents, acceptedTaskCosts: payload?.acceptedTaskCosts,
|
|
118
|
+
operationId: payload?.operationId, costUsd: payload?.costUsd,
|
|
119
|
+
usage: payload?.usage, partialProviderUsage: payload?.partialProviderUsage,
|
|
120
|
+
fallbackMetadata: payload,
|
|
103
121
|
});
|
|
104
122
|
}
|
|
105
123
|
return {
|