mulmocast 0.0.1 → 0.0.2

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.
Files changed (79) hide show
  1. package/README.md +108 -12
  2. package/assets/html/chart.html +47 -0
  3. package/assets/html/mermaid.html +63 -0
  4. package/assets/templates/business.json +60 -6
  5. package/assets/templates/children_book.json +1 -3
  6. package/assets/templates/coding.json +103 -0
  7. package/lib/actions/audio.d.ts +1 -1
  8. package/lib/actions/audio.js +52 -81
  9. package/lib/actions/images.d.ts +1 -1
  10. package/lib/actions/images.js +48 -80
  11. package/lib/actions/movie.d.ts +1 -1
  12. package/lib/actions/movie.js +76 -76
  13. package/lib/actions/translate.d.ts +1 -1
  14. package/lib/actions/translate.js +16 -52
  15. package/lib/agents/add_bgm_agent.d.ts +1 -1
  16. package/lib/agents/add_bgm_agent.js +10 -14
  17. package/lib/agents/combine_audio_files_agent.d.ts +1 -1
  18. package/lib/agents/combine_audio_files_agent.js +40 -30
  19. package/lib/agents/image_google_agent.d.ts +1 -1
  20. package/lib/agents/image_google_agent.js +8 -11
  21. package/lib/agents/image_openai_agent.js +7 -14
  22. package/lib/agents/index.d.ts +8 -8
  23. package/lib/agents/index.js +13 -30
  24. package/lib/agents/mulmo_prompts_agent.d.ts +1 -1
  25. package/lib/agents/mulmo_prompts_agent.js +7 -11
  26. package/lib/agents/prompts_data.js +1 -4
  27. package/lib/agents/tts_nijivoice_agent.d.ts +1 -1
  28. package/lib/agents/tts_nijivoice_agent.js +8 -12
  29. package/lib/agents/tts_openai_agent.js +9 -16
  30. package/lib/agents/validate_mulmo_script_agent.d.ts +1 -1
  31. package/lib/agents/validate_mulmo_script_agent.js +6 -10
  32. package/lib/cli/args.d.ts +2 -1
  33. package/lib/cli/args.js +16 -14
  34. package/lib/cli/cli.js +64 -49
  35. package/lib/cli/common.js +1 -5
  36. package/lib/cli/tool-args.d.ts +2 -1
  37. package/lib/cli/tool-args.js +19 -18
  38. package/lib/cli/tool-cli.js +32 -51
  39. package/lib/methods/index.d.ts +3 -3
  40. package/lib/methods/index.js +3 -19
  41. package/lib/methods/mulmo_script.d.ts +10 -5
  42. package/lib/methods/mulmo_script.js +17 -11
  43. package/lib/methods/mulmo_script_template.d.ts +1 -1
  44. package/lib/methods/mulmo_script_template.js +4 -10
  45. package/lib/methods/mulmo_studio_context.d.ts +1 -1
  46. package/lib/methods/mulmo_studio_context.js +3 -9
  47. package/lib/tools/create_mulmo_script_from_url.d.ts +3 -0
  48. package/lib/tools/create_mulmo_script_from_url.js +152 -0
  49. package/lib/tools/create_mulmo_script_interactively.d.ts +3 -0
  50. package/lib/tools/create_mulmo_script_interactively.js +217 -0
  51. package/lib/tools/dump_prompt.js +5 -8
  52. package/lib/tools/prompt.js +9 -11
  53. package/lib/tools/seed_from_url2.d.ts +3 -0
  54. package/lib/tools/seed_from_url2.js +154 -0
  55. package/lib/types/index.d.ts +1 -1
  56. package/lib/types/index.js +1 -17
  57. package/lib/types/schema.d.ts +433 -71
  58. package/lib/types/schema.js +126 -111
  59. package/lib/types/type.d.ts +7 -3
  60. package/lib/types/type.js +1 -2
  61. package/lib/utils/const.d.ts +2 -1
  62. package/lib/utils/const.js +4 -6
  63. package/lib/utils/file.d.ts +19 -4
  64. package/lib/utils/file.js +78 -71
  65. package/lib/utils/filters.d.ts +1 -0
  66. package/lib/utils/filters.js +47 -26
  67. package/lib/utils/image_preprocess.d.ts +14 -0
  68. package/lib/utils/image_preprocess.js +52 -0
  69. package/lib/utils/inquirer.d.ts +2 -0
  70. package/lib/utils/inquirer.js +33 -0
  71. package/lib/utils/markdown.d.ts +3 -1
  72. package/lib/utils/markdown.js +17 -19
  73. package/lib/utils/plugins.d.ts +5 -0
  74. package/lib/utils/plugins.js +11 -0
  75. package/lib/utils/preprocess.d.ts +24 -7
  76. package/lib/utils/preprocess.js +8 -14
  77. package/lib/utils/string.js +4 -10
  78. package/lib/utils/text_hash.js +2 -39
  79. package/package.json +12 -6
