mulmocast 2.3.0 → 2.3.1

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.
@@ -5,7 +5,7 @@ import { fileWriteAgent } from "@graphai/vanilla_node_agents";
5
5
  import { ttsOpenaiAgent, ttsGoogleAgent, ttsGeminiAgent, ttsElevenlabsAgent, ttsKotodamaAgent, addBGMAgent, combineAudioFilesAgent, mediaMockAgent, } from "../agents/index.js";
6
6
  import { text2SpeechProviderSchema } from "../types/index.js";
7
7
  import { fileCacheAgentFilter } from "../utils/filters.js";
8
- import { getAudioArtifactFilePath, getAudioFilePath, getOutputStudioFilePath, resolveDirPath, defaultBGMPath, mkdir, writingMessage } from "../utils/file.js";
8
+ import { getAudioArtifactFilePath, getAudioFilePath, getGroupedAudioFilePath, getOutputStudioFilePath, resolveDirPath, defaultBGMPath, mkdir, writingMessage, } from "../utils/file.js";
9
9
  import { localizedText, settings2GraphAIConfig } from "../utils/utils.js";
10
10
  import { text2hash } from "../utils/utils_node.js";
11
11
  import { provider2TTSAgent } from "../types/provider2agent.js";
@@ -43,7 +43,9 @@ export const getBeatAudioPathOrUrl = (text, context, beat, lang) => {
43
43
  ].join(":");
44
44
  GraphAILogger.log(`getBeatAudioPathOrUrl [${hash_string}]`);
45
45
  const audioFileName = `${context.studio.filename}_${text2hash(hash_string)}`;
46
- const maybeAudioFile = getAudioFilePath(audioDirPath, context.studio.filename, audioFileName, lang);
46
+ const maybeAudioFile = context.fileDirs.grouped
47
+ ? getGroupedAudioFilePath(audioDirPath, audioFileName, lang)
48
+ : getAudioFilePath(audioDirPath, context.studio.filename, audioFileName, lang);
47
49
  return getAudioPathOrUrl(context, beat, maybeAudioFile);
48
50
  };
49
51
  // for lipSync
