@happyvertical/smrt-voice 0.35.0 → 0.35.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.
package/dist/index.d.ts CHANGED
@@ -230,7 +230,7 @@ export declare class VoiceProfile extends SmrtObject {
230
230
  * Provider-specific voice data (ID, embedding, etc.)
231
231
  * Stored after voice creation/cloning is complete
232
232
  */
233
- voiceData: Record<string, any> | null;
233
+ voiceData: Record<string, unknown> | null;
234
234
  /**
235
235
  * Default speech speed multiplier (0.5 - 2.0)
236
236
  * 1.0 = normal speed
@@ -311,7 +311,7 @@ export declare interface VoiceProfileOptions extends SmrtObjectOptions {
311
311
  * Provider-specific voice data (ID, embedding, etc.)
312
312
  * Stored after voice creation/cloning
313
313
  */
314
- voiceData?: Record<string, any> | null;
314
+ voiceData?: Record<string, unknown> | null;
315
315
  /**
316
316
  * Default speech speed multiplier
317
317
  * @default 1.0
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/__smrt-register__.ts","../src/voice-profile.ts","../src/voice-output.ts","../src/voice-sample.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt() decorator\n * in the package fires. Fixes issue #1132: in consumer runtimes (tsx, SvelteKit\n * SSR, plain `vite dev`) the decorator's synchronous manifest lookup previously\n * missed because no step populated the global manifest cache — classes got\n * registered with zero fields and `save()` / `toJSON()` silently dropped every\n * declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates manifests\n * via a different path. Only needs to succeed in the published dist output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// `new URL('./manifest.json', import.meta.url)` resolves at runtime to the\n// manifest sitting next to this module's compiled output. Vite warns at build\n// time that it cannot pre-resolve the URL; that is the intended behavior —\n// the URL must resolve to dist/manifest.json at runtime, not be inlined.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","/**\n * Voice Profile Model\n *\n * Manages voice profiles for AI-powered voice synthesis and cloning.\n * Supports voice design via natural language descriptions and voice\n * cloning from audio samples.\n */\n\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { crossPackageRef, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\n/**\n * Voice profile status\n */\nexport type VoiceProfileStatus = 'pending' | 'processing' | 'ready' | 'failed';\n\n/**\n * Voice gender classification\n */\nexport type VoiceGender = 'male' | 'female' | 'neutral';\n\n/**\n * Voice profile creation options\n */\nexport interface VoiceProfileOptions extends SmrtObjectOptions {\n /**\n * Human-readable name for the voice profile\n */\n name?: string;\n\n /**\n * Description of the voice characteristics\n */\n description?: string | null;\n\n /**\n * ISO language code (e.g., 'en-US', 'zh-CN')\n */\n language?: string;\n\n /**\n * Voice gender classification\n * @default 'neutral'\n */\n gender?: VoiceGender;\n\n /**\n * Natural language description for voice design\n * Used when creating a voice from scratch\n */\n designPrompt?: string | null;\n\n /**\n * Asset ID of the audio sample for voice cloning\n * Should be at least 3 seconds of clear speech\n */\n sampleAssetId?: string | null;\n\n /**\n * Provider-specific voice data (ID, embedding, etc.)\n * Stored after voice creation/cloning\n */\n voiceData?: Record<string, any> | null;\n\n /**\n * Default speech speed multiplier\n * @default 1.0\n */\n defaultSpeed?: number;\n\n /**\n * Default pitch adjustment in semitones\n * @default 0\n */\n defaultPitch?: number;\n\n /**\n * Voice profile status\n * @default 'pending'\n */\n status?: VoiceProfileStatus;\n\n /**\n * TTS provider that created this voice\n * @default 'qwen3-tts'\n */\n provider?: string;\n\n /**\n * Error message if status is 'failed'\n */\n errorMessage?: string | null;\n\n /**\n * Tenant ID for multi-tenant isolation\n * Null for global/default voices\n */\n tenantId?: string | null;\n}\n\n/**\n * Voice profile for AI-powered speech synthesis\n *\n * VoiceProfile represents a configured voice identity that can be used\n * for text-to-speech synthesis. Voices can be created through:\n * - Voice design: Natural language description of desired voice characteristics\n * - Voice cloning: 3+ second audio sample for voice replication\n *\n * @example\n * ```typescript\n * import { VoiceProfile } from '@happyvertical/smrt-voice';\n *\n * // Create a designed voice\n * const anchorVoice = new VoiceProfile({\n * name: 'News Anchor',\n * description: 'Professional news anchor voice with clear enunciation',\n * language: 'en-US',\n * gender: 'male',\n * designPrompt: 'Warm, authoritative male voice with slight gravitas, suitable for news broadcasts',\n * provider: 'qwen3-tts',\n * });\n *\n * // Create a cloned voice\n * const clonedVoice = new VoiceProfile({\n * name: 'Custom Voice',\n * description: 'Cloned from user sample',\n * language: 'en-US',\n * sampleAssetId: 'asset-123',\n * provider: 'qwen3-tts',\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: ['list', 'get', 'create', 'update', 'delete'],\n },\n mcp: {\n include: ['list', 'get'],\n },\n cli: true,\n})\nexport class VoiceProfile extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n * Nullable to support global/default voices\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Human-readable name for the voice profile\n */\n name: string = '';\n\n /**\n * Description of the voice characteristics\n */\n description: string | null = null;\n\n /**\n * ISO language code (e.g., 'en-US', 'zh-CN')\n */\n language: string = 'en-US';\n\n /**\n * Voice gender classification\n */\n gender: VoiceGender = 'neutral';\n\n /**\n * Natural language description for voice design\n * Used when creating a voice from scratch via AI\n */\n designPrompt: string | null = null;\n\n /**\n * Asset ID of the audio sample for voice cloning\n * Should be at least 3 seconds of clear speech\n */\n @crossPackageRef('@happyvertical/smrt-assets:Asset')\n sampleAssetId: string | null = null;\n\n /**\n * Provider-specific voice data (ID, embedding, etc.)\n * Stored after voice creation/cloning is complete\n */\n voiceData: Record<string, any> | null = null;\n\n /**\n * Default speech speed multiplier (0.5 - 2.0)\n * 1.0 = normal speed\n */\n defaultSpeed: number = 1.0;\n\n /**\n * Default pitch adjustment in semitones (-20 to 20)\n * 0 = no adjustment\n */\n defaultPitch: number = 0;\n\n /**\n * Voice profile status\n * - pending: Profile created but voice not yet generated\n * - processing: Voice generation/cloning in progress\n * - ready: Voice is ready for use\n * - failed: Voice generation failed\n */\n status: VoiceProfileStatus = 'pending';\n\n /**\n * TTS provider that created/manages this voice\n */\n provider: string = 'qwen3-tts';\n\n /**\n * Error message if status is 'failed'\n */\n errorMessage: string | null = null;\n\n constructor(options: VoiceProfileOptions = {}) {\n super(options);\n\n if (options.name !== undefined) this.name = options.name;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.language !== undefined) this.language = options.language;\n if (options.gender !== undefined) this.gender = options.gender;\n if (options.designPrompt !== undefined)\n this.designPrompt = options.designPrompt;\n if (options.sampleAssetId !== undefined)\n this.sampleAssetId = options.sampleAssetId;\n if (options.voiceData !== undefined) this.voiceData = options.voiceData;\n if (options.defaultSpeed !== undefined)\n this.defaultSpeed = options.defaultSpeed;\n if (options.defaultPitch !== undefined)\n this.defaultPitch = options.defaultPitch;\n if (options.status !== undefined) this.status = options.status;\n if (options.provider !== undefined) this.provider = options.provider;\n if (options.errorMessage !== undefined)\n this.errorMessage = options.errorMessage;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Check if this voice profile uses voice cloning\n */\n get isCloned(): boolean {\n return this.sampleAssetId !== null;\n }\n\n /**\n * Check if this voice profile uses voice design\n */\n get isDesigned(): boolean {\n return this.designPrompt !== null && !this.isCloned;\n }\n\n /**\n * Check if the voice is ready for use\n */\n get isReady(): boolean {\n return this.status === 'ready';\n }\n\n /**\n * Check if this is a global (default) voice\n */\n get isGlobal(): boolean {\n return this.tenantId === null;\n }\n}\n","/**\n * Voice Output Model\n *\n * Represents generated audio output from text-to-speech synthesis.\n * Extends Content to leverage content management features.\n */\n\nimport { Content, type ContentOptions } from '@happyvertical/smrt-content';\nimport { crossPackageRef, foreignKey, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped } from '@happyvertical/smrt-tenancy';\nimport { VoiceProfile } from './voice-profile.js';\n\n/**\n * Word timing information for lip-sync alignment\n */\nexport interface WordTiming {\n /**\n * The word\n */\n word: string;\n\n /**\n * Start time in seconds\n */\n start: number;\n\n /**\n * End time in seconds\n */\n end: number;\n}\n\n/**\n * Voice output metadata\n */\nexport interface VoiceOutputMetadata {\n /**\n * Sample rate in Hz\n */\n sampleRate?: number;\n\n /**\n * Audio format (e.g., 'wav', 'mp3', 'ogg')\n */\n format?: string;\n\n /**\n * Number of audio channels\n */\n channels?: number;\n\n /**\n * Bit depth (e.g., 16, 24, 32)\n */\n bitDepth?: number;\n\n /**\n * File size in bytes\n */\n fileSize?: number;\n\n /**\n * TTS provider used\n */\n provider?: string;\n\n /**\n * Model used for synthesis\n */\n model?: string;\n\n /**\n * Speech speed used (1.0 = normal)\n */\n speed?: number;\n\n /**\n * Pitch adjustment used (semitones)\n */\n pitch?: number;\n}\n\n/**\n * Voice output creation options\n */\nexport interface VoiceOutputOptions extends ContentOptions {\n /**\n * Voice profile used for synthesis\n */\n voiceProfileId?: string | null;\n\n /**\n * Original text that was synthesized\n */\n sourceText?: string;\n\n /**\n * Asset ID of the generated audio file\n */\n audioAssetId?: string | null;\n\n /**\n * Duration of the generated audio in seconds\n */\n duration?: number;\n\n /**\n * Word-level timing information for lip-sync\n */\n wordTimings?: WordTiming[] | null;\n\n /**\n * Audio metadata\n */\n audioMetadata?: VoiceOutputMetadata;\n}\n\n/**\n * Generated audio output from text-to-speech synthesis\n *\n * VoiceOutput extends Content to represent audio generated from\n * text using a VoiceProfile. It includes word-level timing information\n * for lip-sync alignment in video production.\n *\n * @example\n * ```typescript\n * import { VoiceOutput } from '@happyvertical/smrt-voice';\n *\n * const output = new VoiceOutput({\n * voiceProfileId: 'voice-123',\n * sourceText: 'Welcome to the evening news broadcast.',\n * audioAssetId: 'asset-789',\n * duration: 3.5,\n * wordTimings: [\n * { word: 'Welcome', start: 0.0, end: 0.4 },\n * { word: 'to', start: 0.4, end: 0.5 },\n * { word: 'the', start: 0.5, end: 0.6 },\n * { word: 'evening', start: 0.6, end: 1.0 },\n * { word: 'news', start: 1.0, end: 1.3 },\n * { word: 'broadcast', start: 1.3, end: 1.9 },\n * ],\n * audioMetadata: {\n * sampleRate: 48000,\n * format: 'wav',\n * channels: 1,\n * provider: 'qwen3-tts',\n * },\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: ['list', 'get', 'create', 'delete'],\n },\n mcp: {\n include: ['list', 'get'],\n },\n cli: true,\n})\nexport class VoiceOutput extends Content {\n /**\n * Voice profile used for synthesis\n */\n @foreignKey(() => VoiceProfile)\n voiceProfileId: string | null = null;\n\n /**\n * Original text that was synthesized\n */\n sourceText: string = '';\n\n /**\n * Asset ID of the generated audio file\n */\n @crossPackageRef('@happyvertical/smrt-assets:Asset')\n audioAssetId: string | null = null;\n\n /**\n * Duration of the generated audio in seconds\n */\n duration: number = 0;\n\n /**\n * Word-level timing information for lip-sync alignment\n */\n wordTimings: WordTiming[] | null = null;\n\n /**\n * Audio metadata (sample rate, format, etc.)\n */\n audioMetadata: VoiceOutputMetadata = {};\n\n constructor(options: VoiceOutputOptions = {}) {\n super({\n ...options,\n type: 'voice-output',\n });\n\n if (options.voiceProfileId !== undefined)\n this.voiceProfileId = options.voiceProfileId;\n if (options.sourceText !== undefined) this.sourceText = options.sourceText;\n if (options.audioAssetId !== undefined)\n this.audioAssetId = options.audioAssetId;\n if (options.duration !== undefined) this.duration = options.duration;\n if (options.wordTimings !== undefined)\n this.wordTimings = options.wordTimings;\n if (options.audioMetadata !== undefined)\n this.audioMetadata = options.audioMetadata;\n }\n\n /**\n * Get the word count of the source text\n */\n get wordCount(): number {\n return this.sourceText.split(/\\s+/).filter(Boolean).length;\n }\n\n /**\n * Get the average words per second rate\n */\n get wordsPerSecond(): number {\n if (this.duration === 0) return 0;\n return this.wordCount / this.duration;\n }\n\n /**\n * Check if word timing data is available for lip-sync\n */\n get hasWordTimings(): boolean {\n return this.wordTimings !== null && this.wordTimings.length > 0;\n }\n\n /**\n * Get the word at a specific timestamp\n */\n getWordAtTime(seconds: number): WordTiming | null {\n if (!this.wordTimings) return null;\n return (\n this.wordTimings.find((wt) => seconds >= wt.start && seconds < wt.end) ??\n null\n );\n }\n}\n","/**\n * Voice Sample Model\n *\n * Manages audio samples used for voice cloning.\n * Samples should be at least 3 seconds of clear speech.\n */\n\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { VoiceProfile } from './voice-profile.js';\n\n/**\n * Audio sample quality rating\n */\nexport type SampleQuality = 'low' | 'medium' | 'high';\n\n/**\n * Voice sample creation options\n */\nexport interface VoiceSampleOptions extends SmrtObjectOptions {\n /**\n * Voice profile this sample belongs to\n */\n voiceProfileId?: string | null;\n\n /**\n * Asset ID of the audio file\n */\n assetId?: string | null;\n\n /**\n * Sample duration in seconds\n */\n duration?: number;\n\n /**\n * Transcription of what was said in the sample\n */\n transcription?: string | null;\n\n /**\n * Quality rating based on audio analysis\n * @default 'medium'\n */\n quality?: SampleQuality;\n\n /**\n * Sample rate in Hz (e.g., 44100, 48000)\n */\n sampleRate?: number | null;\n\n /**\n * Number of audio channels (1 = mono, 2 = stereo)\n */\n channels?: number | null;\n\n /**\n * Audio format (e.g., 'wav', 'mp3', 'ogg')\n */\n format?: string | null;\n\n /**\n * Whether this is the primary sample for the voice profile\n * @default false\n */\n isPrimary?: boolean;\n\n /**\n * Tenant ID for multi-tenant isolation\n */\n tenantId?: string | null;\n}\n\n/**\n * Audio sample for voice cloning\n *\n * VoiceSample represents an audio recording used as source material\n * for voice cloning. For best results, samples should be:\n * - At least 3 seconds long\n * - Clear speech without background noise\n * - Single speaker only\n * - High quality (44.1kHz or higher)\n *\n * Multiple samples can be associated with a single VoiceProfile\n * to improve voice cloning quality.\n *\n * @example\n * ```typescript\n * import { VoiceSample } from '@happyvertical/smrt-voice';\n *\n * const sample = new VoiceSample({\n * voiceProfileId: 'voice-123',\n * assetId: 'asset-456',\n * duration: 5.2,\n * transcription: 'Hello, this is a test recording for voice cloning.',\n * quality: 'high',\n * sampleRate: 48000,\n * channels: 1,\n * format: 'wav',\n * isPrimary: true,\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: ['list', 'get', 'create', 'delete'],\n },\n mcp: {\n include: ['list', 'get'],\n },\n cli: true,\n})\nexport class VoiceSample extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Voice profile this sample belongs to\n */\n @foreignKey(() => VoiceProfile)\n voiceProfileId: string | null = null;\n\n /**\n * Asset ID of the audio file\n * References an Asset in smrt-assets\n */\n @crossPackageRef('@happyvertical/smrt-assets:Asset')\n assetId: string | null = null;\n\n /**\n * Sample duration in seconds\n */\n duration: number = 0;\n\n /**\n * Transcription of what was said in the sample\n * Used for alignment and quality verification\n */\n transcription: string | null = null;\n\n /**\n * Quality rating based on audio analysis\n * - low: Noisy or short samples\n * - medium: Acceptable quality\n * - high: Clear audio, good length\n */\n quality: SampleQuality = 'medium';\n\n /**\n * Sample rate in Hz\n */\n sampleRate: number | null = null;\n\n /**\n * Number of audio channels\n */\n channels: number | null = null;\n\n /**\n * Audio format\n */\n format: string | null = null;\n\n /**\n * Whether this is the primary sample for the voice profile\n */\n isPrimary: boolean = false;\n\n constructor(options: VoiceSampleOptions = {}) {\n super(options);\n\n if (options.voiceProfileId !== undefined)\n this.voiceProfileId = options.voiceProfileId;\n if (options.assetId !== undefined) this.assetId = options.assetId;\n if (options.duration !== undefined) this.duration = options.duration;\n if (options.transcription !== undefined)\n this.transcription = options.transcription;\n if (options.quality !== undefined) this.quality = options.quality;\n if (options.sampleRate !== undefined) this.sampleRate = options.sampleRate;\n if (options.channels !== undefined) this.channels = options.channels;\n if (options.format !== undefined) this.format = options.format;\n if (options.isPrimary !== undefined) this.isPrimary = options.isPrimary;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Check if sample meets minimum duration requirement (3 seconds)\n */\n get meetsMinDuration(): boolean {\n return this.duration >= 3;\n }\n\n /**\n * Check if sample is high quality and suitable for cloning\n */\n get isSuitableForCloning(): boolean {\n return this.meetsMinDuration && this.quality !== 'low';\n }\n}\n"],"names":["__decorateClass"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/__smrt-register__.ts","../src/voice-profile.ts","../src/voice-output.ts","../src/voice-sample.ts"],"sourcesContent":["/**\n * Self-registers this package's build-time manifest before any @smrt() decorator\n * in the package fires. Fixes issue #1132: in consumer runtimes (tsx, SvelteKit\n * SSR, plain `vite dev`) the decorator's synchronous manifest lookup previously\n * missed because no step populated the global manifest cache — classes got\n * registered with zero fields and `save()` / `toJSON()` silently dropped every\n * declared property.\n *\n * Import this module as the first statement in `src/index.ts` so its top-level\n * side effect runs ahead of any class module's @smrt() decorator.\n *\n * Silent no-op in dev/test, where the vitest plugin already populates manifests\n * via a different path. Only needs to succeed in the published dist output.\n *\n * @see https://github.com/happyvertical/smrt/issues/1132\n */\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n// `new URL('./manifest.json', import.meta.url)` resolves at runtime to the\n// manifest sitting next to this module's compiled output. Vite warns at build\n// time that it cannot pre-resolve the URL; that is the intended behavior —\n// the URL must resolve to dist/manifest.json at runtime, not be inlined.\nObjectRegistry.registerPackageManifest(\n new URL('./manifest.json', import.meta.url),\n);\n","/**\n * Voice Profile Model\n *\n * Manages voice profiles for AI-powered voice synthesis and cloning.\n * Supports voice design via natural language descriptions and voice\n * cloning from audio samples.\n */\n\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport { crossPackageRef, SmrtObject, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\n\n/**\n * Voice profile status\n */\nexport type VoiceProfileStatus = 'pending' | 'processing' | 'ready' | 'failed';\n\n/**\n * Voice gender classification\n */\nexport type VoiceGender = 'male' | 'female' | 'neutral';\n\n/**\n * Voice profile creation options\n */\nexport interface VoiceProfileOptions extends SmrtObjectOptions {\n /**\n * Human-readable name for the voice profile\n */\n name?: string;\n\n /**\n * Description of the voice characteristics\n */\n description?: string | null;\n\n /**\n * ISO language code (e.g., 'en-US', 'zh-CN')\n */\n language?: string;\n\n /**\n * Voice gender classification\n * @default 'neutral'\n */\n gender?: VoiceGender;\n\n /**\n * Natural language description for voice design\n * Used when creating a voice from scratch\n */\n designPrompt?: string | null;\n\n /**\n * Asset ID of the audio sample for voice cloning\n * Should be at least 3 seconds of clear speech\n */\n sampleAssetId?: string | null;\n\n /**\n * Provider-specific voice data (ID, embedding, etc.)\n * Stored after voice creation/cloning\n */\n voiceData?: Record<string, unknown> | null;\n\n /**\n * Default speech speed multiplier\n * @default 1.0\n */\n defaultSpeed?: number;\n\n /**\n * Default pitch adjustment in semitones\n * @default 0\n */\n defaultPitch?: number;\n\n /**\n * Voice profile status\n * @default 'pending'\n */\n status?: VoiceProfileStatus;\n\n /**\n * TTS provider that created this voice\n * @default 'qwen3-tts'\n */\n provider?: string;\n\n /**\n * Error message if status is 'failed'\n */\n errorMessage?: string | null;\n\n /**\n * Tenant ID for multi-tenant isolation\n * Null for global/default voices\n */\n tenantId?: string | null;\n}\n\n/**\n * Voice profile for AI-powered speech synthesis\n *\n * VoiceProfile represents a configured voice identity that can be used\n * for text-to-speech synthesis. Voices can be created through:\n * - Voice design: Natural language description of desired voice characteristics\n * - Voice cloning: 3+ second audio sample for voice replication\n *\n * @example\n * ```typescript\n * import { VoiceProfile } from '@happyvertical/smrt-voice';\n *\n * // Create a designed voice\n * const anchorVoice = new VoiceProfile({\n * name: 'News Anchor',\n * description: 'Professional news anchor voice with clear enunciation',\n * language: 'en-US',\n * gender: 'male',\n * designPrompt: 'Warm, authoritative male voice with slight gravitas, suitable for news broadcasts',\n * provider: 'qwen3-tts',\n * });\n *\n * // Create a cloned voice\n * const clonedVoice = new VoiceProfile({\n * name: 'Custom Voice',\n * description: 'Cloned from user sample',\n * language: 'en-US',\n * sampleAssetId: 'asset-123',\n * provider: 'qwen3-tts',\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: ['list', 'get', 'create', 'update', 'delete'],\n },\n mcp: {\n include: ['list', 'get'],\n },\n cli: true,\n})\nexport class VoiceProfile extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n * Nullable to support global/default voices\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Human-readable name for the voice profile\n */\n name: string = '';\n\n /**\n * Description of the voice characteristics\n */\n description: string | null = null;\n\n /**\n * ISO language code (e.g., 'en-US', 'zh-CN')\n */\n language: string = 'en-US';\n\n /**\n * Voice gender classification\n */\n gender: VoiceGender = 'neutral';\n\n /**\n * Natural language description for voice design\n * Used when creating a voice from scratch via AI\n */\n designPrompt: string | null = null;\n\n /**\n * Asset ID of the audio sample for voice cloning\n * Should be at least 3 seconds of clear speech\n */\n @crossPackageRef('@happyvertical/smrt-assets:Asset')\n sampleAssetId: string | null = null;\n\n /**\n * Provider-specific voice data (ID, embedding, etc.)\n * Stored after voice creation/cloning is complete\n */\n voiceData: Record<string, unknown> | null = null;\n\n /**\n * Default speech speed multiplier (0.5 - 2.0)\n * 1.0 = normal speed\n */\n defaultSpeed: number = 1.0;\n\n /**\n * Default pitch adjustment in semitones (-20 to 20)\n * 0 = no adjustment\n */\n defaultPitch: number = 0;\n\n /**\n * Voice profile status\n * - pending: Profile created but voice not yet generated\n * - processing: Voice generation/cloning in progress\n * - ready: Voice is ready for use\n * - failed: Voice generation failed\n */\n status: VoiceProfileStatus = 'pending';\n\n /**\n * TTS provider that created/manages this voice\n */\n provider: string = 'qwen3-tts';\n\n /**\n * Error message if status is 'failed'\n */\n errorMessage: string | null = null;\n\n constructor(options: VoiceProfileOptions = {}) {\n super(options);\n\n if (options.name !== undefined) this.name = options.name;\n if (options.description !== undefined)\n this.description = options.description;\n if (options.language !== undefined) this.language = options.language;\n if (options.gender !== undefined) this.gender = options.gender;\n if (options.designPrompt !== undefined)\n this.designPrompt = options.designPrompt;\n if (options.sampleAssetId !== undefined)\n this.sampleAssetId = options.sampleAssetId;\n if (options.voiceData !== undefined) this.voiceData = options.voiceData;\n if (options.defaultSpeed !== undefined)\n this.defaultSpeed = options.defaultSpeed;\n if (options.defaultPitch !== undefined)\n this.defaultPitch = options.defaultPitch;\n if (options.status !== undefined) this.status = options.status;\n if (options.provider !== undefined) this.provider = options.provider;\n if (options.errorMessage !== undefined)\n this.errorMessage = options.errorMessage;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Check if this voice profile uses voice cloning\n */\n get isCloned(): boolean {\n return this.sampleAssetId !== null;\n }\n\n /**\n * Check if this voice profile uses voice design\n */\n get isDesigned(): boolean {\n return this.designPrompt !== null && !this.isCloned;\n }\n\n /**\n * Check if the voice is ready for use\n */\n get isReady(): boolean {\n return this.status === 'ready';\n }\n\n /**\n * Check if this is a global (default) voice\n */\n get isGlobal(): boolean {\n return this.tenantId === null;\n }\n}\n","/**\n * Voice Output Model\n *\n * Represents generated audio output from text-to-speech synthesis.\n * Extends Content to leverage content management features.\n */\n\nimport { Content, type ContentOptions } from '@happyvertical/smrt-content';\nimport { crossPackageRef, foreignKey, smrt } from '@happyvertical/smrt-core';\nimport { TenantScoped } from '@happyvertical/smrt-tenancy';\nimport { VoiceProfile } from './voice-profile.js';\n\n/**\n * Word timing information for lip-sync alignment\n */\nexport interface WordTiming {\n /**\n * The word\n */\n word: string;\n\n /**\n * Start time in seconds\n */\n start: number;\n\n /**\n * End time in seconds\n */\n end: number;\n}\n\n/**\n * Voice output metadata\n */\nexport interface VoiceOutputMetadata {\n /**\n * Sample rate in Hz\n */\n sampleRate?: number;\n\n /**\n * Audio format (e.g., 'wav', 'mp3', 'ogg')\n */\n format?: string;\n\n /**\n * Number of audio channels\n */\n channels?: number;\n\n /**\n * Bit depth (e.g., 16, 24, 32)\n */\n bitDepth?: number;\n\n /**\n * File size in bytes\n */\n fileSize?: number;\n\n /**\n * TTS provider used\n */\n provider?: string;\n\n /**\n * Model used for synthesis\n */\n model?: string;\n\n /**\n * Speech speed used (1.0 = normal)\n */\n speed?: number;\n\n /**\n * Pitch adjustment used (semitones)\n */\n pitch?: number;\n}\n\n/**\n * Voice output creation options\n */\nexport interface VoiceOutputOptions extends ContentOptions {\n /**\n * Voice profile used for synthesis\n */\n voiceProfileId?: string | null;\n\n /**\n * Original text that was synthesized\n */\n sourceText?: string;\n\n /**\n * Asset ID of the generated audio file\n */\n audioAssetId?: string | null;\n\n /**\n * Duration of the generated audio in seconds\n */\n duration?: number;\n\n /**\n * Word-level timing information for lip-sync\n */\n wordTimings?: WordTiming[] | null;\n\n /**\n * Audio metadata\n */\n audioMetadata?: VoiceOutputMetadata;\n}\n\n/**\n * Generated audio output from text-to-speech synthesis\n *\n * VoiceOutput extends Content to represent audio generated from\n * text using a VoiceProfile. It includes word-level timing information\n * for lip-sync alignment in video production.\n *\n * @example\n * ```typescript\n * import { VoiceOutput } from '@happyvertical/smrt-voice';\n *\n * const output = new VoiceOutput({\n * voiceProfileId: 'voice-123',\n * sourceText: 'Welcome to the evening news broadcast.',\n * audioAssetId: 'asset-789',\n * duration: 3.5,\n * wordTimings: [\n * { word: 'Welcome', start: 0.0, end: 0.4 },\n * { word: 'to', start: 0.4, end: 0.5 },\n * { word: 'the', start: 0.5, end: 0.6 },\n * { word: 'evening', start: 0.6, end: 1.0 },\n * { word: 'news', start: 1.0, end: 1.3 },\n * { word: 'broadcast', start: 1.3, end: 1.9 },\n * ],\n * audioMetadata: {\n * sampleRate: 48000,\n * format: 'wav',\n * channels: 1,\n * provider: 'qwen3-tts',\n * },\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: ['list', 'get', 'create', 'delete'],\n },\n mcp: {\n include: ['list', 'get'],\n },\n cli: true,\n})\nexport class VoiceOutput extends Content {\n /**\n * Voice profile used for synthesis\n */\n @foreignKey(() => VoiceProfile)\n voiceProfileId: string | null = null;\n\n /**\n * Original text that was synthesized\n */\n sourceText: string = '';\n\n /**\n * Asset ID of the generated audio file\n */\n @crossPackageRef('@happyvertical/smrt-assets:Asset')\n audioAssetId: string | null = null;\n\n /**\n * Duration of the generated audio in seconds\n */\n duration: number = 0;\n\n /**\n * Word-level timing information for lip-sync alignment\n */\n wordTimings: WordTiming[] | null = null;\n\n /**\n * Audio metadata (sample rate, format, etc.)\n */\n audioMetadata: VoiceOutputMetadata = {};\n\n constructor(options: VoiceOutputOptions = {}) {\n super({\n ...options,\n type: 'voice-output',\n });\n\n if (options.voiceProfileId !== undefined)\n this.voiceProfileId = options.voiceProfileId;\n if (options.sourceText !== undefined) this.sourceText = options.sourceText;\n if (options.audioAssetId !== undefined)\n this.audioAssetId = options.audioAssetId;\n if (options.duration !== undefined) this.duration = options.duration;\n if (options.wordTimings !== undefined)\n this.wordTimings = options.wordTimings;\n if (options.audioMetadata !== undefined)\n this.audioMetadata = options.audioMetadata;\n }\n\n /**\n * Get the word count of the source text\n */\n get wordCount(): number {\n return this.sourceText.split(/\\s+/).filter(Boolean).length;\n }\n\n /**\n * Get the average words per second rate\n */\n get wordsPerSecond(): number {\n if (this.duration === 0) return 0;\n return this.wordCount / this.duration;\n }\n\n /**\n * Check if word timing data is available for lip-sync\n */\n get hasWordTimings(): boolean {\n return this.wordTimings !== null && this.wordTimings.length > 0;\n }\n\n /**\n * Get the word at a specific timestamp\n */\n getWordAtTime(seconds: number): WordTiming | null {\n if (!this.wordTimings) return null;\n return (\n this.wordTimings.find((wt) => seconds >= wt.start && seconds < wt.end) ??\n null\n );\n }\n}\n","/**\n * Voice Sample Model\n *\n * Manages audio samples used for voice cloning.\n * Samples should be at least 3 seconds of clear speech.\n */\n\nimport type { SmrtObjectOptions } from '@happyvertical/smrt-core';\nimport {\n crossPackageRef,\n foreignKey,\n SmrtObject,\n smrt,\n} from '@happyvertical/smrt-core';\nimport { TenantScoped, tenantId } from '@happyvertical/smrt-tenancy';\nimport { VoiceProfile } from './voice-profile.js';\n\n/**\n * Audio sample quality rating\n */\nexport type SampleQuality = 'low' | 'medium' | 'high';\n\n/**\n * Voice sample creation options\n */\nexport interface VoiceSampleOptions extends SmrtObjectOptions {\n /**\n * Voice profile this sample belongs to\n */\n voiceProfileId?: string | null;\n\n /**\n * Asset ID of the audio file\n */\n assetId?: string | null;\n\n /**\n * Sample duration in seconds\n */\n duration?: number;\n\n /**\n * Transcription of what was said in the sample\n */\n transcription?: string | null;\n\n /**\n * Quality rating based on audio analysis\n * @default 'medium'\n */\n quality?: SampleQuality;\n\n /**\n * Sample rate in Hz (e.g., 44100, 48000)\n */\n sampleRate?: number | null;\n\n /**\n * Number of audio channels (1 = mono, 2 = stereo)\n */\n channels?: number | null;\n\n /**\n * Audio format (e.g., 'wav', 'mp3', 'ogg')\n */\n format?: string | null;\n\n /**\n * Whether this is the primary sample for the voice profile\n * @default false\n */\n isPrimary?: boolean;\n\n /**\n * Tenant ID for multi-tenant isolation\n */\n tenantId?: string | null;\n}\n\n/**\n * Audio sample for voice cloning\n *\n * VoiceSample represents an audio recording used as source material\n * for voice cloning. For best results, samples should be:\n * - At least 3 seconds long\n * - Clear speech without background noise\n * - Single speaker only\n * - High quality (44.1kHz or higher)\n *\n * Multiple samples can be associated with a single VoiceProfile\n * to improve voice cloning quality.\n *\n * @example\n * ```typescript\n * import { VoiceSample } from '@happyvertical/smrt-voice';\n *\n * const sample = new VoiceSample({\n * voiceProfileId: 'voice-123',\n * assetId: 'asset-456',\n * duration: 5.2,\n * transcription: 'Hello, this is a test recording for voice cloning.',\n * quality: 'high',\n * sampleRate: 48000,\n * channels: 1,\n * format: 'wav',\n * isPrimary: true,\n * });\n * ```\n */\n@TenantScoped({ mode: 'optional' })\n@smrt({\n tableStrategy: 'sti',\n api: {\n include: ['list', 'get', 'create', 'delete'],\n },\n mcp: {\n include: ['list', 'get'],\n },\n cli: true,\n})\nexport class VoiceSample extends SmrtObject {\n /**\n * Tenant ID for multi-tenant isolation\n */\n @tenantId({ nullable: true })\n tenantId: string | null = null;\n\n /**\n * Voice profile this sample belongs to\n */\n @foreignKey(() => VoiceProfile)\n voiceProfileId: string | null = null;\n\n /**\n * Asset ID of the audio file\n * References an Asset in smrt-assets\n */\n @crossPackageRef('@happyvertical/smrt-assets:Asset')\n assetId: string | null = null;\n\n /**\n * Sample duration in seconds\n */\n duration: number = 0;\n\n /**\n * Transcription of what was said in the sample\n * Used for alignment and quality verification\n */\n transcription: string | null = null;\n\n /**\n * Quality rating based on audio analysis\n * - low: Noisy or short samples\n * - medium: Acceptable quality\n * - high: Clear audio, good length\n */\n quality: SampleQuality = 'medium';\n\n /**\n * Sample rate in Hz\n */\n sampleRate: number | null = null;\n\n /**\n * Number of audio channels\n */\n channels: number | null = null;\n\n /**\n * Audio format\n */\n format: string | null = null;\n\n /**\n * Whether this is the primary sample for the voice profile\n */\n isPrimary: boolean = false;\n\n constructor(options: VoiceSampleOptions = {}) {\n super(options);\n\n if (options.voiceProfileId !== undefined)\n this.voiceProfileId = options.voiceProfileId;\n if (options.assetId !== undefined) this.assetId = options.assetId;\n if (options.duration !== undefined) this.duration = options.duration;\n if (options.transcription !== undefined)\n this.transcription = options.transcription;\n if (options.quality !== undefined) this.quality = options.quality;\n if (options.sampleRate !== undefined) this.sampleRate = options.sampleRate;\n if (options.channels !== undefined) this.channels = options.channels;\n if (options.format !== undefined) this.format = options.format;\n if (options.isPrimary !== undefined) this.isPrimary = options.isPrimary;\n if (options.tenantId !== undefined) this.tenantId = options.tenantId;\n }\n\n /**\n * Check if sample meets minimum duration requirement (3 seconds)\n */\n get meetsMinDuration(): boolean {\n return this.duration >= 3;\n }\n\n /**\n * Check if sample is high quality and suitable for cloning\n */\n get isSuitableForCloning(): boolean {\n return this.meetsMinDuration && this.quality !== 'low';\n }\n}\n"],"names":["__decorateClass"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "version": "1.0.0",
3
- "timestamp": 1782330667619,
3
+ "timestamp": 1782335314362,
4
4
  "packageName": "@happyvertical/smrt-voice",
5
- "packageVersion": "0.35.0",
5
+ "packageVersion": "0.35.1",
6
6
  "objects": {
7
7
  "@happyvertical/smrt-voice:VoiceOutput": {
8
8
  "name": "voiceoutput",
@@ -1,13 +1,13 @@
1
1
  {
2
2
  "schemaVersion": 1,
3
- "generatedAt": "2026-06-24T19:51:08.853Z",
3
+ "generatedAt": "2026-06-24T21:08:35.803Z",
4
4
  "packageName": "@happyvertical/smrt-voice",
5
- "packageVersion": "0.35.0",
5
+ "packageVersion": "0.35.1",
6
6
  "sourceManifestPath": "dist/manifest.json",
7
7
  "agentDocPath": "AGENTS.md",
8
8
  "sourceHashes": {
9
- "manifest": "48a06bcc6f709a4b26e113613b771fc2e05e633878b072de06deefc6f9ee8208",
10
- "packageJson": "c661643ce170805cb900c278e936973398cf44dbfd0f28044b2a4b8f88d41893",
9
+ "manifest": "2ba573e75d67a746ab1834fce55eee0b25a3036f47b16c11354726902f3408db",
10
+ "packageJson": "39f2d784f6b1e8a5630acb39d5460149983b3e29a1af4661f61fd29efe4e3c79",
11
11
  "agents": "49a29e74f9bd018c1141f0d39468ad71d91d4ba078e2e82e828b7bf5a8f775e9"
12
12
  },
13
13
  "exports": [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happyvertical/smrt-voice",
3
- "version": "0.35.0",
3
+ "version": "0.35.1",
4
4
  "type": "module",
5
5
  "description": "Voice profile management for AI-powered voice synthesis and cloning in the SMRT ecosystem",
6
6
  "author": "HappyVertical",
@@ -30,11 +30,11 @@
30
30
  ],
31
31
  "dependencies": {
32
32
  "@happyvertical/utils": "^0.74.7",
33
- "@happyvertical/smrt-assets": "0.35.0",
34
- "@happyvertical/smrt-config": "0.35.0",
35
- "@happyvertical/smrt-content": "0.35.0",
36
- "@happyvertical/smrt-core": "0.35.0",
37
- "@happyvertical/smrt-tenancy": "0.35.0"
33
+ "@happyvertical/smrt-assets": "0.35.1",
34
+ "@happyvertical/smrt-config": "0.35.1",
35
+ "@happyvertical/smrt-content": "0.35.1",
36
+ "@happyvertical/smrt-core": "0.35.1",
37
+ "@happyvertical/smrt-tenancy": "0.35.1"
38
38
  },
39
39
  "devDependencies": {
40
40
  "@happyvertical/logger": "^0.74.7",
@@ -43,7 +43,7 @@
43
43
  "typescript": "^5.9.3",
44
44
  "vite": "^7.3.1",
45
45
  "vitest": "^4.0.17",
46
- "@happyvertical/smrt-vitest": "0.35.0"
46
+ "@happyvertical/smrt-vitest": "0.35.1"
47
47
  },
48
48
  "keywords": [
49
49
  "voice",