@mulmocast/slide 0.1.4 → 0.1.6
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/actions/common.d.ts +1 -1
- package/lib/actions/common.d.ts.map +1 -1
- package/lib/actions/common.js +9 -0
- package/lib/actions/common.js.map +1 -1
- package/lib/actions/movie.js +2 -2
- package/lib/actions/movie.js.map +1 -1
- package/lib/actions/preview.d.ts +3 -0
- package/lib/actions/preview.d.ts.map +1 -0
- package/lib/actions/preview.js +147 -0
- package/lib/actions/preview.js.map +1 -0
- package/lib/cli.js +62 -5
- package/lib/cli.js.map +1 -1
- package/lib/convert/movie.d.ts +17 -0
- package/lib/convert/movie.d.ts.map +1 -0
- package/lib/convert/movie.js +397 -0
- package/lib/convert/movie.js.map +1 -0
- package/lib/convert/movie_bundle.d.ts +34 -0
- package/lib/convert/movie_bundle.d.ts.map +1 -0
- package/lib/convert/movie_bundle.js +217 -0
- package/lib/convert/movie_bundle.js.map +1 -0
- package/lib/utils/audio-save.d.ts +25 -0
- package/lib/utils/audio-save.d.ts.map +1 -0
- package/lib/utils/audio-save.js +190 -0
- package/lib/utils/audio-save.js.map +1 -0
- package/lib/utils/bundle-server.d.ts +10 -0
- package/lib/utils/bundle-server.d.ts.map +1 -0
- package/lib/utils/bundle-server.js +97 -0
- package/lib/utils/bundle-server.js.map +1 -0
- package/lib/utils/dependencies.d.ts.map +1 -1
- package/lib/utils/dependencies.js +7 -0
- package/lib/utils/dependencies.js.map +1 -1
- package/lib/vue/assets/index-D6am8L57.css +1 -0
- package/lib/vue/assets/index-xq-ZNfmX.js +2 -0
- package/lib/vue/index.html +13 -0
- package/lib/vue/main.d.ts +2 -0
- package/lib/vue/main.d.ts.map +1 -0
- package/lib/vue/main.js +10 -0
- package/lib/vue/main.js.map +1 -0
- package/package.json +16 -5
|
@@ -0,0 +1,397 @@
|
|
|
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.convertMovie = convertMovie;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const child_process_1 = require("child_process");
|
|
43
|
+
const yargs_1 = __importDefault(require("yargs"));
|
|
44
|
+
const helpers_1 = require("yargs/helpers");
|
|
45
|
+
const lang_1 = require("../utils/lang");
|
|
46
|
+
const dependencies_1 = require("../utils/dependencies");
|
|
47
|
+
const openai_1 = __importDefault(require("openai"));
|
|
48
|
+
const mulmocast_1 = require("mulmocast");
|
|
49
|
+
const movie_bundle_1 = require("./movie_bundle");
|
|
50
|
+
// Get video duration using ffprobe
|
|
51
|
+
function getVideoDuration(videoPath) {
|
|
52
|
+
const result = (0, child_process_1.execSync)(`ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 "${videoPath}"`, { encoding: "utf-8" });
|
|
53
|
+
return parseFloat(result.trim());
|
|
54
|
+
}
|
|
55
|
+
// Detect silence intervals in video using FFmpeg
|
|
56
|
+
async function detectSilence(videoPath, noiseThreshold = -30, minSilenceDuration = 0.5) {
|
|
57
|
+
return new Promise((resolve, reject) => {
|
|
58
|
+
const silences = [];
|
|
59
|
+
let currentStart = null;
|
|
60
|
+
const ffmpeg = (0, child_process_1.spawn)("ffmpeg", [
|
|
61
|
+
"-i",
|
|
62
|
+
videoPath,
|
|
63
|
+
"-af",
|
|
64
|
+
`silencedetect=noise=${noiseThreshold}dB:d=${minSilenceDuration}`,
|
|
65
|
+
"-f",
|
|
66
|
+
"null",
|
|
67
|
+
"-",
|
|
68
|
+
]);
|
|
69
|
+
let stderr = "";
|
|
70
|
+
ffmpeg.stderr.on("data", (data) => {
|
|
71
|
+
stderr += data.toString();
|
|
72
|
+
});
|
|
73
|
+
ffmpeg.on("close", (code) => {
|
|
74
|
+
if (code !== 0 && code !== null) {
|
|
75
|
+
// FFmpeg may return non-zero even on success for silence detection
|
|
76
|
+
}
|
|
77
|
+
// Parse silence_start and silence_end from stderr
|
|
78
|
+
const lines = stderr.split("\n");
|
|
79
|
+
for (const line of lines) {
|
|
80
|
+
const startMatch = line.match(/silence_start:\s*([\d.]+)/);
|
|
81
|
+
const endMatch = line.match(/silence_end:\s*([\d.]+)/);
|
|
82
|
+
if (startMatch) {
|
|
83
|
+
currentStart = parseFloat(startMatch[1]);
|
|
84
|
+
}
|
|
85
|
+
if (endMatch && currentStart !== null) {
|
|
86
|
+
silences.push({
|
|
87
|
+
start: currentStart,
|
|
88
|
+
end: parseFloat(endMatch[1]),
|
|
89
|
+
});
|
|
90
|
+
currentStart = null;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
resolve(silences);
|
|
94
|
+
});
|
|
95
|
+
ffmpeg.on("error", reject);
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
// Calculate segment boundaries based on silence intervals
|
|
99
|
+
function calculateSegments(totalDuration, silences, minDuration = 20, maxDuration = 120) {
|
|
100
|
+
const segments = [];
|
|
101
|
+
let currentStart = 0;
|
|
102
|
+
let segmentIndex = 1;
|
|
103
|
+
// Get silence midpoints as potential split points
|
|
104
|
+
const splitPoints = silences.map((s) => (s.start + s.end) / 2);
|
|
105
|
+
while (currentStart < totalDuration) {
|
|
106
|
+
const targetEnd = currentStart + maxDuration;
|
|
107
|
+
if (targetEnd >= totalDuration) {
|
|
108
|
+
// Last segment
|
|
109
|
+
segments.push({
|
|
110
|
+
index: segmentIndex,
|
|
111
|
+
startTime: currentStart,
|
|
112
|
+
endTime: totalDuration,
|
|
113
|
+
duration: totalDuration - currentStart,
|
|
114
|
+
});
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
// Find the closest silence point near the target end
|
|
118
|
+
let bestSplit = targetEnd;
|
|
119
|
+
let minDistance = Infinity;
|
|
120
|
+
for (const point of splitPoints) {
|
|
121
|
+
if (point > currentStart + minDuration && point < targetEnd + 30) {
|
|
122
|
+
const distance = Math.abs(point - targetEnd);
|
|
123
|
+
if (distance < minDistance) {
|
|
124
|
+
minDistance = distance;
|
|
125
|
+
bestSplit = point;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
segments.push({
|
|
130
|
+
index: segmentIndex,
|
|
131
|
+
startTime: currentStart,
|
|
132
|
+
endTime: bestSplit,
|
|
133
|
+
duration: bestSplit - currentStart,
|
|
134
|
+
});
|
|
135
|
+
currentStart = bestSplit;
|
|
136
|
+
segmentIndex++;
|
|
137
|
+
}
|
|
138
|
+
// If no silences detected, use fixed segmentation
|
|
139
|
+
if (segments.length === 0) {
|
|
140
|
+
const fixedDuration = 60;
|
|
141
|
+
let start = 0;
|
|
142
|
+
let idx = 1;
|
|
143
|
+
while (start < totalDuration) {
|
|
144
|
+
const end = Math.min(start + fixedDuration, totalDuration);
|
|
145
|
+
segments.push({
|
|
146
|
+
index: idx,
|
|
147
|
+
startTime: start,
|
|
148
|
+
endTime: end,
|
|
149
|
+
duration: end - start,
|
|
150
|
+
});
|
|
151
|
+
start = end;
|
|
152
|
+
idx++;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
return segments;
|
|
156
|
+
}
|
|
157
|
+
// Split video into segment
|
|
158
|
+
function splitVideo(inputPath, outputPath, startTime, duration) {
|
|
159
|
+
(0, child_process_1.execSync)(`ffmpeg -y -ss ${startTime} -i "${inputPath}" -t ${duration} -c copy "${outputPath}"`, { stdio: "ignore" });
|
|
160
|
+
}
|
|
161
|
+
// Extract audio from video segment
|
|
162
|
+
function extractAudio(videoPath, audioPath) {
|
|
163
|
+
(0, child_process_1.execSync)(`ffmpeg -y -i "${videoPath}" -vn -acodec libmp3lame -q:a 2 "${audioPath}"`, { stdio: "ignore" });
|
|
164
|
+
}
|
|
165
|
+
// Generate thumbnail from video segment
|
|
166
|
+
function generateThumbnail(videoPath, thumbnailPath) {
|
|
167
|
+
(0, child_process_1.execSync)(`ffmpeg -y -i "${videoPath}" -ss 0 -vframes 1 -vf "scale=640:-1" "${thumbnailPath}"`, { stdio: "ignore" });
|
|
168
|
+
}
|
|
169
|
+
// Transcribe audio using OpenAI Whisper API
|
|
170
|
+
async function transcribeAudio(audioPath, lang, openai) {
|
|
171
|
+
const audioFile = fs.createReadStream(audioPath);
|
|
172
|
+
const response = await openai.audio.transcriptions.create({
|
|
173
|
+
file: audioFile,
|
|
174
|
+
model: "whisper-1",
|
|
175
|
+
language: lang === "ja" ? "ja" : "en",
|
|
176
|
+
});
|
|
177
|
+
return response.text;
|
|
178
|
+
}
|
|
179
|
+
async function convertMovie(options) {
|
|
180
|
+
const { inputPath, lang, minSegmentDuration = 20, maxSegmentDuration = 120, } = options;
|
|
181
|
+
const videoPath = path.resolve(inputPath);
|
|
182
|
+
// Determine source language upfront (CLI option or default)
|
|
183
|
+
// For video transcription, we use the specified language directly
|
|
184
|
+
const sourceLang = lang && (0, lang_1.isValidLang)(lang) ? lang : "en";
|
|
185
|
+
if (!fs.existsSync(videoPath)) {
|
|
186
|
+
throw new Error(`File not found: ${videoPath}`);
|
|
187
|
+
}
|
|
188
|
+
// Check for required dependencies
|
|
189
|
+
(0, dependencies_1.checkDependencies)("movie");
|
|
190
|
+
// Check for OpenAI API key
|
|
191
|
+
const apiKey = process.env.OPENAI_API_KEY;
|
|
192
|
+
if (!apiKey) {
|
|
193
|
+
throw new Error("OPENAI_API_KEY environment variable is required for transcription");
|
|
194
|
+
}
|
|
195
|
+
const openai = new openai_1.default({ apiKey });
|
|
196
|
+
const ext = path.extname(videoPath);
|
|
197
|
+
const basename = path.basename(videoPath, ext);
|
|
198
|
+
// Scripts directory for MulmoScript and processing assets
|
|
199
|
+
const scriptsDir = options.outputDir || path.join("scripts", basename);
|
|
200
|
+
// Bundle output directory (same structure as other formats)
|
|
201
|
+
const bundleDir = path.join("output", basename, "mulmo_script");
|
|
202
|
+
// Create scripts directory
|
|
203
|
+
if (!fs.existsSync(scriptsDir)) {
|
|
204
|
+
fs.mkdirSync(scriptsDir, { recursive: true });
|
|
205
|
+
}
|
|
206
|
+
console.log(`Processing video: ${videoPath}`);
|
|
207
|
+
console.log(`Scripts directory: ${scriptsDir}`);
|
|
208
|
+
// Get video duration
|
|
209
|
+
console.log("Getting video duration...");
|
|
210
|
+
const totalDuration = getVideoDuration(videoPath);
|
|
211
|
+
console.log(` Total duration: ${Math.floor(totalDuration / 60)}m ${Math.floor(totalDuration % 60)}s`);
|
|
212
|
+
// Detect silence intervals
|
|
213
|
+
console.log("Detecting silence intervals...");
|
|
214
|
+
const silences = await detectSilence(videoPath);
|
|
215
|
+
console.log(` Found ${silences.length} silence intervals`);
|
|
216
|
+
// Calculate segments
|
|
217
|
+
console.log("Calculating segments...");
|
|
218
|
+
const segments = calculateSegments(totalDuration, silences, minSegmentDuration, maxSegmentDuration);
|
|
219
|
+
console.log(` Created ${segments.length} segments`);
|
|
220
|
+
// Process each segment
|
|
221
|
+
const beats = [];
|
|
222
|
+
const transcriptions = [];
|
|
223
|
+
for (const segment of segments) {
|
|
224
|
+
const segmentNum = segment.index;
|
|
225
|
+
const videoFile = `${segmentNum}.mp4`;
|
|
226
|
+
const audioFile = `${segmentNum}.mp3`;
|
|
227
|
+
const thumbnailFile = `${segmentNum}.jpg`;
|
|
228
|
+
const videoOutputPath = path.join(scriptsDir, videoFile);
|
|
229
|
+
const audioOutputPath = path.join(scriptsDir, audioFile);
|
|
230
|
+
const thumbnailOutputPath = path.join(scriptsDir, thumbnailFile);
|
|
231
|
+
console.log(`\nProcessing segment ${segmentNum}/${segments.length}...`);
|
|
232
|
+
// Split video (with caching)
|
|
233
|
+
if (!fs.existsSync(videoOutputPath)) {
|
|
234
|
+
console.log(` Splitting video...`);
|
|
235
|
+
splitVideo(videoPath, videoOutputPath, segment.startTime, segment.duration);
|
|
236
|
+
}
|
|
237
|
+
else {
|
|
238
|
+
console.log(` Using cached video`);
|
|
239
|
+
}
|
|
240
|
+
// Extract audio (with caching)
|
|
241
|
+
if (!fs.existsSync(audioOutputPath)) {
|
|
242
|
+
console.log(` Extracting audio...`);
|
|
243
|
+
extractAudio(videoOutputPath, audioOutputPath);
|
|
244
|
+
}
|
|
245
|
+
else {
|
|
246
|
+
console.log(` Using cached audio`);
|
|
247
|
+
}
|
|
248
|
+
// Generate thumbnail (with caching)
|
|
249
|
+
if (!fs.existsSync(thumbnailOutputPath)) {
|
|
250
|
+
console.log(` Generating thumbnail...`);
|
|
251
|
+
generateThumbnail(videoOutputPath, thumbnailOutputPath);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
console.log(` Using cached thumbnail`);
|
|
255
|
+
}
|
|
256
|
+
// Transcribe audio
|
|
257
|
+
console.log(` Transcribing audio...`);
|
|
258
|
+
const transcription = await transcribeAudio(audioOutputPath, sourceLang, openai);
|
|
259
|
+
transcriptions.push(transcription);
|
|
260
|
+
console.log(` Transcription: ${transcription.substring(0, 100)}...`);
|
|
261
|
+
beats.push({
|
|
262
|
+
text: transcription,
|
|
263
|
+
audioSources: {
|
|
264
|
+
[sourceLang]: audioFile,
|
|
265
|
+
},
|
|
266
|
+
multiLinguals: {
|
|
267
|
+
[sourceLang]: transcription,
|
|
268
|
+
},
|
|
269
|
+
videoSource: videoFile,
|
|
270
|
+
imageSource: thumbnailFile,
|
|
271
|
+
startTime: segment.startTime,
|
|
272
|
+
endTime: segment.endTime,
|
|
273
|
+
duration: segment.duration,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
console.log(`\nSource language: ${sourceLang}`);
|
|
277
|
+
// Build MulmoScript with proper schema
|
|
278
|
+
// For video content, we use the `image` field with type: "movie"
|
|
279
|
+
const mulmoBeats = beats.map((beat) => ({
|
|
280
|
+
text: beat.text,
|
|
281
|
+
image: {
|
|
282
|
+
type: "movie",
|
|
283
|
+
source: {
|
|
284
|
+
kind: "path",
|
|
285
|
+
path: `./${beat.videoSource}`,
|
|
286
|
+
},
|
|
287
|
+
},
|
|
288
|
+
}));
|
|
289
|
+
const mulmoScript = {
|
|
290
|
+
$mulmocast: {
|
|
291
|
+
version: "1.1",
|
|
292
|
+
credit: "closing",
|
|
293
|
+
},
|
|
294
|
+
lang: sourceLang,
|
|
295
|
+
beats: mulmoBeats,
|
|
296
|
+
};
|
|
297
|
+
// Validate MulmoScript
|
|
298
|
+
const result = mulmocast_1.mulmoScriptSchema.safeParse(mulmoScript);
|
|
299
|
+
if (!result.success) {
|
|
300
|
+
console.error("MulmoScript validation failed:");
|
|
301
|
+
console.error(result.error.format());
|
|
302
|
+
throw new Error("Invalid MulmoScript generated");
|
|
303
|
+
}
|
|
304
|
+
// Write MulmoScript to scripts directory
|
|
305
|
+
const jsonPath = path.join(scriptsDir, "mulmo_script.json");
|
|
306
|
+
fs.writeFileSync(jsonPath, JSON.stringify(result.data, null, 2));
|
|
307
|
+
console.log(`\nMulmoScript saved to: ${jsonPath}`);
|
|
308
|
+
// Generate bundle with translations and TTS if requested
|
|
309
|
+
const shouldBundle = options.bundle ?? true; // Default to bundling for movie
|
|
310
|
+
const targetLangs = options.targetLangs ?? ["ja"]; // Default target language
|
|
311
|
+
let bundlePath;
|
|
312
|
+
if (shouldBundle) {
|
|
313
|
+
// Create bundle output directory
|
|
314
|
+
if (!fs.existsSync(bundleDir)) {
|
|
315
|
+
fs.mkdirSync(bundleDir, { recursive: true });
|
|
316
|
+
}
|
|
317
|
+
console.log(`Bundle directory: ${bundleDir}`);
|
|
318
|
+
// Prepare beat data for bundle generation
|
|
319
|
+
const bundleBeats = beats.map((beat, index) => ({
|
|
320
|
+
text: beat.text,
|
|
321
|
+
videoSource: beat.videoSource,
|
|
322
|
+
imageSource: beat.imageSource,
|
|
323
|
+
audioSource: beat.audioSources[sourceLang] || `${index + 1}.mp3`,
|
|
324
|
+
startTime: beat.startTime,
|
|
325
|
+
endTime: beat.endTime,
|
|
326
|
+
duration: beat.duration,
|
|
327
|
+
}));
|
|
328
|
+
await (0, movie_bundle_1.generateMovieBundle)({
|
|
329
|
+
scriptsDir,
|
|
330
|
+
outputDir: bundleDir,
|
|
331
|
+
sourceLang: sourceLang,
|
|
332
|
+
targetLangs,
|
|
333
|
+
beats: bundleBeats,
|
|
334
|
+
totalDuration,
|
|
335
|
+
});
|
|
336
|
+
bundlePath = path.join(bundleDir, "mulmo_view.json");
|
|
337
|
+
}
|
|
338
|
+
return {
|
|
339
|
+
mulmoScriptPath: jsonPath,
|
|
340
|
+
segmentCount: segments.length,
|
|
341
|
+
bundlePath,
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
async function main() {
|
|
345
|
+
// Load environment variables
|
|
346
|
+
const dotenv = await Promise.resolve().then(() => __importStar(require("dotenv")));
|
|
347
|
+
dotenv.config();
|
|
348
|
+
const argv = await (0, yargs_1.default)((0, helpers_1.hideBin)(process.argv))
|
|
349
|
+
.usage("Usage: $0 <video-file> [options]")
|
|
350
|
+
.command("$0 <file>", "Convert video to MulmoScript", (yargs) => {
|
|
351
|
+
return yargs.positional("file", {
|
|
352
|
+
describe: "Video file to convert (mp4, mov, mkv, webm, avi)",
|
|
353
|
+
type: "string",
|
|
354
|
+
demandOption: true,
|
|
355
|
+
});
|
|
356
|
+
})
|
|
357
|
+
.options({
|
|
358
|
+
...lang_1.langOption,
|
|
359
|
+
"min-segment": {
|
|
360
|
+
type: "number",
|
|
361
|
+
description: "Minimum segment duration in seconds",
|
|
362
|
+
default: 20,
|
|
363
|
+
},
|
|
364
|
+
"max-segment": {
|
|
365
|
+
type: "number",
|
|
366
|
+
description: "Maximum segment duration in seconds",
|
|
367
|
+
default: 120,
|
|
368
|
+
},
|
|
369
|
+
bundle: {
|
|
370
|
+
type: "boolean",
|
|
371
|
+
description: "Generate bundle with translations and TTS",
|
|
372
|
+
default: true,
|
|
373
|
+
},
|
|
374
|
+
"target-langs": {
|
|
375
|
+
type: "string",
|
|
376
|
+
description: "Target languages for translation (comma-separated)",
|
|
377
|
+
default: "ja",
|
|
378
|
+
},
|
|
379
|
+
})
|
|
380
|
+
.help()
|
|
381
|
+
.parse();
|
|
382
|
+
await convertMovie({
|
|
383
|
+
inputPath: argv.file,
|
|
384
|
+
lang: argv.l,
|
|
385
|
+
minSegmentDuration: argv["min-segment"],
|
|
386
|
+
maxSegmentDuration: argv["max-segment"],
|
|
387
|
+
bundle: argv.bundle,
|
|
388
|
+
targetLangs: argv["target-langs"].split(",").map((l) => l.trim()),
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
if (require.main === module) {
|
|
392
|
+
main().catch((error) => {
|
|
393
|
+
console.error("Error:", error.message);
|
|
394
|
+
process.exit(1);
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
//# sourceMappingURL=movie.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"movie.js","sourceRoot":"","sources":["../../src/convert/movie.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export interface BeatData {
|
|
2
|
+
text: string;
|
|
3
|
+
audioSources: Record<string, string>;
|
|
4
|
+
multiLinguals: Record<string, string>;
|
|
5
|
+
videoSource: string;
|
|
6
|
+
thumbnail: string;
|
|
7
|
+
startTime: number;
|
|
8
|
+
endTime: number;
|
|
9
|
+
duration: number;
|
|
10
|
+
}
|
|
11
|
+
export interface MulmoViewData {
|
|
12
|
+
lang: string;
|
|
13
|
+
totalDuration: number;
|
|
14
|
+
totalSegments: number;
|
|
15
|
+
beats: BeatData[];
|
|
16
|
+
}
|
|
17
|
+
export interface MovieBundleOptions {
|
|
18
|
+
scriptsDir: string;
|
|
19
|
+
outputDir: string;
|
|
20
|
+
sourceLang: string;
|
|
21
|
+
targetLangs: string[];
|
|
22
|
+
beats: Array<{
|
|
23
|
+
text: string;
|
|
24
|
+
videoSource: string;
|
|
25
|
+
imageSource: string;
|
|
26
|
+
audioSource: string;
|
|
27
|
+
startTime: number;
|
|
28
|
+
endTime: number;
|
|
29
|
+
duration: number;
|
|
30
|
+
}>;
|
|
31
|
+
totalDuration: number;
|
|
32
|
+
}
|
|
33
|
+
export declare function generateMovieBundle(options: MovieBundleOptions): Promise<MulmoViewData>;
|
|
34
|
+
//# sourceMappingURL=movie_bundle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"movie_bundle.d.ts","sourceRoot":"","sources":["../../src/convert/movie_bundle.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,MAAM,CAAC;IACtB,aAAa,EAAE,MAAM,CAAC;IACtB,KAAK,EAAE,QAAQ,EAAE,CAAC;CACnB;AAyFD,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,KAAK,EAAE,KAAK,CAAC;QACX,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;KAClB,CAAC,CAAC;IACH,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,aAAa,CAAC,CAiHxB"}
|
|
@@ -0,0 +1,217 @@
|
|
|
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.generateMovieBundle = generateMovieBundle;
|
|
40
|
+
const fs = __importStar(require("fs"));
|
|
41
|
+
const path = __importStar(require("path"));
|
|
42
|
+
const openai_1 = __importDefault(require("openai"));
|
|
43
|
+
const LANG_NAMES = {
|
|
44
|
+
en: "English",
|
|
45
|
+
ja: "Japanese",
|
|
46
|
+
fr: "French",
|
|
47
|
+
de: "German",
|
|
48
|
+
es: "Spanish",
|
|
49
|
+
zh: "Chinese",
|
|
50
|
+
ko: "Korean",
|
|
51
|
+
};
|
|
52
|
+
// Copy file if it doesn't exist in destination
|
|
53
|
+
function copyFileIfNeeded(srcPath, destPath) {
|
|
54
|
+
if (!fs.existsSync(destPath) && fs.existsSync(srcPath)) {
|
|
55
|
+
fs.copyFileSync(srcPath, destPath);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Translate text using OpenAI with retry logic
|
|
59
|
+
async function translateText(text, fromLang, toLang, openai, maxRetries = 3) {
|
|
60
|
+
if (!text.trim()) {
|
|
61
|
+
return "";
|
|
62
|
+
}
|
|
63
|
+
const fromLangName = LANG_NAMES[fromLang] || fromLang;
|
|
64
|
+
const toLangName = LANG_NAMES[toLang] || toLang;
|
|
65
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
66
|
+
try {
|
|
67
|
+
const response = await openai.chat.completions.create({
|
|
68
|
+
model: "gpt-4o-mini",
|
|
69
|
+
messages: [
|
|
70
|
+
{
|
|
71
|
+
role: "system",
|
|
72
|
+
content: `Translate the given ${fromLangName} text to natural ${toLangName}. Only return the translated text, nothing else.`,
|
|
73
|
+
},
|
|
74
|
+
{
|
|
75
|
+
role: "user",
|
|
76
|
+
content: text,
|
|
77
|
+
},
|
|
78
|
+
],
|
|
79
|
+
});
|
|
80
|
+
return response.choices[0]?.message?.content?.trim() || text;
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
console.warn(`Translation attempt ${attempt}/${maxRetries} failed: ${error}`);
|
|
84
|
+
if (attempt === maxRetries) {
|
|
85
|
+
console.warn(`Translation failed after ${maxRetries} attempts, using original text`);
|
|
86
|
+
return text;
|
|
87
|
+
}
|
|
88
|
+
// Wait before retry (exponential backoff)
|
|
89
|
+
await new Promise((resolve) => setTimeout(resolve, 1000 * attempt));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return text;
|
|
93
|
+
}
|
|
94
|
+
// Generate TTS audio using OpenAI with retry logic
|
|
95
|
+
async function textToSpeech(text, outputPath, lang, openai, maxRetries = 3) {
|
|
96
|
+
if (!text.trim()) {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
100
|
+
try {
|
|
101
|
+
const response = await openai.audio.speech.create({
|
|
102
|
+
model: "tts-1",
|
|
103
|
+
voice: "alloy",
|
|
104
|
+
input: text,
|
|
105
|
+
});
|
|
106
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
107
|
+
fs.writeFileSync(outputPath, buffer);
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
catch (error) {
|
|
111
|
+
console.warn(`TTS attempt ${attempt}/${maxRetries} failed: ${error}`);
|
|
112
|
+
if (attempt === maxRetries) {
|
|
113
|
+
console.error(`TTS generation failed for ${outputPath} after ${maxRetries} attempts`);
|
|
114
|
+
throw error;
|
|
115
|
+
}
|
|
116
|
+
// Wait before retry (exponential backoff)
|
|
117
|
+
await new Promise((resolve) => setTimeout(resolve, 1000 * attempt));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
async function generateMovieBundle(options) {
|
|
122
|
+
const { scriptsDir, outputDir, sourceLang, targetLangs, beats, totalDuration } = options;
|
|
123
|
+
const apiKey = process.env.OPENAI_API_KEY;
|
|
124
|
+
if (!apiKey) {
|
|
125
|
+
throw new Error("OPENAI_API_KEY environment variable is required");
|
|
126
|
+
}
|
|
127
|
+
const openai = new openai_1.default({ apiKey });
|
|
128
|
+
const bundleBeats = [];
|
|
129
|
+
console.log(`\nGenerating bundle with ${beats.length} segments...`);
|
|
130
|
+
console.log(` Source: ${scriptsDir}`);
|
|
131
|
+
console.log(` Output: ${outputDir}`);
|
|
132
|
+
console.log(` Source language: ${sourceLang}`);
|
|
133
|
+
console.log(` Target languages: ${targetLangs.join(", ")}`);
|
|
134
|
+
for (let i = 0; i < beats.length; i++) {
|
|
135
|
+
const beat = beats[i];
|
|
136
|
+
const segmentNum = i + 1;
|
|
137
|
+
console.log(`\nProcessing segment ${segmentNum}/${beats.length}...`);
|
|
138
|
+
// Copy source assets to output directory
|
|
139
|
+
const srcVideoPath = path.join(scriptsDir, beat.videoSource);
|
|
140
|
+
const srcAudioPath = path.join(scriptsDir, beat.audioSource);
|
|
141
|
+
const srcThumbnailPath = path.join(scriptsDir, beat.imageSource);
|
|
142
|
+
const destVideoPath = path.join(outputDir, beat.videoSource);
|
|
143
|
+
const destAudioPath = path.join(outputDir, beat.audioSource);
|
|
144
|
+
const destThumbnailPath = path.join(outputDir, beat.imageSource);
|
|
145
|
+
console.log(` Copying assets...`);
|
|
146
|
+
copyFileIfNeeded(srcVideoPath, destVideoPath);
|
|
147
|
+
copyFileIfNeeded(srcAudioPath, destAudioPath);
|
|
148
|
+
copyFileIfNeeded(srcThumbnailPath, destThumbnailPath);
|
|
149
|
+
// Initialize audioSources and multiLinguals with source language
|
|
150
|
+
const audioSources = {
|
|
151
|
+
[sourceLang]: beat.audioSource,
|
|
152
|
+
};
|
|
153
|
+
const multiLinguals = {
|
|
154
|
+
[sourceLang]: beat.text,
|
|
155
|
+
};
|
|
156
|
+
// Process each target language
|
|
157
|
+
for (const targetLang of targetLangs) {
|
|
158
|
+
if (targetLang === sourceLang) {
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
const targetAudioFile = `${segmentNum}_${targetLang}.mp3`;
|
|
162
|
+
const targetAudioPath = path.join(outputDir, targetAudioFile);
|
|
163
|
+
// Check if translation/audio already exists (caching)
|
|
164
|
+
if (fs.existsSync(targetAudioPath)) {
|
|
165
|
+
console.log(` Using cached ${targetLang} audio`);
|
|
166
|
+
audioSources[targetLang] = targetAudioFile;
|
|
167
|
+
// Try to read cached translation from existing mulmo_view.json
|
|
168
|
+
const viewPath = path.join(outputDir, "mulmo_view.json");
|
|
169
|
+
if (fs.existsSync(viewPath)) {
|
|
170
|
+
try {
|
|
171
|
+
const existingView = JSON.parse(fs.readFileSync(viewPath, "utf-8"));
|
|
172
|
+
const existingBeat = existingView.beats?.[i];
|
|
173
|
+
if (existingBeat?.multiLinguals?.[targetLang]) {
|
|
174
|
+
multiLinguals[targetLang] = existingBeat.multiLinguals[targetLang];
|
|
175
|
+
continue;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
// Ignore cache read errors
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
// Translate text
|
|
184
|
+
console.log(` Translating to ${targetLang}...`);
|
|
185
|
+
const translatedText = await translateText(beat.text, sourceLang, targetLang, openai);
|
|
186
|
+
multiLinguals[targetLang] = translatedText;
|
|
187
|
+
// Generate TTS audio if not cached
|
|
188
|
+
if (!fs.existsSync(targetAudioPath)) {
|
|
189
|
+
console.log(` Generating ${targetLang} audio...`);
|
|
190
|
+
await textToSpeech(translatedText, targetAudioPath, targetLang, openai);
|
|
191
|
+
}
|
|
192
|
+
audioSources[targetLang] = targetAudioFile;
|
|
193
|
+
}
|
|
194
|
+
bundleBeats.push({
|
|
195
|
+
text: beat.text,
|
|
196
|
+
audioSources,
|
|
197
|
+
multiLinguals,
|
|
198
|
+
videoSource: beat.videoSource,
|
|
199
|
+
thumbnail: beat.imageSource,
|
|
200
|
+
startTime: beat.startTime,
|
|
201
|
+
endTime: beat.endTime,
|
|
202
|
+
duration: beat.duration,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
const mulmoView = {
|
|
206
|
+
lang: sourceLang,
|
|
207
|
+
totalDuration,
|
|
208
|
+
totalSegments: beats.length,
|
|
209
|
+
beats: bundleBeats,
|
|
210
|
+
};
|
|
211
|
+
// Write mulmo_view.json
|
|
212
|
+
const viewPath = path.join(outputDir, "mulmo_view.json");
|
|
213
|
+
fs.writeFileSync(viewPath, JSON.stringify(mulmoView, null, 2));
|
|
214
|
+
console.log(`\nBundle saved to: ${viewPath}`);
|
|
215
|
+
return mulmoView;
|
|
216
|
+
}
|
|
217
|
+
//# sourceMappingURL=movie_bundle.js.map
|