mulmocast 2.0.8 → 2.0.9
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/lib/utils/provider2agent.d.ts +4 -0
- package/lib/utils/provider2agent.js +5 -0
- package/lib/utils/utils.js +24 -55
- package/package.json +7 -7
- package/scripts/test/README.md +48 -48
- package/scripts/test/test_all_image.json~ +0 -45
- package/scripts/test/test_all_movie.json~ +0 -37
- package/scripts/test/test_all_tts.json~ +0 -83
- package/scripts/test/test_audio_gemini.json~ +0 -67
- package/scripts/test/test_genai2.json~ +0 -84
- package/scripts/test/test_genai_movie.json~ +0 -22
- package/scripts/test/test_kotodama.json~ +0 -0
- package/scripts/test/test_lipsync2.json~ +0 -24
- package/scripts/test/test_movie2.json~ +0 -40
- package/scripts/test/test_play_to_end.json~ +0 -65
|
@@ -10,6 +10,7 @@ export declare const provider2TTSAgent: {
|
|
|
10
10
|
defaultModel: string;
|
|
11
11
|
defaultVoice: string;
|
|
12
12
|
keyName: string;
|
|
13
|
+
baseURLKeyName: string;
|
|
13
14
|
};
|
|
14
15
|
google: {
|
|
15
16
|
agentName: string;
|
|
@@ -49,6 +50,7 @@ export declare const provider2ImageAgent: {
|
|
|
49
50
|
defaultModel: string;
|
|
50
51
|
models: string[];
|
|
51
52
|
keyName: string;
|
|
53
|
+
baseURLKeyName: string;
|
|
52
54
|
};
|
|
53
55
|
google: {
|
|
54
56
|
agentName: string;
|
|
@@ -138,6 +140,7 @@ export declare const provider2LLMAgent: {
|
|
|
138
140
|
readonly agentName: "openAIAgent";
|
|
139
141
|
readonly defaultModel: "gpt-5";
|
|
140
142
|
readonly keyName: "OPENAI_API_KEY";
|
|
143
|
+
readonly baseURLKeyName: "OPENAI_BASE_URL";
|
|
141
144
|
readonly max_tokens: 8192;
|
|
142
145
|
readonly models: readonly ["gpt-5", "gpt-5-nano", "gpt-5-mini", "gpt-4.1", "gpt-4.1-mini", "gpt-4.1-nano", "o3", "o3-mini", "o3-pro", "o1", "o1-pro", "gpt-4o", "gpt-4o-mini"];
|
|
143
146
|
};
|
|
@@ -147,6 +150,7 @@ export declare const provider2LLMAgent: {
|
|
|
147
150
|
readonly max_tokens: 8192;
|
|
148
151
|
readonly models: readonly ["claude-opus-4-1-20250805", "claude-opus-4-20250514", "claude-sonnet-4-20250514", "claude-3-7-sonnet-20250219", "claude-3-haiku-20240307"];
|
|
149
152
|
readonly keyName: "ANTHROPIC_API_KEY";
|
|
153
|
+
readonly apiKeyNameOverride: "ANTHROPIC_API_TOKEN";
|
|
150
154
|
};
|
|
151
155
|
readonly gemini: {
|
|
152
156
|
readonly agentName: "geminiAgent";
|
|
@@ -11,6 +11,7 @@ export const provider2TTSAgent = {
|
|
|
11
11
|
defaultModel: "gpt-4o-mini-tts",
|
|
12
12
|
defaultVoice: "shimmer",
|
|
13
13
|
keyName: "OPENAI_API_KEY",
|
|
14
|
+
baseURLKeyName: "OPENAI_BASE_URL",
|
|
14
15
|
},
|
|
15
16
|
google: {
|
|
16
17
|
agentName: "ttsGoogleAgent",
|
|
@@ -52,6 +53,7 @@ export const provider2ImageAgent = {
|
|
|
52
53
|
defaultModel: "gpt-image-1",
|
|
53
54
|
models: ["dall-e-3", "gpt-image-1"],
|
|
54
55
|
keyName: "OPENAI_API_KEY",
|
|
56
|
+
baseURLKeyName: "OPENAI_BASE_URL",
|
|
55
57
|
},
|
|
56
58
|
google: {
|
|
57
59
|
agentName: "imageGenAIAgent",
|
|
@@ -251,6 +253,7 @@ export const provider2LLMAgent = {
|
|
|
251
253
|
agentName: "openAIAgent",
|
|
252
254
|
defaultModel: "gpt-5",
|
|
253
255
|
keyName: "OPENAI_API_KEY",
|
|
256
|
+
baseURLKeyName: "OPENAI_BASE_URL",
|
|
254
257
|
max_tokens: 8192,
|
|
255
258
|
models: [
|
|
256
259
|
"gpt-5",
|
|
@@ -274,6 +277,8 @@ export const provider2LLMAgent = {
|
|
|
274
277
|
max_tokens: 8192,
|
|
275
278
|
models: ["claude-opus-4-1-20250805", "claude-opus-4-20250514", "claude-sonnet-4-20250514", "claude-3-7-sonnet-20250219", "claude-3-haiku-20240307"],
|
|
276
279
|
keyName: "ANTHROPIC_API_KEY",
|
|
280
|
+
apiKeyNameOverride: "ANTHROPIC_API_TOKEN",
|
|
281
|
+
// GraphAI is currently using ANTHROPIC_API_KEY, but the official name is ANTHROPIC_API_TOKEN.
|
|
277
282
|
},
|
|
278
283
|
gemini: {
|
|
279
284
|
agentName: "geminiAgent",
|
package/lib/utils/utils.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* (No Node.js built-ins like fs, path, dotenv, etc.)
|
|
4
4
|
* Works in both Node.js and modern browsers.
|
|
5
5
|
*/
|
|
6
|
-
import { provider2LLMAgent } from "./provider2agent.js";
|
|
6
|
+
import { provider2LLMAgent, provider2TTSAgent, provider2ImageAgent, provider2MovieAgent, provider2SoundEffectAgent, provider2LipSyncAgent, } from "./provider2agent.js";
|
|
7
7
|
export const llmPair = (_llm, _model) => {
|
|
8
8
|
const llmKey = _llm ?? "openai";
|
|
9
9
|
const agent = provider2LLMAgent[llmKey]?.agentName ?? provider2LLMAgent.openai.agentName;
|
|
@@ -42,61 +42,30 @@ export const settings2GraphAIConfig = (settings, env) => {
|
|
|
42
42
|
const getKey = (prefix, key) => {
|
|
43
43
|
return settings?.[`${prefix}_${key}`] ?? settings?.[key] ?? env?.[`${prefix}_${key}`] ?? env?.[key];
|
|
44
44
|
};
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
imageReplicateAgent: {
|
|
58
|
-
apiKey: getKey("IMAGE", "REPLICATE_API_TOKEN"),
|
|
59
|
-
},
|
|
60
|
-
imageGenAIAgent: {
|
|
61
|
-
apiKey: getKey("IMAGE", "GEMINI_API_KEY"),
|
|
62
|
-
},
|
|
63
|
-
movieReplicateAgent: {
|
|
64
|
-
apiKey: getKey("MOVIE", "REPLICATE_API_TOKEN"),
|
|
65
|
-
},
|
|
66
|
-
movieGenAIAgent: {
|
|
67
|
-
apiKey: getKey("MOVIE", "GEMINI_API_KEY"),
|
|
68
|
-
},
|
|
69
|
-
ttsOpenaiAgent: {
|
|
70
|
-
apiKey: getKey("TTS", "OPENAI_API_KEY"),
|
|
71
|
-
baseURL: getKey("TTS", "OPENAI_BASE_URL"),
|
|
72
|
-
},
|
|
73
|
-
ttsNijivoiceAgent: {
|
|
74
|
-
apiKey: getKey("TTS", "NIJIVOICE_API_KEY"),
|
|
75
|
-
},
|
|
76
|
-
ttsGoogleAgent: {
|
|
77
|
-
apiKey: getKey("TTS", "GEMINI_API_KEY"),
|
|
78
|
-
},
|
|
79
|
-
ttsGeminiAgent: {
|
|
80
|
-
apiKey: getKey("TTS", "GEMINI_API_KEY"),
|
|
81
|
-
},
|
|
82
|
-
ttsElevenlabsAgent: {
|
|
83
|
-
apiKey: getKey("TTS", "ELEVENLABS_API_KEY"),
|
|
84
|
-
},
|
|
85
|
-
ttsKotodamaAgent: {
|
|
86
|
-
apiKey: getKey("TTS", "KOTODAMA_API_KEY"),
|
|
87
|
-
},
|
|
88
|
-
soundEffectReplicateAgent: {
|
|
89
|
-
apiKey: getKey("SOUND_EFFECT", "REPLICATE_API_TOKEN"),
|
|
90
|
-
},
|
|
91
|
-
lipSyncReplicateAgent: {
|
|
92
|
-
apiKey: getKey("LIPSYNC", "REPLICATE_API_TOKEN"),
|
|
93
|
-
},
|
|
94
|
-
// TODO
|
|
95
|
-
// browserlessAgent
|
|
96
|
-
// ttsGoogleAgent
|
|
97
|
-
// geminiAgent, groqAgent for tool
|
|
98
|
-
// TAVILY_API_KEY ( for deep research)
|
|
45
|
+
const addProviderConfigs = (config, providers, prefix) => {
|
|
46
|
+
Object.entries(providers).forEach(([__provider, info]) => {
|
|
47
|
+
if (info.agentName === "mediaMockAgent" || !info.keyName)
|
|
48
|
+
return;
|
|
49
|
+
const apiKeyName = info.apiKeyNameOverride || info.keyName;
|
|
50
|
+
config[info.agentName] = {
|
|
51
|
+
apiKey: getKey(prefix, apiKeyName),
|
|
52
|
+
};
|
|
53
|
+
if (info.baseURLKeyName) {
|
|
54
|
+
config[info.agentName].baseURL = getKey(prefix, info.baseURLKeyName);
|
|
55
|
+
}
|
|
56
|
+
});
|
|
99
57
|
};
|
|
58
|
+
const config = {};
|
|
59
|
+
addProviderConfigs(config, provider2LLMAgent, "LLM");
|
|
60
|
+
addProviderConfigs(config, provider2TTSAgent, "TTS");
|
|
61
|
+
addProviderConfigs(config, provider2ImageAgent, "IMAGE");
|
|
62
|
+
addProviderConfigs(config, provider2MovieAgent, "MOVIE");
|
|
63
|
+
addProviderConfigs(config, provider2SoundEffectAgent, "SOUND_EFFECT");
|
|
64
|
+
addProviderConfigs(config, provider2LipSyncAgent, "LIPSYNC");
|
|
65
|
+
// TODO
|
|
66
|
+
// browserlessAgent
|
|
67
|
+
// geminiAgent, groqAgent for tool
|
|
68
|
+
// TAVILY_API_KEY ( for deep research)
|
|
100
69
|
return deepClean(config) ?? {};
|
|
101
70
|
};
|
|
102
71
|
export const deepClean = (input) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mulmocast",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.9",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.node.js",
|
|
@@ -96,11 +96,11 @@
|
|
|
96
96
|
"graphai": "^2.0.16",
|
|
97
97
|
"jsdom": "^27.2.0",
|
|
98
98
|
"marked": "^17.0.1",
|
|
99
|
-
"mulmocast-vision": "^1.0.
|
|
99
|
+
"mulmocast-vision": "^1.0.8",
|
|
100
100
|
"ora": "^9.0.0",
|
|
101
|
-
"puppeteer": "^24.
|
|
101
|
+
"puppeteer": "^24.32.0",
|
|
102
102
|
"replicate": "^1.4.0",
|
|
103
|
-
"yaml": "^2.8.
|
|
103
|
+
"yaml": "^2.8.2",
|
|
104
104
|
"yargs": "^18.0.0",
|
|
105
105
|
"zod": "^4.1.13"
|
|
106
106
|
},
|
|
@@ -114,10 +114,10 @@
|
|
|
114
114
|
"eslint-config-prettier": "^10.1.8",
|
|
115
115
|
"eslint-plugin-prettier": "^5.5.4",
|
|
116
116
|
"eslint-plugin-sonarjs": "^3.0.5",
|
|
117
|
-
"prettier": "^3.7.
|
|
118
|
-
"tsx": "^4.
|
|
117
|
+
"prettier": "^3.7.4",
|
|
118
|
+
"tsx": "^4.21.0",
|
|
119
119
|
"typescript": "^5.9.3",
|
|
120
|
-
"typescript-eslint": "^8.48.
|
|
120
|
+
"typescript-eslint": "^8.48.1"
|
|
121
121
|
},
|
|
122
122
|
"engines": {
|
|
123
123
|
"node": ">=20.0.0"
|
package/scripts/test/README.md
CHANGED
|
@@ -12,10 +12,10 @@ This directory contains MulmoScript samples for testing MulmoCast features.
|
|
|
12
12
|
|
|
13
13
|
Simple test scripts for basic functionality verification
|
|
14
14
|
|
|
15
|
-
- **test_hello.json** - 最もシンプルなHello Worldテスト / Simplest Hello World test
|
|
16
|
-
- **test.json** - 基本的な動作テスト / Basic functionality test
|
|
17
|
-
- **test1.json
|
|
18
|
-
- **test_beats.json** - Beatの基本機能テスト / Beat basic features test
|
|
15
|
+
- [**test_hello.json**](./test_hello.json) - 最もシンプルなHello Worldテスト / Simplest Hello World test
|
|
16
|
+
- [**test.json**](./test.json) - 基本的な動作テスト / Basic functionality test
|
|
17
|
+
- [**test1.json**](./test1.json), [**test2.json**](./test2.json) - 追加の基本テスト / Additional basic tests
|
|
18
|
+
- [**test_beats.json**](./test_beats.json) - Beatの基本機能テスト / Beat basic features test
|
|
19
19
|
|
|
20
20
|
### 🎤 TTS(音声合成)テスト / TTS (Text-to-Speech) Tests
|
|
21
21
|
|
|
@@ -23,13 +23,13 @@ Simple test scripts for basic functionality verification
|
|
|
23
23
|
|
|
24
24
|
Tests for various TTS providers
|
|
25
25
|
|
|
26
|
-
- **test_all_tts.json** - 全TTSプロバイダーのテスト(OpenAI, Gemini, Google, ElevenLabs, Nijivoice) / All TTS providers test
|
|
27
|
-
- **test_audio.json** - 音声パラメータのテスト(padding, duration, movieVolumeなど) / Audio parameters test
|
|
28
|
-
- **test_audio_gemini.json** - Gemini TTSの個別テスト / Gemini TTS specific test
|
|
29
|
-
- **test_audio_instructions.json** - OpenAI TTS instructionsのテスト / OpenAI TTS instructions test
|
|
30
|
-
- **test_elevenlabs_models.json** - ElevenLabsの複数モデルテスト / ElevenLabs multiple models test
|
|
31
|
-
- **test_voices.json** - 複数の音声設定テスト / Multiple voice settings test
|
|
32
|
-
- **test_mixed_providers.json** - 複数のTTSプロバイダー混在テスト / Mixed TTS providers test
|
|
26
|
+
- [**test_all_tts.json**](./test_all_tts.json) - 全TTSプロバイダーのテスト(OpenAI, Gemini, Google, ElevenLabs, Nijivoice) / All TTS providers test
|
|
27
|
+
- [**test_audio.json**](./test_audio.json) - 音声パラメータのテスト(padding, duration, movieVolumeなど) / Audio parameters test
|
|
28
|
+
- [**test_audio_gemini.json**](./test_audio_gemini.json) - Gemini TTSの個別テスト / Gemini TTS specific test
|
|
29
|
+
- [**test_audio_instructions.json**](./test_audio_instructions.json) - OpenAI TTS instructionsのテスト / OpenAI TTS instructions test
|
|
30
|
+
- [**test_elevenlabs_models.json**](./test_elevenlabs_models.json) - ElevenLabsの複数モデルテスト / ElevenLabs multiple models test
|
|
31
|
+
- [**test_voices.json**](./test_voices.json) - 複数の音声設定テスト / Multiple voice settings test
|
|
32
|
+
- [**test_mixed_providers.json**](./test_mixed_providers.json) - 複数のTTSプロバイダー混在テスト / Mixed TTS providers test
|
|
33
33
|
|
|
34
34
|
### 🖼️ 画像生成テスト / Image Generation Tests
|
|
35
35
|
|
|
@@ -37,13 +37,13 @@ Tests for various TTS providers
|
|
|
37
37
|
|
|
38
38
|
Image generation feature tests
|
|
39
39
|
|
|
40
|
-
- **test_images.json** - 画像生成の基本テスト / Basic image generation test
|
|
41
|
-
- **test_hello_image.json** - Hello World画像テスト / Hello World image test
|
|
42
|
-
- **test_image_refs.json** - 参照画像を使った生成テスト / Image generation with references
|
|
43
|
-
- **test_markdown.json** - Markdown形式の画像テスト / Markdown format image test
|
|
44
|
-
- **test_html.json** - HTMLから画像生成テスト / HTML to image test
|
|
45
|
-
- **test_vision.json** - Vision APIを使った画像生成テスト / Vision API image test
|
|
46
|
-
- **test_layout.json** - レイアウト機能のテスト / Layout features test
|
|
40
|
+
- [**test_images.json**](./test_images.json) - 画像生成の基本テスト / Basic image generation test
|
|
41
|
+
- [**test_hello_image.json**](./test_hello_image.json) - Hello World画像テスト / Hello World image test
|
|
42
|
+
- [**test_image_refs.json**](./test_image_refs.json) - 参照画像を使った生成テスト / Image generation with references
|
|
43
|
+
- [**test_markdown.json**](./test_markdown.json) - Markdown形式の画像テスト / Markdown format image test
|
|
44
|
+
- [**test_html.json**](./test_html.json) - HTMLから画像生成テスト / HTML to image test
|
|
45
|
+
- [**test_vision.json**](./test_vision.json) - Vision APIを使った画像生成テスト / Vision API image test
|
|
46
|
+
- [**test_layout.json**](./test_layout.json) - レイアウト機能のテスト / Layout features test
|
|
47
47
|
|
|
48
48
|
### 🎬 動画生成テスト / Video Generation Tests
|
|
49
49
|
|
|
@@ -51,12 +51,12 @@ Image generation feature tests
|
|
|
51
51
|
|
|
52
52
|
Video generation feature tests
|
|
53
53
|
|
|
54
|
-
- **test_movie.json** - 動画生成の基本テスト(imagePrompt + moviePrompt) / Basic video generation test
|
|
55
|
-
- **test_movie2.json** - 動画生成の追加テスト / Additional video generation test
|
|
56
|
-
- **test_genai_movie.json** - GenAI動画生成テスト / GenAI video generation test
|
|
57
|
-
- **test_genai.json** - GenAI機能テスト / GenAI features test
|
|
58
|
-
- **test_replicate.json** - Replicate動画生成テスト / Replicate video generation test
|
|
59
|
-
- **test_mv.json** - ミュージックビデオ形式のテスト / Music video format test
|
|
54
|
+
- [**test_movie.json**](./test_movie.json) - 動画生成の基本テスト(imagePrompt + moviePrompt) / Basic video generation test
|
|
55
|
+
- [**test_movie2.json**](./test_movie2.json) - 動画生成の追加テスト / Additional video generation test
|
|
56
|
+
- [**test_genai_movie.json**](./test_genai_movie.json) - GenAI動画生成テスト / GenAI video generation test
|
|
57
|
+
- [**test_genai.json**](./test_genai.json) - GenAI機能テスト / GenAI features test
|
|
58
|
+
- [**test_replicate.json**](./test_replicate.json) - Replicate動画生成テスト / Replicate video generation test
|
|
59
|
+
- [**test_mv.json**](./test_mv.json) - ミュージックビデオ形式のテスト / Music video format test
|
|
60
60
|
|
|
61
61
|
### 🎭 高度な機能テスト / Advanced Feature Tests
|
|
62
62
|
|
|
@@ -64,17 +64,17 @@ Video generation feature tests
|
|
|
64
64
|
|
|
65
65
|
Special features and complex scenario tests
|
|
66
66
|
|
|
67
|
-
- **test_spillover.json** - 音声スピルオーバー機能テスト / Audio spillover feature test
|
|
68
|
-
- **test_lipsync.json** - リップシンク機能テスト / Lip-sync feature test
|
|
69
|
-
- **test_transition.json** - トランジション効果テスト / Transition effects test
|
|
70
|
-
- **test_transition_no_audio.json** - 音声なしトランジションテスト / Transition without audio test
|
|
71
|
-
- **test_slideout_left_no_audio.json** - スライドアウト効果テスト / Slide-out effect test
|
|
72
|
-
- **test_sound_effect.json** - サウンドエフェクトテスト / Sound effect test
|
|
73
|
-
- **test_voice_over.json** - ボイスオーバー機能テスト / Voice-over feature test
|
|
74
|
-
- **test_captions.json** - 字幕機能テスト / Caption feature test
|
|
75
|
-
- **test_hello_caption.json** - Hello World字幕テスト / Hello World caption test
|
|
76
|
-
- **test_loop.json** - ループ再生テスト / Loop playback test
|
|
77
|
-
- **test_video_speed.json** - 動画速度調整テスト / Video speed adjustment test
|
|
67
|
+
- [**test_spillover.json**](./test_spillover.json) - 音声スピルオーバー機能テスト / Audio spillover feature test
|
|
68
|
+
- [**test_lipsync.json**](./test_lipsync.json) - リップシンク機能テスト / Lip-sync feature test
|
|
69
|
+
- [**test_transition.json**](./test_transition.json) - トランジション効果テスト / Transition effects test
|
|
70
|
+
- [**test_transition_no_audio.json**](./test_transition_no_audio.json) - 音声なしトランジションテスト / Transition without audio test
|
|
71
|
+
- [**test_slideout_left_no_audio.json**](./test_slideout_left_no_audio.json) - スライドアウト効果テスト / Slide-out effect test
|
|
72
|
+
- [**test_sound_effect.json**](./test_sound_effect.json) - サウンドエフェクトテスト / Sound effect test
|
|
73
|
+
- [**test_voice_over.json**](./test_voice_over.json) - ボイスオーバー機能テスト / Voice-over feature test
|
|
74
|
+
- [**test_captions.json**](./test_captions.json) - 字幕機能テスト / Caption feature test
|
|
75
|
+
- [**test_hello_caption.json**](./test_hello_caption.json) - Hello World字幕テスト / Hello World caption test
|
|
76
|
+
- [**test_loop.json**](./test_loop.json) - ループ再生テスト / Loop playback test
|
|
77
|
+
- [**test_video_speed.json**](./test_video_speed.json) - 動画速度調整テスト / Video speed adjustment test
|
|
78
78
|
|
|
79
79
|
### 🔧 特殊条件テスト / Special Condition Tests
|
|
80
80
|
|
|
@@ -82,13 +82,13 @@ Special features and complex scenario tests
|
|
|
82
82
|
|
|
83
83
|
Edge cases and special condition tests
|
|
84
84
|
|
|
85
|
-
- **test_no_audio.json** - 音声なし動画テスト / Video without audio test
|
|
86
|
-
- **test_no_audio_with_credit.json** - クレジット付き音声なしテスト / No audio with credits test
|
|
87
|
-
- **test_hello_nobgm.json** - BGMなしテスト / Test without BGM
|
|
88
|
-
- **test_size_error.json** - サイズエラーテスト / Size error test
|
|
89
|
-
- **test_media.json** - メディアファイル処理テスト / Media file processing test
|
|
90
|
-
- **test_order.json** - 順序処理テスト / Order processing test
|
|
91
|
-
- **test_order_portrait.json** - 縦向き順序テスト / Portrait order test
|
|
85
|
+
- [**test_no_audio.json**](./test_no_audio.json) - 音声なし動画テスト / Video without audio test
|
|
86
|
+
- [**test_no_audio_with_credit.json**](./test_no_audio_with_credit.json) - クレジット付き音声なしテスト / No audio with credits test
|
|
87
|
+
- [**test_hello_nobgm.json**](./test_hello_nobgm.json) - BGMなしテスト / Test without BGM
|
|
88
|
+
- [**test_size_error.json**](./test_size_error.json) - サイズエラーテスト / Size error test
|
|
89
|
+
- [**test_media.json**](./test_media.json) - メディアファイル処理テスト / Media file processing test
|
|
90
|
+
- [**test_order.json**](./test_order.json) - 順序処理テスト / Order processing test
|
|
91
|
+
- [**test_order_portrait.json**](./test_order_portrait.json) - 縦向き順序テスト / Portrait order test
|
|
92
92
|
|
|
93
93
|
### 🌍 多言語テスト / Multi-language Tests
|
|
94
94
|
|
|
@@ -96,8 +96,8 @@ Edge cases and special condition tests
|
|
|
96
96
|
|
|
97
97
|
Language setting tests
|
|
98
98
|
|
|
99
|
-
- **test_lang.json** - 多言語サポートテスト / Multi-language support test
|
|
100
|
-
- **test_en.json** - 英語専用テスト / English-only test
|
|
99
|
+
- [**test_lang.json**](./test_lang.json) - 多言語サポートテスト / Multi-language support test
|
|
100
|
+
- [**test_en.json**](./test_en.json) - 英語専用テスト / English-only test
|
|
101
101
|
|
|
102
102
|
### 🎯 プロバイダー別テスト / Provider-Specific Tests
|
|
103
103
|
|
|
@@ -105,10 +105,10 @@ Language setting tests
|
|
|
105
105
|
|
|
106
106
|
Provider-specific feature tests
|
|
107
107
|
|
|
108
|
-
- **test_hello_google.json** - Google TTS専用テスト / Google TTS specific test
|
|
109
|
-
- **gpt.json** - GPTモデルテスト / GPT model test
|
|
110
|
-
- **mulmo_story.json** - ストーリー形式テスト / Story format test
|
|
111
|
-
- **nano_banana.json** - カスタムサンプル / Custom sample
|
|
108
|
+
- [**test_hello_google.json**](./test_hello_google.json) - Google TTS専用テスト / Google TTS specific test
|
|
109
|
+
- [**gpt.json**](./gpt.json) - GPTモデルテスト / GPT model test
|
|
110
|
+
- [**mulmo_story.json**](./mulmo_story.json) - ストーリー形式テスト / Story format test
|
|
111
|
+
- [**nano_banana.json**](./nano_banana.json) - カスタムサンプル / Custom sample
|
|
112
112
|
|
|
113
113
|
## 🚀 使い方 / Usage
|
|
114
114
|
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$mulmocast": {
|
|
3
|
-
"version": "1.1"
|
|
4
|
-
},
|
|
5
|
-
"lang": "ja",
|
|
6
|
-
"title": "All Image Providers Test",
|
|
7
|
-
"imageParams": {
|
|
8
|
-
"canvasSize": {
|
|
9
|
-
"width": 1024,
|
|
10
|
-
"height": 1024
|
|
11
|
-
}
|
|
12
|
-
},
|
|
13
|
-
"beats": [
|
|
14
|
-
{
|
|
15
|
-
"speaker": "Presenter",
|
|
16
|
-
"text": "こんにちは、テストです。",
|
|
17
|
-
"image": {
|
|
18
|
-
"type": "generated",
|
|
19
|
-
"prompt": "美しい日本庭園",
|
|
20
|
-
"provider": "openai",
|
|
21
|
-
"model": "gpt-image-1"
|
|
22
|
-
}
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
"speaker": "Presenter",
|
|
26
|
-
"text": "こんにちは、テストです。",
|
|
27
|
-
"image": {
|
|
28
|
-
"type": "generated",
|
|
29
|
-
"prompt": "美しい日本庭園",
|
|
30
|
-
"provider": "google",
|
|
31
|
-
"model": "gemini-2.5-flash-image"
|
|
32
|
-
}
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
"speaker": "Presenter",
|
|
36
|
-
"text": "こんにちは、テストです。",
|
|
37
|
-
"image": {
|
|
38
|
-
"type": "generated",
|
|
39
|
-
"prompt": "美しい日本庭園",
|
|
40
|
-
"provider": "replicate",
|
|
41
|
-
"model": "bytedance/seedream-4"
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
]
|
|
45
|
-
}
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$mulmocast": {
|
|
3
|
-
"version": "1.1"
|
|
4
|
-
},
|
|
5
|
-
"lang": "ja",
|
|
6
|
-
"title": "All Movie Providers Test",
|
|
7
|
-
"imageParams": {
|
|
8
|
-
"canvasSize": {
|
|
9
|
-
"width": 1280,
|
|
10
|
-
"height": 720
|
|
11
|
-
}
|
|
12
|
-
},
|
|
13
|
-
"beats": [
|
|
14
|
-
{
|
|
15
|
-
"speaker": "Presenter",
|
|
16
|
-
"text": "こんにちは、テストです。",
|
|
17
|
-
"image": {
|
|
18
|
-
"type": "movie",
|
|
19
|
-
"prompt": "美しい日本庭園を散歩するカメラワーク",
|
|
20
|
-
"provider": "google",
|
|
21
|
-
"model": "veo-2.0-generate-001",
|
|
22
|
-
"duration": 5
|
|
23
|
-
}
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
"speaker": "Presenter",
|
|
27
|
-
"text": "こんにちは、テストです。",
|
|
28
|
-
"image": {
|
|
29
|
-
"type": "movie",
|
|
30
|
-
"prompt": "美しい日本庭園を散歩するカメラワーク",
|
|
31
|
-
"provider": "replicate",
|
|
32
|
-
"model": "bytedance/seedance-1-lite",
|
|
33
|
-
"duration": 5
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
]
|
|
37
|
-
}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$mulmocast": {
|
|
3
|
-
"version": "1.1"
|
|
4
|
-
},
|
|
5
|
-
"lang": "ja",
|
|
6
|
-
"title": "All TTS Providers Test",
|
|
7
|
-
"speechParams": {
|
|
8
|
-
"speakers": {
|
|
9
|
-
"OpenAI": {
|
|
10
|
-
"provider": "openai",
|
|
11
|
-
"voiceId": "shimmer"
|
|
12
|
-
},
|
|
13
|
-
"Gemini": {
|
|
14
|
-
"provider": "gemini",
|
|
15
|
-
"voiceId": "Kore"
|
|
16
|
-
},
|
|
17
|
-
"Google": {
|
|
18
|
-
"provider": "google",
|
|
19
|
-
"voiceId": "ja-JP-Standard-A"
|
|
20
|
-
},
|
|
21
|
-
"ElevenLabs": {
|
|
22
|
-
"provider": "elevenlabs",
|
|
23
|
-
"voiceId": "3JDquces8E8bkmvbh6Bc"
|
|
24
|
-
},
|
|
25
|
-
"Nijivoice": {
|
|
26
|
-
"provider": "nijivoice",
|
|
27
|
-
"voiceId": "231e0170-0ece-4155-be44-231423062f41"
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
},
|
|
31
|
-
"beats": [
|
|
32
|
-
{
|
|
33
|
-
"speaker": "OpenAI",
|
|
34
|
-
"text": "こんにちは、テストです。",
|
|
35
|
-
"image": {
|
|
36
|
-
"type": "textSlide",
|
|
37
|
-
"slide": {
|
|
38
|
-
"title": "OpenAI TTS"
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
"speaker": "Gemini",
|
|
44
|
-
"text": "こんにちは、テストです。",
|
|
45
|
-
"image": {
|
|
46
|
-
"type": "textSlide",
|
|
47
|
-
"slide": {
|
|
48
|
-
"title": "Gemini TTS"
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
"speaker": "Google",
|
|
54
|
-
"text": "こんにちは、テストです。",
|
|
55
|
-
"image": {
|
|
56
|
-
"type": "textSlide",
|
|
57
|
-
"slide": {
|
|
58
|
-
"title": "Google TTS"
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
"speaker": "ElevenLabs",
|
|
64
|
-
"text": "こんにちは、テストです。",
|
|
65
|
-
"image": {
|
|
66
|
-
"type": "textSlide",
|
|
67
|
-
"slide": {
|
|
68
|
-
"title": "ElevenLabs TTS"
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
},
|
|
72
|
-
{
|
|
73
|
-
"speaker": "Nijivoice",
|
|
74
|
-
"text": "こんにちは、テストです。",
|
|
75
|
-
"image": {
|
|
76
|
-
"type": "textSlide",
|
|
77
|
-
"slide": {
|
|
78
|
-
"title": "Nijivoice TTS"
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
]
|
|
83
|
-
}
|
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$mulmocast": {
|
|
3
|
-
"version": "1.1"
|
|
4
|
-
},
|
|
5
|
-
"lang": "en",
|
|
6
|
-
"title": "Audio Instructions Test",
|
|
7
|
-
"speechParams": {
|
|
8
|
-
"speakers": {
|
|
9
|
-
"Presenter": {
|
|
10
|
-
"provider": "google",
|
|
11
|
-
"voiceId": "ja-JP-Standard-A"
|
|
12
|
-
},
|
|
13
|
-
"Presenter2": {
|
|
14
|
-
"provider": "google",
|
|
15
|
-
"voiceId": "ja-JP-Standard-B"
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
},
|
|
19
|
-
"beats": [
|
|
20
|
-
{
|
|
21
|
-
"speaker": "Presenter",
|
|
22
|
-
"text": "Hello, I'm a presenter. I have no instructions.",
|
|
23
|
-
"image": {
|
|
24
|
-
"type": "textSlide",
|
|
25
|
-
"slide": {
|
|
26
|
-
"title": "Presenter"
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"speaker": "Presenter2",
|
|
32
|
-
"text": "Hello, I'm a presenter 2. My instructions are 'Speak in a cheerful and positive tone'.",
|
|
33
|
-
"image": {
|
|
34
|
-
"type": "textSlide",
|
|
35
|
-
"slide": {
|
|
36
|
-
"title": "Presenter 2"
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
"speaker": "Presenter",
|
|
42
|
-
"text": "Hello, I'm a presenter. I have a British English instruction.",
|
|
43
|
-
"speechOptions": {
|
|
44
|
-
"instruction": "Speak in British English."
|
|
45
|
-
},
|
|
46
|
-
"image": {
|
|
47
|
-
"type": "textSlide",
|
|
48
|
-
"slide": {
|
|
49
|
-
"title": "Presenter with British English instruction"
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
"speaker": "Presenter",
|
|
55
|
-
"text": "Hello, I'm a presenter. I have a whisper instruction.",
|
|
56
|
-
"speechOptions": {
|
|
57
|
-
"instruction": "Whisper softly, like a pillow talk."
|
|
58
|
-
},
|
|
59
|
-
"image": {
|
|
60
|
-
"type": "textSlide",
|
|
61
|
-
"slide": {
|
|
62
|
-
"title": "Presenter with whisper instruction"
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
]
|
|
67
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$mulmocast": { "version": "1.1" },
|
|
3
|
-
"imageParams": {
|
|
4
|
-
"provider": "google",
|
|
5
|
-
"style": "<style>Photo realistic.</style>"
|
|
6
|
-
},
|
|
7
|
-
"movieParams": {
|
|
8
|
-
"provider": "google"
|
|
9
|
-
},
|
|
10
|
-
"lang": "en",
|
|
11
|
-
"beats": [
|
|
12
|
-
{
|
|
13
|
-
"id": "gemini_3_pro_image_preview",
|
|
14
|
-
"text": "image generated by gemini-3-pro-image-preview",
|
|
15
|
-
"imagePrompt": "a woman is walking through a busy Tokyo street at night, she is wearing dark sunglasses",
|
|
16
|
-
"imageParams": {
|
|
17
|
-
"model": "gemini-3-pro-image-preview"
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
"id": "gemini_2_5_flash_image",
|
|
22
|
-
"text": "image generated by gemini-2.5-flash-image",
|
|
23
|
-
"imagePrompt": "a woman is walking through a busy Tokyo street at night, she is wearing dark sunglasses",
|
|
24
|
-
"imageParams": {
|
|
25
|
-
"model": "gemini-2.5-flash-image"
|
|
26
|
-
}
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
"id": "imagen_4",
|
|
30
|
-
"text": "image generated by imagen-4",
|
|
31
|
-
"imagePrompt": "a woman is walking through a busy Tokyo street at night, she is wearing dark sunglasses"
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
"id": "imagen_4_ultra",
|
|
35
|
-
"text": "image generated by imagen-4",
|
|
36
|
-
"imagePrompt": "a woman is walking through a busy Tokyo street at night, she is wearing dark sunglasses",
|
|
37
|
-
"imageParams": {
|
|
38
|
-
"model": "imagen-4.0-ultra-generate-preview-06-06"
|
|
39
|
-
}
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
"id": "genai_veo2",
|
|
43
|
-
"text": "movie generated by veo2",
|
|
44
|
-
"duration": 5,
|
|
45
|
-
"moviePrompt": "a woman is walking through a busy Tokyo street at night, she is wearing dark sunglasses"
|
|
46
|
-
},
|
|
47
|
-
{
|
|
48
|
-
"id": "genai_veo2_image",
|
|
49
|
-
"text": "movie generated by veo2 with image",
|
|
50
|
-
"duration": 5,
|
|
51
|
-
"imagePrompt": "a woman is walking through a busy Tokyo street at night, she is wearing dark sunglasses",
|
|
52
|
-
"moviePrompt": "a woman takes a selfie with her phone"
|
|
53
|
-
},
|
|
54
|
-
{
|
|
55
|
-
"id": "genai_veo3",
|
|
56
|
-
"text": "movie generated by veo3",
|
|
57
|
-
"moviePrompt": "a woman is walking through a busy Tokyo street at night, she is wearing dark sunglasses",
|
|
58
|
-
"movieParams": {
|
|
59
|
-
"model": "veo-3.0-generate-001"
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
{
|
|
63
|
-
"id": "genai_veo3_1",
|
|
64
|
-
"text": "movie generated by veo3_1",
|
|
65
|
-
"moviePrompt": "a woman is walking through a busy Tokyo street at night, she is wearing dark sunglasses",
|
|
66
|
-
"movieParams": {
|
|
67
|
-
"model": "veo-3.1-generate-preview"
|
|
68
|
-
}
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
"id": "genai_veo3_image",
|
|
72
|
-
"text": "movie generated by veo3",
|
|
73
|
-
"duration": 5,
|
|
74
|
-
"imagePrompt": "a woman is walking through a busy Tokyo street at night, she is wearing dark sunglasses",
|
|
75
|
-
"imageParams": {
|
|
76
|
-
"model": "gemini-2.5-flash-image"
|
|
77
|
-
},
|
|
78
|
-
"moviePrompt": "a woman is walking through a busy Tokyo street at night, she is wearing dark sunglasses",
|
|
79
|
-
"movieParams": {
|
|
80
|
-
"model": "veo-3.0-generate-001"
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
]
|
|
84
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$mulmocast": { "version": "1.1" },
|
|
3
|
-
"imageParams": {
|
|
4
|
-
"provider": "google",
|
|
5
|
-
"style": "<style>Photo realistic.</style>"
|
|
6
|
-
},
|
|
7
|
-
"canvasSize": {
|
|
8
|
-
"width": 720,
|
|
9
|
-
"height": 1280
|
|
10
|
-
},
|
|
11
|
-
"lang": "en",
|
|
12
|
-
"movieParams": {
|
|
13
|
-
"provider": "google",
|
|
14
|
-
"model": "veo-3.1-generate-preview"
|
|
15
|
-
},
|
|
16
|
-
"beats": [
|
|
17
|
-
{
|
|
18
|
-
"moviePrompt": "A butterfly flying in slow motion",
|
|
19
|
-
"duration": 20
|
|
20
|
-
}
|
|
21
|
-
]
|
|
22
|
-
}
|
|
File without changes
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$mulmocast": {
|
|
3
|
-
"version": "1.1"
|
|
4
|
-
},
|
|
5
|
-
"lang": "en",
|
|
6
|
-
"movieParams": {
|
|
7
|
-
"provider": "google"
|
|
8
|
-
},
|
|
9
|
-
"lipSyncParams": {
|
|
10
|
-
"provider": "replicate",
|
|
11
|
-
"model": "bytedance/latentsync"
|
|
12
|
-
},
|
|
13
|
-
"canvasSize": {
|
|
14
|
-
"width": 1280,
|
|
15
|
-
"height": 720
|
|
16
|
-
},
|
|
17
|
-
"beats": [
|
|
18
|
-
{
|
|
19
|
-
"text": "Hello, I'm macoro. Hello, I'm macoro. Hello, I'm macoro.",
|
|
20
|
-
"moviePrompt": "macoro is speaking",
|
|
21
|
-
"enableLipSync": true
|
|
22
|
-
}
|
|
23
|
-
]
|
|
24
|
-
}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$mulmocast": {
|
|
3
|
-
"version": "1.1"
|
|
4
|
-
},
|
|
5
|
-
"lang": "en",
|
|
6
|
-
"movieParams": {
|
|
7
|
-
"provider": "google"
|
|
8
|
-
},
|
|
9
|
-
"canvasSize": {
|
|
10
|
-
"width": 720,
|
|
11
|
-
"height": 1280
|
|
12
|
-
},
|
|
13
|
-
"imageParams": {
|
|
14
|
-
"provider": "openai",
|
|
15
|
-
"model": "dall-e-3",
|
|
16
|
-
"style": "Photo realistic, cinematic style.",
|
|
17
|
-
"images": {
|
|
18
|
-
"optimus": {
|
|
19
|
-
"type": "image",
|
|
20
|
-
"source": {
|
|
21
|
-
"kind": "url",
|
|
22
|
-
"url": "https://raw.githubusercontent.com/receptron/mulmocast-media/refs/heads/main/characters/optimus.png"
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
},
|
|
27
|
-
"beats": [
|
|
28
|
-
{
|
|
29
|
-
"text": "Image with both image and movie prompt",
|
|
30
|
-
"imagePrompt": "巨大なロケット「Starship」が発射台から打ち上がろうとしている様子。空には星と火星が浮かんでいる。",
|
|
31
|
-
"moviePrompt": "Startship lifts off.",
|
|
32
|
-
"duration": 5
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
"text": "Image with only movie prompt",
|
|
36
|
-
"moviePrompt": "Startship lifts off.",
|
|
37
|
-
"duration": 5
|
|
38
|
-
}
|
|
39
|
-
]
|
|
40
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$mulmocast": {
|
|
3
|
-
"version": "1.1",
|
|
4
|
-
"credit": "closing"
|
|
5
|
-
},
|
|
6
|
-
"canvasSize": {
|
|
7
|
-
"width": 1536,
|
|
8
|
-
"height": 1024
|
|
9
|
-
},
|
|
10
|
-
"speechParams": {
|
|
11
|
-
"speakers": {
|
|
12
|
-
"Presenter": {
|
|
13
|
-
"displayName": {
|
|
14
|
-
"en": "Presenter"
|
|
15
|
-
},
|
|
16
|
-
"voiceId": "shimmer"
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
"imageParams": {
|
|
21
|
-
"provider": "openai",
|
|
22
|
-
"style": "<style>Vibrant 3D animation style inspired by K-pop aesthetics, with glossy, stylized characters. The overall visual style combines elements of modern animation, game cinematics, and fashion-forward character design, with sleek outlines, glowing effects, and a polished, cinematic finish.</style>",
|
|
23
|
-
"images": {
|
|
24
|
-
"min": {
|
|
25
|
-
"type": "image",
|
|
26
|
-
"source": {
|
|
27
|
-
"kind": "url",
|
|
28
|
-
"url": "https://raw.githubusercontent.com/receptron/mulmocast-media/refs/heads/main/characters/min_anime.png"
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
},
|
|
33
|
-
"movieParams": {
|
|
34
|
-
"provider": "replicate"
|
|
35
|
-
},
|
|
36
|
-
"soundEffectParams": {
|
|
37
|
-
"provider": "replicate"
|
|
38
|
-
},
|
|
39
|
-
"captionParams": {
|
|
40
|
-
"lang": "en",
|
|
41
|
-
"styles": ["font-size: 64px", "width: 90%", "padding-left: 5%", "padding-right: 5%"]
|
|
42
|
-
},
|
|
43
|
-
"audioParams": {
|
|
44
|
-
"padding": 0,
|
|
45
|
-
"introPadding": 0,
|
|
46
|
-
"closingPadding": 0,
|
|
47
|
-
"outroPadding": 0,
|
|
48
|
-
"bgm": {
|
|
49
|
-
"kind": "url",
|
|
50
|
-
"url": "https://raw.githubusercontent.com/receptron/mulmocast-media/refs/heads/main/music/finetuning_with_you.mp3"
|
|
51
|
-
},
|
|
52
|
-
"bgmVolume": 1,
|
|
53
|
-
"audioVolume": 0,
|
|
54
|
-
"suppressSpeech": true
|
|
55
|
-
},
|
|
56
|
-
"title": "Music Video",
|
|
57
|
-
"lang": "en",
|
|
58
|
-
"beats": [
|
|
59
|
-
{
|
|
60
|
-
"text": "Finetuning with you",
|
|
61
|
-
"moviePrompt": "The singer preparing to sing a song.",
|
|
62
|
-
"playGenMovieToEnd": true
|
|
63
|
-
}
|
|
64
|
-
]
|
|
65
|
-
}
|