this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at main 60 lines 2.1 kB view raw
1/** 2 * Audio file utilities: voice IDs, filename conventions, and file listing. 3 */ 4 5import { join } from '@std/path' 6import { Locale } from '$/enums.ts' 7 8/** Azure Neural TTS voice ID used per locale. */ 9export const VOICE_IDS: Record<Locale, string> = { 10 [Locale.zh_CN]: 'zh-CN-XiaoxiaoNeural', 11 [Locale.zh_HK]: 'zh-HK-WanLungNeural', 12 [Locale.zh_TW]: 'zh-TW-YunJheNeural', 13 [Locale.ja]: 'ja-JP-NanamiNeural', 14} 15 16/** 17 * Returns the audio filename for a given subject id and locale. 18 * When col and reading are both provided, appends `_{col}_{reading}` to disambiguate 19 * subjects with multiple readings (e.g. polyphonic characters). 20 */ 21export function getFilename(id: string, locale: Locale, col?: string, reading?: string): string { 22 const base = `${id}_${locale.replace('_', '-')}_${VOICE_IDS[locale]}` 23 if (col && reading) return `${base}_${col}_${reading}.mp3` 24 return `${base}.mp3` 25} 26 27/** 28 * Parses an audio filename into its components. 29 * Handles both formats: 30 * {id}_{locale}_{voiceId}.mp3 31 * {id}_{locale}_{voiceId}_{col}_{reading}.mp3 32 * Returns null if the filename doesn't match. 33 */ 34export function parseAudioFilename( 35 filename: string, 36): { id: string; locale: string; voiceId: string; col?: string; reading?: string } | null { 37 const parts = filename.replace('.mp3', '').split('_') 38 if (parts.length < 3) return null 39 const [id, localeHyphen, voiceId, col, reading] = parts 40 const locale = localeHyphen.replace('-', '_') 41 return { id, locale, voiceId, col, reading } 42} 43 44/** 45 * Returns all existing audio filenames (not full paths) for the given locales. 46 * Skips locales whose audio directories don't exist yet (e.g. before first audio run). 47 */ 48export function listAudioFiles(locales: string[] = ['zh_CN', 'zh_HK', 'zh_TW', 'ja']): string[] { 49 return locales 50 .filter((locale) => locale !== 'tmp') 51 .flatMap((locale) => { 52 try { 53 return Array.from(Deno.readDirSync(join('www/static/gen/audio', locale))) 54 } catch { 55 return [] 56 } 57 }) 58 .filter(({ name }) => /.*\.mp3$/.test(name)) 59 .map((file) => file.name) 60}