Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | #!/usr/bin/env tsx /** * Generate audio clips from the audio manifest using OpenAI's TTS API. * * Usage: OPENAI_API_KEY=sk-... npx tsx scripts/generateAudioClips.ts [--voice <voice>] * * Options: * --voice <voice> OpenAI TTS voice name (default: 'nova') * * Idempotent: skips clips that already exist in data/audio/{voice}/ */ import { existsSync, mkdirSync, writeFileSync } from 'fs' import { join } from 'path' import OpenAI from 'openai' import { AUDIO_MANIFEST } from '../src/lib/audio/audioManifest' function parseArgs(): { voice: string } { const args = process.argv.slice(2) let voice = 'nova' for (let i = 0; i < args.length; i++) { if (args[i] === '--voice' && args[i + 1]) { voice = args[i + 1] i++ } } return { voice } } async function main() { const { voice } = parseArgs() const apiKey = process.env.OPENAI_API_KEY if (!apiKey) { console.error('Error: OPENAI_API_KEY environment variable is required') process.exit(1) } const client = new OpenAI({ apiKey }) const outputDir = join(__dirname, '..', 'data', 'audio', voice) mkdirSync(outputDir, { recursive: true }) console.log(`Voice: ${voice}`) console.log(`Output: ${outputDir}`) let generated = 0 let skipped = 0 for (const clip of AUDIO_MANIFEST) { const outputPath = join(outputDir, clip.filename) if (existsSync(outputPath)) { skipped++ continue } console.log(`Generating: ${clip.id} ("${clip.text}")`) try { const response = await client.audio.speech.create({ model: 'tts-1', voice: voice as 'nova' | 'shimmer' | 'alloy' | 'echo' | 'fable' | 'onyx', input: clip.text, response_format: 'mp3', }) const buffer = Buffer.from(await response.arrayBuffer()) writeFileSync(outputPath, buffer) generated++ } catch (error) { console.error(`Failed to generate ${clip.id}:`, error) process.exit(1) } } console.log(`\nDone! Generated: ${generated}, Skipped (existing): ${skipped}`) console.log(`Total clips in manifest: ${AUDIO_MANIFEST.length}`) console.log(`Output directory: ${outputDir}`) } main() |