UNPKG

@yuchida-tamu/podcast-gen

Version:

AI-Powered Monologue Podcast Generator

84 lines 3.5 kB
import fs from 'fs-extra'; import OpenAI from 'openai'; import path from 'path'; import { AudioDataTransformer } from './audio/dataTransformer.js'; import { AudioSynthesizer } from './audio/synthesizer.js'; import { OpenAIService } from './llm/OpenAIService.js'; import { MonologueEngine } from './monologue/engine.js'; import { ScriptFormatter } from './script/formatter.js'; import { handleError, validateApiKey, validateDuration, validateTopic, } from './utils/errors.js'; import { showError, showFileOutput, showProgress, showStep, showSuccess, } from './utils/progress.js'; // Default dependencies const defaultDependencies = { fs, path, MonologueEngine, ScriptFormatter, AudioSynthesizer, AudioDataTransformer, validateTopic, validateDuration, validateApiKey, handleError, showProgress, showStep, showSuccess, showError, showFileOutput, }; export async function generatePodcast(topic, options, deps = defaultDependencies) { const duration = parseInt(options.duration); const outputDir = deps.path.resolve(options.output); // Validation deps.validateTopic(topic); deps.validateDuration(duration); deps.validateApiKey(); deps.showProgress(`Generating podcast on: '${topic}'`); // Ensure output directory exists await deps.fs.ensureDir(outputDir); // Initialize engines const openaiClient = new OpenAI({ apiKey: process.env.OPENAI_API_KEY }); const llmService = new OpenAIService(openaiClient); const monologueEngine = new deps.MonologueEngine(llmService); const scriptFormatter = new deps.ScriptFormatter(); const audioSynthesizer = new deps.AudioSynthesizer(openaiClient); const audioDataTransformer = new deps.AudioDataTransformer(); let jsonPath = options.script; let filename = ''; if (jsonPath === '') { // Step 1: Generate monologue deps.showStep(1, 5, 'Analyzing topic...'); const segments = await monologueEngine.generateMonologue(topic, duration); // Step 2: Format script deps.showStep(2, 5, 'Creating narrative content...'); const jsonScript = await scriptFormatter.formatScript(segments, topic); // Step 3: Save script file deps.showStep(3, 5, 'Formatting script...'); filename = scriptFormatter.generateFilename(topic); jsonPath = deps.path.join(outputDir, `${filename}.json`); await deps.fs.writeFile(jsonPath, jsonScript); } // Step 4: Generate audio deps.showStep(4, 5, 'Synthesizing voice...'); const audioPath = deps.path.join(outputDir, `${filename}.mp3`); const segmentFiles = await audioSynthesizer.synthesizeAudio(jsonPath, audioPath); // Step 5: Concatenate audio segments deps.showStep(5, 5, 'Combining audio segments...'); try { await audioDataTransformer.concatenate(segmentFiles, audioPath); deps.showSuccess('Audio segments successfully concatenated!'); } catch (error) { deps.handleError(new Error(`Failed to concatenate audio segments: ${error}`)); } // Success deps.showSuccess('Podcast generated successfully!'); deps.showFileOutput('script', jsonPath); // Show final concatenated audio file deps.showFileOutput('audio', audioPath); // Show all generated audio segment files segmentFiles.forEach((segmentPath, index) => { deps.showFileOutput(`audio segment ${index + 1}`, segmentPath); }); } //# sourceMappingURL=orchestrator.js.map