@@ -1,53 +1,15 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.audio = void 0;
40
- require("dotenv/config");
41
- const graphai_1 = require("graphai");
42
- const agents = __importStar(require("@graphai/vanilla"));
43
- const tts_nijivoice_agent_1 = __importDefault(require("../agents/tts_nijivoice_agent"));
44
- const add_bgm_agent_1 = __importDefault(require("../agents/add_bgm_agent"));
45
- const combine_audio_files_agent_1 = __importDefault(require("../agents/combine_audio_files_agent"));
46
- const tts_openai_agent_1 = __importDefault(require("../agents/tts_openai_agent"));
47
- const vanilla_node_agents_1 = require("@graphai/vanilla_node_agents");
48
- const methods_1 = require("../methods");
49
- const filters_1 = require("../utils/filters");
50
- const file_1 = require("../utils/file");
1
+ import "dotenv/config";
2
+ import { GraphAI } from "graphai";
3
+ import * as agents from "@graphai/vanilla";
4
+ import ttsNijivoiceAgent from "../agents/tts_nijivoice_agent.js";
5
+ import addBGMAgent from "../agents/add_bgm_agent.js";
6
+ import combineAudioFilesAgent from "../agents/combine_audio_files_agent.js";
7
+ import ttsOpenaiAgent from "../agents/tts_openai_agent.js";
8
+ import { fileWriteAgent } from "@graphai/vanilla_node_agents";
9
+ import { MulmoScriptMethods } from "../methods/index.js";
10
+ import { fileCacheAgentFilter } from "../utils/filters.js";
11
+ import { getAudioArtifactFilePath, getAudioSegmentDirPath, getAudioCombinedFilePath, getOutputStudioFilePath, defaultBGMPath, mkdir, writingMessage, } from "../utils/file.js";
12
+ const { default: __, ...vanillaAgents } = agents;
51
13
  // const rion_takanashi_voice = "b9277ce3-ba1c-4f6f-9a65-c05ca102ded0"; // たかなし りおん
52
14
  // const ben_carter_voice = "bc06c63f-fef6-43b6-92f7-67f919bd5dae"; // ベン・カーター