@@ -241,7 +243,7 @@ export const generateBeatAudio = async (index, context, args) => {
241
243
  const fileName = MulmoStudioContextMethods.getFileName(context);
242
244
  const audioDirPath = MulmoStudioContextMethods.getAudioDirPath(context);
243
245
  const outDirPath = MulmoStudioContextMethods.getOutDirPath(context);
244
- const audioSegmentDirPath = resolveDirPath(audioDirPath, fileName);
246
+ const audioSegmentDirPath = context.fileDirs.grouped ? audioDirPath : resolveDirPath(audioDirPath, fileName);
245
247
  mkdir(outDirPath);
246
248
  mkdir(audioSegmentDirPath);
247
249
  const config = settings2GraphAIConfig(settings);
@@ -279,8 +281,10 @@ export const audio = async (context, args) => {
279
281
  const audioDirPath = MulmoStudioContextMethods.getAudioDirPath(context);
280
282
  const outDirPath = MulmoStudioContextMethods.getOutDirPath(context);
281
283
  const audioArtifactFilePath = getAudioArtifactFilePath(context);
282
- const audioSegmentDirPath = resolveDirPath(audioDirPath, fileName);
283
- const audioCombinedFilePath = getAudioFilePath(audioDirPath, fileName, fileName, context.lang);
284
+ const audioSegmentDirPath = context.fileDirs.grouped ? audioDirPath : resolveDirPath(audioDirPath, fileName);
285
+ const audioCombinedFilePath = context.fileDirs.grouped
286
+ ? getGroupedAudioFilePath(audioDirPath, fileName, context.lang)
287
+ : getAudioFilePath(audioDirPath, fileName, fileName, context.lang);
284
288
  const outputStudioFilePath = getOutputStudioFilePath(outDirPath, fileName);
285
289
  mkdir(outDirPath);
286
290
  mkdir(audioSegmentDirPath);
@@ -61,8 +61,8 @@ export const mulmoViewerBundle = async (context, options = {}) => {
61
61
  const baseDir = context.fileDirs.baseDirPath;
62
62
  const filename = context.studio.filename;
63
63
  mkdir(outDir);
64
- // Bundle directory: output/<script_name>/
65
- const bundleDir = path.resolve(outDir, filename);
64
+ // Bundle directory: when grouped, outDir is already output/<script_name>/
65
+ const bundleDir = context.fileDirs.grouped ? outDir : path.resolve(outDir, filename);
66
66
  mkdir(bundleDir);
67
67
  const zipper = skipZip ? undefined : new ZipBuilder(path.resolve(bundleDir, zipFileName));
68
68
  // text
@@ -1,6 +1,6 @@
1
1
  import { GraphAILogger } from "graphai";
2
2
  import { MulmoPresentationStyleMethods, MulmoStudioContextMethods, MulmoBeatMethods, MulmoMediaSourceMethods } from "../methods/index.js";
3
- import { getBeatPngImagePath, getBeatMoviePaths, getAudioFilePath } from "../utils/file.js";
3
+ import { getBeatPngImagePath, getBeatMoviePaths, getAudioFilePath, getGroupedAudioFilePath } from "../utils/file.js";
4
4
  import { imagePrompt, htmlImageSystemPrompt } from "../utils/prompt.js";
5
5
  import { renderHTMLToImage } from "../utils/html_render.js";
6
6
  import { beatId } from "../utils/utils.js";
@@ -54,8 +54,10 @@ export const imagePreprocessAgent = async (namedInputs) => {
54
54
  returnValue.bgmFile = MulmoMediaSourceMethods.resolve(context.studio.script.audioParams.bgm, context);
55
55
  const folderName = MulmoStudioContextMethods.getFileName(context);
56
56
  const audioDirPath = MulmoStudioContextMethods.getAudioDirPath(context);
57
- const fileName = `${beatId(beat.id, index)}_trimmed.mp3`;
58
- returnValue.audioFile = getAudioFilePath(audioDirPath, folderName, fileName);
57
+ const trimmedName = `${beatId(beat.id, index)}_trimmed`;
58
+ returnValue.audioFile = context.fileDirs.grouped
59
+ ? getGroupedAudioFilePath(audioDirPath, trimmedName)
60
+ : getAudioFilePath(audioDirPath, folderName, trimmedName);
59
61
  }
60
62
  else {
61
63
  // Audio file will be set from the beat's audio file when available
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ g: boolean;
10
12
  } & {
11
13
  backup: boolean;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ g: boolean;
10
12
  } & {
11
13
  backup: boolean;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ g: boolean;
10
12
  } & {
11
13
  backup: boolean;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ g: boolean;
10
12
  } & {
11
13
  backup: boolean;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ g: boolean;
10
12
  } & {
11
13
  backup: boolean;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ g: boolean;
10
12
  } & {
11
13
  backup: boolean;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ g: boolean;
10
12
  } & {
11
13
  backup: boolean;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const builder: (yargs: Argv) => Argv<import("yargs").Omit<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ g: boolean;
10
12
  } & {
11
13
  backup: boolean;
12
14
  } & {
@@ -7,6 +7,8 @@ export declare const commonOptions: (yargs: Argv) => Argv<{
7
7
  l: string | undefined;
8
8
  } & {
9
9
  f: boolean;
10
+ } & {
11
+ g: boolean;
10
12
  } & {
11
13
  backup: boolean;
12
14
  } & {
package/lib/cli/common.js CHANGED
@@ -25,6 +25,12 @@ export const commonOptions = (yargs) => {
25
25
  describe: "Force regenerate",
26
26
  type: "boolean",
27
27
  default: false,
28
+ })
29
+ .option("g", {
30
+ alias: "grouped",
31
+ describe: "Output all files under output/<basename>/ directory",
32
+ type: "boolean",
33
+ default: false,
28
34
  })
29
35
  .option("backup", {
30
36
  describe: "create backup media file",
@@ -10,5 +10,6 @@ export declare const getFileObject: (args: {
10
10
  presentationStyle?: string;
11
11
  file: string;
12
12
  nodeModuleRootPath?: string;
13
+ grouped?: boolean;
13
14
  }) => FileObject;
14
15
  export declare const initializeContext: (argv: CliArgs<InitOptions>, raiseError?: boolean) => Promise<MulmoStudioContext | null>;
@@ -30,9 +30,9 @@ export const setGraphAILogger = (verbose, logValues) => {
30
30
  }
31
31
  };
32
32
  export const getFileObject = (args) => {
33
- const { basedir, outdir, imagedir, audiodir, file, presentationStyle, nodeModuleRootPath } = args;
33
+ const { basedir, outdir, imagedir, audiodir, file, presentationStyle, nodeModuleRootPath, grouped = false } = args;
34
34
  const baseDirPath = getBaseDirPath(basedir);
35
- const outDirPath = getFullPath(baseDirPath, outdir ?? outDirName);
35
+ const baseOutDirPath = getFullPath(baseDirPath, outdir ?? outDirName);
36
36
  const { fileOrUrl, fileName } = (() => {
37
37
  if (file === "__clipboard") {
38
38
  // We generate a new unique script file from clipboard text in the output directory
@@ -40,8 +40,8 @@ export const getFileObject = (args) => {
40
40
  const clipboardText = clipboardy.readSync();
41
41
  const json = JSON.parse(clipboardText);
42
42
  const formattedText = JSON.stringify(json, null, 2);
43
- const resolvedFilePath = resolveDirPath(outDirPath, `${generatedFileName}.json`);
44
- mkdir(outDirPath);
43
+ const resolvedFilePath = resolveDirPath(baseOutDirPath, `${generatedFileName}.json`);
44
+ mkdir(baseOutDirPath);
45
45
  fs.writeFileSync(resolvedFilePath, formattedText, "utf8");
46
46
  return { fileOrUrl: resolvedFilePath, fileName: generatedFileName };
47
47
  }
@@ -49,6 +49,7 @@ export const getFileObject = (args) => {
49
49
  const parsedFileName = path.parse(resolvedFileOrUrl).name;
50
50
  return { fileOrUrl: resolvedFileOrUrl, fileName: parsedFileName };
51
51
  })();
52
+ const outDirPath = grouped ? getFullPath(baseOutDirPath, fileName) : baseOutDirPath;
52
53
  const isHttpPath = isHttp(fileOrUrl);
53
54
  const mulmoFilePath = isHttpPath ? "" : getFullPath(baseDirPath, fileOrUrl);
54
55
  const mulmoFileDirPath = path.dirname(isHttpPath ? baseDirPath : mulmoFilePath);
@@ -71,6 +72,7 @@ export const getFileObject = (args) => {
71
72
  presentationStylePath,
72
73
  fileName,
73
74
  nodeModuleRootPath,
75
+ grouped,
74
76
  };
75
77
  };
76
78
  export const initializeContext = async (argv, raiseError = false) => {
@@ -81,6 +83,7 @@ export const initializeContext = async (argv, raiseError = false) => {
81
83
  audiodir: argv.a,
82
84
  presentationStyle: argv.p,
83
85
  file: argv.file ?? "",
86
+ grouped: Boolean(argv.g),
84
87
  });
85
88
  setGraphAILogger(Boolean(argv.v), { files });
86
89
  return await initializeContextFromFiles(files, raiseError, Boolean(argv.f), Boolean(argv.backup), argv.c, argv.l);
@@ -44,6 +44,9 @@ export const MulmoStudioContextMethods = {
44
44
  },
45
45
  getImageProjectDirPath(context) {
46
46
  const imageDirPath = MulmoStudioContextMethods.getImageDirPath(context);
47
+ if (context.fileDirs.grouped) {
48
+ return imageDirPath;
49
+ }
47
50
  return `${imageDirPath}/${context.studio.filename}`;
48
51
  },
49
52
  getOutDirPath(context) {
@@ -128,6 +128,7 @@ export interface FileObject {
128
128
  outputMultilingualFilePath: string;
129
129
  presentationStylePath: string | undefined;
130
130
  fileName: string;
131
+ grouped: boolean;
131
132
  }
132
133
  export type InitOptions = {
133
134
  b?: string;
@@ -138,6 +139,7 @@ export type InitOptions = {
138
139
  l?: string;
139
140
  c?: string;
140
141
  p?: string;
142
+ g?: boolean;
141
143
  };
142
144
  export type PublicAPIArgs = {
143
145
  settings?: Record<string, string>;
@@ -20,7 +20,9 @@ export declare const fetchMulmoScriptFile: (url: string) => Promise<{
20
20
  export declare const getOutputStudioFilePath: (outDirPath: string, fileName: string) => string;
21
21
  export declare const getOutputMultilingualFilePath: (outDirPath: string, fileName: string) => string;
22
22
  export declare const resolveDirPath: (dirPath: string, studioFileName: string) => string;
23
+ export declare const formatAudioFileName: (name: string, lang?: string) => string;
23
24
  export declare const getAudioFilePath: (audioDirPath: string, dirName: string, fileName: string, lang?: string) => string;
25
+ export declare const getGroupedAudioFilePath: (audioDirPath: string, fileName: string, lang?: string) => string;
24
26
  export declare const getAudioArtifactFilePath: (context: MulmoStudioContext) => string;
25
27
  export declare const getOutputVideoFilePath: (outDirPath: string, fileName: string, lang?: string, caption?: string) => string;
26
28
  export declare const imageSuffix = "p";
package/lib/utils/file.js CHANGED
@@ -68,11 +68,15 @@ export const resolveDirPath = (dirPath, studioFileName) => {
68
68
  return path.resolve(dirPath, studioFileName);
69
69
  };
70
70
  // audio
71
+ export const formatAudioFileName = (name, lang) => {
72
+ const suffix = lang ? `_${lang}` : "";
73
+ return `${name}${suffix}.mp3`;
74
+ };
71
75
  export const getAudioFilePath = (audioDirPath, dirName, fileName, lang) => {
72
- if (lang) {
73
- return path.resolve(audioDirPath, dirName, `${fileName}_${lang}.mp3`);
74
- }
75
- return path.resolve(audioDirPath, dirName, fileName + ".mp3");
76
+ return path.resolve(audioDirPath, dirName, formatAudioFileName(fileName, lang));
77
+ };
78
+ export const getGroupedAudioFilePath = (audioDirPath, fileName, lang) => {
79
+ return path.resolve(audioDirPath, formatAudioFileName(fileName, lang));
76
80
  };
77
81
  export const getAudioArtifactFilePath = (context) => {
78
82
  const suffix = context.lang ? `_${context.lang}` : "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mulmocast",
3
- "version": "2.3.0",
3
+ "version": "2.3.1",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "lib/index.node.js",