53
15
  const graph_tts = {
@@ -57,7 +19,7 @@ const graph_tts = {
57
19
  const { beat, script, speakers } = namedInputs;
58
20
  return {
59
21
  voiceId: speakers[beat.speaker].voiceId,
60
- speechOptions: methods_1.MulmoScriptMethods.getSpeechOptions(script, beat),
22
+ speechOptions: MulmoScriptMethods.getSpeechOptions(script, beat),
61
23
  };
62
24
  },
63
25
  inputs: {
@@ -82,7 +44,8 @@ const graph_tts = {
82
44
  agent: ":ttsAgent",
83
45
  inputs: {
84
46
  text: ":beat.text",
85
- file: "${:scratchpadDirPath}/${:beat.audioFile}.mp3", // TODO
47
+ file: "${:audioSegmentDirPath}/${:beat.audioFile}.mp3", // TODO
48
+ force: ":context.force",
86
49
  },
87
50
  params: {
88
51
  voice: ":preprocessor.voiceId",
@@ -97,13 +60,20 @@ const graph_data = {
97
60
  concurrency: 8,
98
61
  nodes: {
99
62
  context: {},
100
- outputBGMFilePath: {},
101
- outputAudioFilePath: {},
63
+ audioArtifactFilePath: {},
64
+ audioCombinedFilePath: {},
102
65
  outputStudioFilePath: {},
103
- scratchpadDirPath: {},
66
+ audioDirPath: {},
67
+ audioSegmentDirPath: {},
104
68
  map: {
105
69
  agent: "mapAgent",
106
- inputs: { rows: ":context.studio.beats", script: ":context.studio.script", scratchpadDirPath: ":scratchpadDirPath" },
70
+ inputs: {
71
+ rows: ":context.studio.beats",
72
+ script: ":context.studio.script",
73
+ audioDirPath: ":audioDirPath",
74
+ audioSegmentDirPath: ":audioSegmentDirPath",
75
+ context: ":context",
76
+ },
107
77
  params: {
108
78
  rowKey: "beat",
109
79
  },
@@ -114,8 +84,8 @@ const graph_data = {
114
84
  inputs: {
115
85
  map: ":map",
116
86
  context: ":context",
117
- combinedFileName: ":outputAudioFilePath",
118
- scratchpadDirPath: ":scratchpadDirPath",
87
+ combinedFileName: ":audioCombinedFilePath",
88
+ audioDirPath: ":audioDirPath",
119
89
  },
120
90
  isResult: true,
121
91
  },
@@ -129,12 +99,12 @@ const graph_data = {
129
99
  addBGM: {
130
100
  agent: "addBGMAgent",
131
101
  params: {
132
- musicFile: process.env.PATH_BGM ?? file_1.defaultBGMPath,
102
+ musicFile: process.env.PATH_BGM ?? defaultBGMPath,
133
103
  },
134
104
  inputs: {
135
105
  wait: ":combineFiles",
136
- voiceFile: ":outputAudioFilePath",
137
- outputFile: ":outputBGMFilePath",
106
+ voiceFile: ":audioCombinedFilePath",
107
+ outputFile: ":audioArtifactFilePath",
138
108
  script: ":context.studio.script",
139
109
  },
140
110
  isResult: true,
@@ -154,33 +124,34 @@ const graph_data = {
154
124
  const agentFilters = [
155
125
  {
156
126
  name: "fileCacheAgentFilter",
157
- agent: filters_1.fileCacheAgentFilter,
127
+ agent: fileCacheAgentFilter,
158
128
  nodeIds: ["tts"],
159
129
  },
160
130
  ];
161
- const audio = async (context, concurrency) => {
131
+ export const audio = async (context, concurrency) => {
162
132
  const { studio, fileDirs } = context;
163
- const { outDirPath, scratchpadDirPath } = fileDirs;
164
- const outputBGMFilePath = (0, file_1.getOutputBGMFilePath)(outDirPath, studio.filename);
165
- const outputAudioFilePath = (0, file_1.getOutputAudioFilePath)(outDirPath, studio.filename);
166
- const outputStudioFilePath = (0, file_1.getOutputStudioFilePath)(outDirPath, studio.filename);
167
- (0, file_1.mkdir)(outDirPath);
168
- (0, file_1.mkdir)(scratchpadDirPath);
133
+ const { outDirPath, audioDirPath } = fileDirs;
134
+ const audioArtifactFilePath = getAudioArtifactFilePath(outDirPath, studio.filename);
135
+ const audioSegmentDirPath = getAudioSegmentDirPath(audioDirPath, studio.filename);
136
+ const audioCombinedFilePath = getAudioCombinedFilePath(audioDirPath, studio.filename);
137
+ const outputStudioFilePath = getOutputStudioFilePath(outDirPath, studio.filename);
138
+ mkdir(outDirPath);
139
+ mkdir(audioSegmentDirPath);
169
140
  graph_data.concurrency = concurrency;
170
- const graph = new graphai_1.GraphAI(graph_data, {
171
- ...agents,
172
- fileWriteAgent: vanilla_node_agents_1.fileWriteAgent,
173
- ttsOpenaiAgent: tts_openai_agent_1.default,
174
- ttsNijivoiceAgent: tts_nijivoice_agent_1.default,
175
- addBGMAgent: add_bgm_agent_1.default,
176
- combineAudioFilesAgent: combine_audio_files_agent_1.default,
141
+ const graph = new GraphAI(graph_data, {
142
+ ...vanillaAgents,
143
+ fileWriteAgent,
144
+ ttsOpenaiAgent,
145
+ ttsNijivoiceAgent,
146
+ addBGMAgent,
147
+ combineAudioFilesAgent,
177
148
  }, { agentFilters });
178
149
  graph.injectValue("context", context);
179
- graph.injectValue("outputBGMFilePath", outputBGMFilePath);
180
- graph.injectValue("outputAudioFilePath", outputAudioFilePath);
150
+ graph.injectValue("audioArtifactFilePath", audioArtifactFilePath);
151
+ graph.injectValue("audioCombinedFilePath", audioCombinedFilePath);
181
152
  graph.injectValue("outputStudioFilePath", outputStudioFilePath);
182
- graph.injectValue("scratchpadDirPath", scratchpadDirPath);
153
+ graph.injectValue("audioSegmentDirPath", audioSegmentDirPath);
154
+ graph.injectValue("audioDirPath", audioDirPath);
183
155
  await graph.run();
184
- (0, file_1.writingMessage)(outputAudioFilePath);
156
+ writingMessage(audioCombinedFilePath);
185
157
  };
186
- exports.audio = audio;
@@ -1,2 +1,2 @@
1
- import { MulmoStudioContext } from "../types";
1
+ import { MulmoStudioContext } from "../types/index.js";
2
2
  export declare const images: (context: MulmoStudioContext) => Promise<void>;
@@ -1,81 +1,46 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __importStar = (this && this.__importStar) || (function () {
19
- var ownKeys = function(o) {
20
- ownKeys = Object.getOwnPropertyNames || function (o) {
21
- var ar = [];
22
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
- return ar;
24
- };
25
- return ownKeys(o);
26
- };
27
- return function (mod) {
28
- if (mod && mod.__esModule) return mod;
29
- var result = {};
30
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
- __setModuleDefault(result, mod);
32
- return result;
33
- };
34
- })();
35
- var __importDefault = (this && this.__importDefault) || function (mod) {
36
- return (mod && mod.__esModule) ? mod : { "default": mod };
37
- };
38
- Object.defineProperty(exports, "__esModule", { value: true });
39
- exports.images = void 0;
40
- const dotenv_1 = __importDefault(require("dotenv"));
41
- const graphai_1 = require("graphai");
42
- const agents = __importStar(require("@graphai/vanilla"));
43
- const vanilla_node_agents_1 = require("@graphai/vanilla_node_agents");
44
- const file_1 = require("../utils/file");
45
- const filters_1 = require("../utils/filters");
46
- const markdown_1 = require("../utils/markdown");
47
- const image_google_agent_1 = __importDefault(require("../agents/image_google_agent"));
48
- const image_openai_agent_1 = __importDefault(require("../agents/image_openai_agent"));
49
- const methods_1 = require("../methods");
50
- dotenv_1.default.config();
1
+ import dotenv from "dotenv";
2
+ import { GraphAI, GraphAILogger } from "graphai";
3
+ import * as agents from "@graphai/vanilla";
4
+ import { fileWriteAgent } from "@graphai/vanilla_node_agents";
5
+ import { getOutputStudioFilePath, mkdir } from "../utils/file.js";
6
+ import { fileCacheAgentFilter } from "../utils/filters.js";
7
+ import imageGoogleAgent from "../agents/image_google_agent.js";
8
+ import imageOpenaiAgent from "../agents/image_openai_agent.js";
9
+ import { MulmoScriptMethods } from "../methods/index.js";
10
+ import { processChart, processMarkdown, processTextSlide, processImage, processMermaid } from "../utils/image_preprocess.js";
11
+ const { default: __, ...vanillaAgents } = agents;
12
+ dotenv.config();
51
13
  // const openai = new OpenAI();
52
- const google_auth_library_1 = require("google-auth-library");
53
- const preprocess_agent = async (namedInputs) => {
54
- const { context, beat, index, suffix, imageDirPath } = namedInputs;
55
- const imageParams = { ...context.studio.script.imageParams, ...beat.imageParams };
14
+ import { GoogleAuth } from "google-auth-library";
15
+ const imagePreprocessAgent = async (namedInputs) => {
16
+ const { context, beat, index, suffix, imageDirPath, imageAgentInfo } = namedInputs;
17
+ const imageParams = { ...imageAgentInfo.imageParams, ...beat.imageParams };
56
18
  const prompt = (beat.imagePrompt || beat.text) + "\n" + (imageParams.style || "");
57
19
  const imagePath = `${imageDirPath}/${context.studio.filename}/${index}${suffix}.png`;
58
- const aspectRatio = methods_1.MulmoScriptMethods.getAspectRatio(context.studio.script);
20
+ const aspectRatio = MulmoScriptMethods.getAspectRatio(context.studio.script);
21
+ const textSlideStyle = MulmoScriptMethods.getTextSlideStyle(context.studio.script, beat);
59
22
  if (beat.image) {
23
+ const canvasSize = MulmoScriptMethods.getCanvasSize(context.studio.script);
24
+ const processorParams = { beat, context, imagePath, textSlideStyle, canvasSize };
60
25
  if (beat.image.type === "textSlide") {
61
- const slide = beat.image.slide;
62
- const markdown = `# ${slide.title}` + slide.bullets.map((text) => `- ${text}`).join("\n");
63
- await (0, markdown_1.convertMarkdownToImage)(markdown, methods_1.MulmoScriptMethods.getTextSlideStyle(context.studio.script, beat), imagePath);
26
+ await processTextSlide(processorParams);
64
27
  }
65
28
  else if (beat.image.type === "markdown") {
66
- const markdown = Array.isArray(beat.image.markdown) ? beat.image.markdown.join("\n") : beat.image.markdown;
67
- await (0, markdown_1.convertMarkdownToImage)(markdown, methods_1.MulmoScriptMethods.getTextSlideStyle(context.studio.script, beat), imagePath);
29
+ await processMarkdown(processorParams);
68
30
  }
69
31
  else if (beat.image.type === "image") {
70
- if (beat.image.source.kind === "url") {
71
- // undefined prompt indicates "no need to generate image"
72
- return { path: beat.image.source.url, prompt: undefined, imageParams, aspectRatio };
73
- }
74
- else if (beat.image.source.kind === "path") {
75
- const path = methods_1.MulmoStudioContextMethods.resolveAssetPath(context, beat.image.source.path);
32
+ const path = processImage(processorParams);
33
+ if (path) {
34
+ // undefined prompt indicates that image generation is not needed
76
35
  return { path, prompt: undefined, imageParams, aspectRatio };
77
36
  }
78
37
  }
38
+ else if (beat.image.type === "chart") {
39
+ await processChart(processorParams);
40
+ }
41
+ else if (beat.image.type === "mermaid") {
42
+ await processMermaid(processorParams);
43
+ }
79
44
  }
80
45
  return { path: imagePath, prompt, imageParams, aspectRatio };
81
46
  };
@@ -85,11 +50,11 @@ const graph_data = {
85
50
  nodes: {
86
51
  context: {},
87
52
  imageDirPath: {},
88
- text2imageAgent: {},
53
+ imageAgentInfo: {},
89
54
  outputStudioFilePath: {},
90
55
  map: {
91
56
  agent: "mapAgent",
92
- inputs: { rows: ":context.studio.beats", context: ":context", text2imageAgent: ":text2imageAgent", imageDirPath: ":imageDirPath" },
57
+ inputs: { rows: ":context.studio.beats", context: ":context", imageAgentInfo: ":imageAgentInfo", imageDirPath: ":imageDirPath" },
93
58
  isResult: true,
94
59
  params: {
95
60
  rowKey: "beat",
@@ -98,18 +63,19 @@ const graph_data = {
98
63
  graph: {
99
64
  nodes: {
100
65
  preprocessor: {
101
- agent: preprocess_agent,
66
+ agent: imagePreprocessAgent,
102
67
  inputs: {
103
68
  context: ":context",
104
69
  beat: ":beat",
105
70
  index: ":__mapIndex",
106
71
  suffix: "p",
107
72
  imageDirPath: ":imageDirPath",
73
+ imageAgentInfo: ":imageAgentInfo",
108
74
  },
109
75
  },
110
76
  imageGenerator: {
111
77
  if: ":preprocessor.prompt",
112
- agent: ":text2imageAgent",
78
+ agent: ":imageAgentInfo.agent",
113
79
  params: {
114
80
  model: ":preprocessor.imageParams.model",
115
81
  size: ":preprocessor.imageParams.size",
@@ -120,6 +86,7 @@ const graph_data = {
120
86
  prompt: ":preprocessor.prompt",
121
87
  file: ":preprocessor.path", // only for fileCacheAgentFilter
122
88
  text: ":preprocessor.prompt", // only for fileCacheAgentFilter
89
+ force: ":context.force",
123
90
  },
124
91
  defaultValue: {},
125
92
  },
@@ -164,30 +131,31 @@ const graph_data = {
164
131
  },
165
132
  };
166
133
  const googleAuth = async () => {
167
- const auth = new google_auth_library_1.GoogleAuth({
134
+ const auth = new GoogleAuth({
168
135
  scopes: ["https://www.googleapis.com/auth/cloud-platform"],
169
136
  });
170
137
  const client = await auth.getClient();
171
138
  const accessToken = await client.getAccessToken();
172
139
  return accessToken.token;
173
140
  };
174
- const images = async (context) => {
141
+ export const images = async (context) => {
175
142
  const { studio, fileDirs } = context;
176
143
  const { outDirPath, imageDirPath } = fileDirs;
177
- (0, file_1.mkdir)(`${imageDirPath}/${studio.filename}`);
144
+ mkdir(`${imageDirPath}/${studio.filename}`);
178
145
  const agentFilters = [
179
146
  {
180
147
  name: "fileCacheAgentFilter",
181
- agent: filters_1.fileCacheAgentFilter,
148
+ agent: fileCacheAgentFilter,
182
149
  nodeIds: ["imageGenerator"],
183
150
  },
184
151
  ];
185
152
  const options = {
186
153
  agentFilters,
187
154
  };
155
+ const imageAgentInfo = MulmoScriptMethods.getImageAgentInfo(studio.script);
188
156
  // We need to get google's auth token only if the google is the text2image provider.
189
- if (methods_1.MulmoScriptMethods.getImageProvider(studio.script) === "google") {
190
- console.log("google was specified as text2image engine");
157
+ if (imageAgentInfo.provider === "google") {
158
+ GraphAILogger.log("google was specified as text2image engine");
191
159
  const token = await googleAuth();
192
160
  options.config = {
193
161
  imageGoogleAgent: {
@@ -196,16 +164,16 @@ const images = async (context) => {
196
164
  },
197
165
  };
198
166
  }
167
+ GraphAILogger.info(`text2image: provider=${imageAgentInfo.provider} model=${imageAgentInfo.imageParams.model}`);
199
168
  const injections = {
200
169
  context,
201
- text2imageAgent: methods_1.MulmoScriptMethods.getText2imageAgent(studio.script),
202
- outputStudioFilePath: (0, file_1.getOutputStudioFilePath)(outDirPath, studio.filename),
170
+ imageAgentInfo,
171
+ outputStudioFilePath: getOutputStudioFilePath(outDirPath, studio.filename),
203
172
  imageDirPath,
204
173
  };
205
- const graph = new graphai_1.GraphAI(graph_data, { ...agents, imageGoogleAgent: image_google_agent_1.default, imageOpenaiAgent: image_openai_agent_1.default, fileWriteAgent: vanilla_node_agents_1.fileWriteAgent }, options);
174
+ const graph = new GraphAI(graph_data, { ...vanillaAgents, imageGoogleAgent, imageOpenaiAgent, fileWriteAgent }, options);
206
175
  Object.keys(injections).forEach((key) => {
207
176
  graph.injectValue(key, injections[key]);
208
177
  });
209
178
  await graph.run();
210
179
  };
211
- exports.images = images;
@@ -1,2 +1,2 @@
1
- import { MulmoStudioContext } from "../types";
1
+ import { MulmoStudioContext } from "../types/index.js";
2
2
  export declare const movie: (context: MulmoStudioContext) => Promise<void>;
@@ -1,81 +1,81 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.movie = void 0;
7
- const fluent_ffmpeg_1 = __importDefault(require("fluent-ffmpeg"));
8
- const methods_1 = require("../methods");
9
- const file_1 = require("../utils/file");
10
- const createVideo = (audioPath, outputVideoPath, studio) => {
11
- const start = performance.now();
12
- let command = (0, fluent_ffmpeg_1.default)();
13
- if (studio.beats.some((beat) => !beat.imageFile)) {
14
- console.error("beat.imageFile is not set. Please run `yarn run images ${file}` ");
15
- return;
16
- }
17
- // Add each image input
18
- studio.beats.forEach((beat) => {
19
- command = command.input(beat.imageFile); // HACK
20
- });
21
- const imageCount = studio.beats.length;
22
- const canvasInfo = methods_1.MulmoScriptMethods.getCanvasSize(studio.script);
23
- const filterComplexParts = [];
24
- studio.beats.forEach((beat, index) => {
25
- // Resize background image to match canvas dimensions
26
- const duration = beat.duration + (index === 0 ? methods_1.MulmoScriptMethods.getPadding(studio.script) / 1000 : 0);
27
- const parts = `[${index}:v]loop=loop=-1:size=1:start=0,` +
28
- `trim=duration=${duration},` +
29
- `fps=30,` +
30
- `setpts=PTS-STARTPTS,` +
31
- `scale=${canvasInfo.width}:${canvasInfo.height},` +
32
- `setsar=1,format=yuv420p` +
33
- `[v${index}]`;
34
- // console.log(parts);
35
- filterComplexParts.push(parts);
1
+ import ffmpeg from "fluent-ffmpeg";
2
+ import { GraphAILogger } from "graphai";
3
+ import { MulmoScriptMethods } from "../methods/index.js";
4
+ import { getAudioArtifactFilePath, getOutputVideoFilePath, writingMessage } from "../utils/file.js";
5
+ const createVideo = (audioArtifactFilePath, outputVideoPath, studio) => {
6
+ return new Promise((resolve, reject) => {
7
+ const start = performance.now();
8
+ let command = ffmpeg();
9
+ if (studio.beats.some((beat) => !beat.imageFile)) {
10
+ GraphAILogger.info("beat.imageFile is not set. Please run `yarn run images ${file}` ");
11
+ return;
12
+ }
13
+ // Add each image input
14
+ studio.beats.forEach((beat) => {
15
+ command = command.input(beat.imageFile); // HACK
16
+ });
17
+ const imageCount = studio.beats.length;
18
+ const canvasInfo = MulmoScriptMethods.getCanvasSize(studio.script);
19
+ const filterComplexParts = [];
20
+ studio.beats.forEach((beat, index) => {
21
+ // Resize background image to match canvas dimensions
22
+ const duration = beat.duration + (index === 0 ? MulmoScriptMethods.getPadding(studio.script) / 1000 : 0);
23
+ const parts = `[${index}:v]loop=loop=-1:size=1:start=0,` +
24
+ `trim=duration=${duration},` +
25
+ `fps=30,` +
26
+ `setpts=PTS-STARTPTS,` +
27
+ `scale=${canvasInfo.width}:${canvasInfo.height},` +
28
+ `setsar=1,format=yuv420p` +
29
+ `[v${index}]`;
30
+ // console.log(parts);
31
+ filterComplexParts.push(parts);
32
+ });
33
+ // Concatenate the trimmed images
34
+ const concatInput = studio.beats.map((_, index) => `[v${index}]`).join("");
35
+ filterComplexParts.push(`${concatInput}concat=n=${imageCount}:v=1:a=0[v]`);
36
+ // Apply the filter complex for concatenation and map audio input
37
+ command
38
+ .complexFilter(filterComplexParts)
39
+ .input(audioArtifactFilePath) // Add audio input
40
+ .outputOptions([
41
+ "-preset veryfast", // Faster encoding
42
+ "-map [v]", // Map the video stream
43
+ `-map ${imageCount /* + captionCount*/}:a`, // Map the audio stream (audio is the next input after all images)
44
+ "-c:v h264_videotoolbox", // Set video codec
45
+ "-threads 8",
46
+ "-filter_threads 8",
47
+ "-b:v 5M", // bitrate (only for videotoolbox)
48
+ "-bufsize",
49
+ "10M", // Add buffer size for better quality
50
+ "-maxrate",
51
+ "7M", // Maximum bitrate
52
+ "-r 30", // Set frame rate
53
+ "-pix_fmt yuv420p", // Set pixel format for better compatibility
54
+ ])
55
+ .on("start", (__cmdLine) => {
56
+ GraphAILogger.log("Started FFmpeg ..."); // with command:', cmdLine);
57
+ })
58
+ .on("error", (err, stdout, stderr) => {
59
+ GraphAILogger.error("Error occurred:", err);
60
+ GraphAILogger.error("FFmpeg stdout:", stdout);
61
+ GraphAILogger.error("FFmpeg stderr:", stderr);
62
+ GraphAILogger.info("Video creation failed. An unexpected error occurred.");
63
+ reject();
64
+ })
65
+ .on("end", () => {
66
+ const end = performance.now();
67
+ GraphAILogger.info(`Video created successfully! ${Math.round(end - start) / 1000} sec`);
68
+ resolve(0);
69
+ })
70
+ .output(outputVideoPath)
71
+ .run();
36
72
  });
37
- // Concatenate the trimmed images
38
- const concatInput = studio.beats.map((_, index) => `[v${index}]`).join("");
39
- filterComplexParts.push(`${concatInput}concat=n=${imageCount}:v=1:a=0[v]`);
40
- // Apply the filter complex for concatenation and map audio input
41
- command
42
- .complexFilter(filterComplexParts)
43
- .input(audioPath) // Add audio input
44
- .outputOptions([
45
- "-preset veryfast", // Faster encoding
46
- "-map [v]", // Map the video stream
47
- `-map ${imageCount /* + captionCount*/}:a`, // Map the audio stream (audio is the next input after all images)
48
- "-c:v h264_videotoolbox", // Set video codec
49
- "-threads 8",
50
- "-filter_threads 8",
51
- "-b:v 5M", // bitrate (only for videotoolbox)
52
- "-bufsize",
53
- "10M", // Add buffer size for better quality
54
- "-maxrate",
55
- "7M", // Maximum bitrate
56
- "-r 30", // Set frame rate
57
- "-pix_fmt yuv420p", // Set pixel format for better compatibility
58
- ])
59
- .on("start", (__cmdLine) => {
60
- console.log("Started FFmpeg ..."); // with command:', cmdLine);
61
- })
62
- .on("error", (err, stdout, stderr) => {
63
- console.error("Error occurred:", err);
64
- console.error("FFmpeg stdout:", stdout);
65
- console.error("FFmpeg stderr:", stderr);
66
- })
67
- .on("end", () => {
68
- const end = performance.now();
69
- console.log(`Video created successfully! ${Math.round(end - start) / 1000} sec`);
70
- })
71
- .output(outputVideoPath)
72
- .run();
73
73
  };
74
- const movie = async (context) => {
74
+ export const movie = async (context) => {
75
75
  const { studio, fileDirs } = context;
76
76
  const { outDirPath } = fileDirs;
77
- const audioPath = (0, file_1.getOutputBGMFilePath)(outDirPath, studio.filename);
78
- const outputVideoPath = (0, file_1.getOutputVideoFilePath)(outDirPath, studio.filename);
79
- createVideo(audioPath, outputVideoPath, studio);
77
+ const audioArtifactFilePath = getAudioArtifactFilePath(outDirPath, studio.filename);
78
+ const outputVideoPath = getOutputVideoFilePath(outDirPath, studio.filename);
79
+ await createVideo(audioArtifactFilePath, outputVideoPath, studio);
80
+ writingMessage(outputVideoPath);
80
81
  };
81
- exports.movie = movie;
@@ -1,3 +1,3 @@
1
1
  import "dotenv/config";
2
- import { MulmoStudioContext } from "../types";
2
+ import { MulmoStudioContext } from "../types/index.js";
3
3
  export declare const translate: (context: MulmoStudioContext) => Promise<void>;