@aituber-onair/core 0.1.0

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.
Files changed (104) hide show
  1. package/README.md +723 -0
  2. package/dist/constants/api.d.ts +4 -0
  3. package/dist/constants/api.js +13 -0
  4. package/dist/constants/api.js.map +1 -0
  5. package/dist/constants/index.d.ts +23 -0
  6. package/dist/constants/index.js +25 -0
  7. package/dist/constants/index.js.map +1 -0
  8. package/dist/constants/openaiApi.d.ts +15 -0
  9. package/dist/constants/openaiApi.js +15 -0
  10. package/dist/constants/openaiApi.js.map +1 -0
  11. package/dist/constants/prompts.d.ts +2 -0
  12. package/dist/constants/prompts.js +13 -0
  13. package/dist/constants/prompts.js.map +1 -0
  14. package/dist/core/AITuberOnAirCore.d.ts +142 -0
  15. package/dist/core/AITuberOnAirCore.js +316 -0
  16. package/dist/core/AITuberOnAirCore.js.map +1 -0
  17. package/dist/core/ChatProcessor.d.ts +86 -0
  18. package/dist/core/ChatProcessor.js +246 -0
  19. package/dist/core/ChatProcessor.js.map +1 -0
  20. package/dist/core/EventEmitter.d.ts +35 -0
  21. package/dist/core/EventEmitter.js +72 -0
  22. package/dist/core/EventEmitter.js.map +1 -0
  23. package/dist/core/MemoryManager.d.ts +98 -0
  24. package/dist/core/MemoryManager.js +208 -0
  25. package/dist/core/MemoryManager.js.map +1 -0
  26. package/dist/index.d.ts +24 -0
  27. package/dist/index.js +22 -0
  28. package/dist/index.js.map +1 -0
  29. package/dist/services/chat/ChatService.d.ts +21 -0
  30. package/dist/services/chat/ChatService.js +2 -0
  31. package/dist/services/chat/ChatService.js.map +1 -0
  32. package/dist/services/chat/ChatServiceFactory.d.ts +38 -0
  33. package/dist/services/chat/ChatServiceFactory.js +55 -0
  34. package/dist/services/chat/ChatServiceFactory.js.map +1 -0
  35. package/dist/services/chat/OpenAIChatService.d.ts +38 -0
  36. package/dist/services/chat/OpenAIChatService.js +166 -0
  37. package/dist/services/chat/OpenAIChatService.js.map +1 -0
  38. package/dist/services/chat/OpenAISummarizer.d.ts +25 -0
  39. package/dist/services/chat/OpenAISummarizer.js +70 -0
  40. package/dist/services/chat/OpenAISummarizer.js.map +1 -0
  41. package/dist/services/chat/providers/ChatServiceProvider.d.ts +44 -0
  42. package/dist/services/chat/providers/ChatServiceProvider.js +2 -0
  43. package/dist/services/chat/providers/ChatServiceProvider.js.map +1 -0
  44. package/dist/services/chat/providers/OpenAIChatServiceProvider.d.ts +33 -0
  45. package/dist/services/chat/providers/OpenAIChatServiceProvider.js +44 -0
  46. package/dist/services/chat/providers/OpenAIChatServiceProvider.js.map +1 -0
  47. package/dist/services/voice/VoiceEngineAdapter.d.ts +46 -0
  48. package/dist/services/voice/VoiceEngineAdapter.js +173 -0
  49. package/dist/services/voice/VoiceEngineAdapter.js.map +1 -0
  50. package/dist/services/voice/VoiceService.d.ts +55 -0
  51. package/dist/services/voice/VoiceService.js +2 -0
  52. package/dist/services/voice/VoiceService.js.map +1 -0
  53. package/dist/services/voice/engines/AivisSpeechEngine.d.ts +10 -0
  54. package/dist/services/voice/engines/AivisSpeechEngine.js +70 -0
  55. package/dist/services/voice/engines/AivisSpeechEngine.js.map +1 -0
  56. package/dist/services/voice/engines/NijiVoiceEngine.d.ts +12 -0
  57. package/dist/services/voice/engines/NijiVoiceEngine.js +105 -0
  58. package/dist/services/voice/engines/NijiVoiceEngine.js.map +1 -0
  59. package/dist/services/voice/engines/OpenAiEngine.d.ts +9 -0
  60. package/dist/services/voice/engines/OpenAiEngine.js +34 -0
  61. package/dist/services/voice/engines/OpenAiEngine.js.map +1 -0
  62. package/dist/services/voice/engines/VoiceEngine.d.ts +21 -0
  63. package/dist/services/voice/engines/VoiceEngine.js +2 -0
  64. package/dist/services/voice/engines/VoiceEngine.js.map +1 -0
  65. package/dist/services/voice/engines/VoiceEngineFactory.d.ts +14 -0
  66. package/dist/services/voice/engines/VoiceEngineFactory.js +34 -0
  67. package/dist/services/voice/engines/VoiceEngineFactory.js.map +1 -0
  68. package/dist/services/voice/engines/VoicePeakEngine.d.ts +13 -0
  69. package/dist/services/voice/engines/VoicePeakEngine.js +46 -0
  70. package/dist/services/voice/engines/VoicePeakEngine.js.map +1 -0
  71. package/dist/services/voice/engines/VoiceVoxEngine.d.ts +13 -0
  72. package/dist/services/voice/engines/VoiceVoxEngine.js +67 -0
  73. package/dist/services/voice/engines/VoiceVoxEngine.js.map +1 -0
  74. package/dist/services/voice/engines/index.d.ts +7 -0
  75. package/dist/services/voice/engines/index.js +7 -0
  76. package/dist/services/voice/engines/index.js.map +1 -0
  77. package/dist/services/voice/messages.d.ts +38 -0
  78. package/dist/services/voice/messages.js +49 -0
  79. package/dist/services/voice/messages.js.map +1 -0
  80. package/dist/services/youtube/YouTubeDataApiService.d.ts +69 -0
  81. package/dist/services/youtube/YouTubeDataApiService.js +255 -0
  82. package/dist/services/youtube/YouTubeDataApiService.js.map +1 -0
  83. package/dist/services/youtube/YouTubeService.d.ts +63 -0
  84. package/dist/services/youtube/YouTubeService.js +2 -0
  85. package/dist/services/youtube/YouTubeService.js.map +1 -0
  86. package/dist/types/index.d.ts +82 -0
  87. package/dist/types/index.js +5 -0
  88. package/dist/types/index.js.map +1 -0
  89. package/dist/types/nijiVoice.d.ts +27 -0
  90. package/dist/types/nijiVoice.js +2 -0
  91. package/dist/types/nijiVoice.js.map +1 -0
  92. package/dist/utils/index.d.ts +5 -0
  93. package/dist/utils/index.js +6 -0
  94. package/dist/utils/index.js.map +1 -0
  95. package/dist/utils/screenplay.d.ts +19 -0
  96. package/dist/utils/screenplay.js +42 -0
  97. package/dist/utils/screenplay.js.map +1 -0
  98. package/dist/utils/screenshot.d.ts +19 -0
  99. package/dist/utils/screenshot.js +44 -0
  100. package/dist/utils/screenshot.js.map +1 -0
  101. package/dist/utils/storage.d.ts +44 -0
  102. package/dist/utils/storage.js +103 -0
  103. package/dist/utils/storage.js.map +1 -0
  104. package/package.json +33 -0
@@ -0,0 +1,105 @@
1
+ import { NIJI_VOICE_API_URL } from '../../../constants';
2
+ /**
3
+ * NijiVoice voice synthesis engine
4
+ */
5
+ export class NijiVoiceEngine {
6
+ async fetchAudio(input, speaker, apiKey, voiceActor) {
7
+ if (!apiKey) {
8
+ throw new Error('NijiVoice API key is required');
9
+ }
10
+ const talk = input;
11
+ const script = talk.message.trim();
12
+ // get emotion from talk.style and process parameters
13
+ const emotion = talk.style || 'neutral';
14
+ const emotionParams = this.processEmotionParams(emotion, script, voiceActor);
15
+ const generateResponse = await fetch(`${NIJI_VOICE_API_URL}/voice-actors/${speaker}/generate-encoded-voice`, {
16
+ method: 'POST',
17
+ headers: {
18
+ 'x-api-key': apiKey,
19
+ 'Content-Type': 'application/json',
20
+ accept: 'application/json',
21
+ },
22
+ body: JSON.stringify({
23
+ script: emotionParams.script,
24
+ speed: emotionParams.speed,
25
+ emotionalLevel: emotionParams.emotionalLevel,
26
+ format: 'mp3',
27
+ }),
28
+ });
29
+ if (!generateResponse.ok) {
30
+ const errorBody = await generateResponse.text();
31
+ console.error('NijiVoice generate-encoded-voice error:', errorBody);
32
+ throw new Error('Failed to generate voice from NijiVoice');
33
+ }
34
+ const generateResult = (await generateResponse.json());
35
+ const base64Audio = generateResult.generatedVoice?.base64Audio;
36
+ if (!base64Audio) {
37
+ throw new Error('Base64 audio not found in NijiVoice response');
38
+ }
39
+ return this.base64ToArrayBuffer(base64Audio);
40
+ }
41
+ processEmotionParams(emotion, script, voiceActor) {
42
+ // set default values
43
+ const defaultEmotionalLevel = 0.7; // default emotional level
44
+ const defaultSpeed = 1.0; // default speed
45
+ let emotionalLevel;
46
+ // if voiceActor does not exist, use default values
47
+ let speed = voiceActor?.recommendedVoiceSpeed
48
+ ? String(voiceActor.recommendedVoiceSpeed)
49
+ : String(defaultSpeed);
50
+ // base emotional level (use voiceActor's recommendedEmotionalLevel or default values)
51
+ const baseEmotionalLevel = voiceActor?.recommendedEmotionalLevel
52
+ ? Number(voiceActor.recommendedEmotionalLevel)
53
+ : defaultEmotionalLevel;
54
+ // base speed (use voiceActor's recommendedVoiceSpeed or default values)
55
+ let baseSpeed = voiceActor?.recommendedVoiceSpeed
56
+ ? Number(voiceActor.recommendedVoiceSpeed)
57
+ : defaultSpeed;
58
+ // adjust according to emotion
59
+ let adjustment = '0.0';
60
+ switch (emotion.toLowerCase()) {
61
+ case 'happy':
62
+ adjustment = '0.2';
63
+ baseSpeed *= 1.1;
64
+ break;
65
+ case 'sad':
66
+ adjustment = '-0.4';
67
+ baseSpeed *= 0.9;
68
+ break;
69
+ case 'angry':
70
+ adjustment = '0.4';
71
+ baseSpeed *= 1.0;
72
+ break;
73
+ case 'surprised':
74
+ adjustment = '0.3';
75
+ baseSpeed *= 1.2;
76
+ break;
77
+ default:
78
+ // if default, set emotional level
79
+ emotionalLevel = String(baseEmotionalLevel);
80
+ break;
81
+ }
82
+ if (adjustment !== '0.0') {
83
+ emotionalLevel = (Math.round(Math.min(Math.max(baseEmotionalLevel + Number(adjustment), 0), 1.5) *
84
+ 10) / 10).toString();
85
+ }
86
+ // ensure speed is always between 0.4 and 3.0
87
+ speed = (Math.round(Math.min(Math.max(baseSpeed, 0.4), 3.0) * 10) / 10).toString();
88
+ return { script, emotionalLevel, speed };
89
+ }
90
+ base64ToArrayBuffer(base64) {
91
+ const sanitizedBase64 = base64.replace(/[\r\n\s]/g, '');
92
+ const binaryString = atob(sanitizedBase64);
93
+ const len = binaryString.length;
94
+ const buffer = new ArrayBuffer(len);
95
+ const view = new Uint8Array(buffer);
96
+ for (let i = 0; i < len; i++) {
97
+ view[i] = binaryString.charCodeAt(i);
98
+ }
99
+ return buffer;
100
+ }
101
+ getTestMessage(textVoiceText) {
102
+ return textVoiceText || 'にじボイスを使用します';
103
+ }
104
+ }
105
+ //# sourceMappingURL=NijiVoiceEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NijiVoiceEngine.js","sourceRoot":"","sources":["../../../../src/services/voice/engines/NijiVoiceEngine.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { Talk } from '../messages';
2
+ import { VoiceEngine } from './VoiceEngine';
3
+ /**
4
+ * OpenAI TTS voice synthesis engine
5
+ */
6
+ export declare class OpenAiEngine implements VoiceEngine {
7
+ fetchAudio(input: Talk, speaker: string, apiKey?: string): Promise<ArrayBuffer>;
8
+ getTestMessage(textVoiceText?: string): string;
9
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * OpenAI TTS voice synthesis engine
3
+ */
4
+ export class OpenAiEngine {
5
+ async fetchAudio(input, speaker, apiKey) {
6
+ if (!apiKey) {
7
+ throw new Error('OpenAI API key is required');
8
+ }
9
+ const talk = input;
10
+ const text = talk.message.trim();
11
+ const response = await fetch('https://api.openai.com/v1/audio/speech', {
12
+ method: 'POST',
13
+ headers: {
14
+ 'Content-Type': 'application/json',
15
+ Authorization: `Bearer ${apiKey}`,
16
+ },
17
+ body: JSON.stringify({
18
+ model: 'tts-1',
19
+ voice: speaker,
20
+ input: text,
21
+ }),
22
+ });
23
+ if (!response.ok) {
24
+ console.error('Failed to fetch TTS from OpenAI TTS:', response.status);
25
+ throw new Error('Failed to fetch TTS from OpenAI TTS.');
26
+ }
27
+ const blob = await response.blob();
28
+ return await blob.arrayBuffer();
29
+ }
30
+ getTestMessage(textVoiceText) {
31
+ return textVoiceText || 'OpenAI TTSを使用します';
32
+ }
33
+ }
34
+ //# sourceMappingURL=OpenAiEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OpenAiEngine.js","sourceRoot":"","sources":["../../../../src/services/voice/engines/OpenAiEngine.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,MAAM,OAAO,YAAY;IACvB,KAAK,CAAC,UAAU,CACd,KAAW,EACX,OAAe,EACf,MAAe;QAEf,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,IAAI,GAAG,KAAa,CAAC;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC;QAEjC,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,wCAAwC,EAAE;YACrE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,aAAa,EAAE,UAAU,MAAM,EAAE;aAClC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,KAAK,EAAE,OAAO;gBACd,KAAK,EAAE,OAAO;gBACd,KAAK,EAAE,IAAI;aACZ,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO,CAAC,KAAK,CAAC,sCAAsC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;YACvE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QAC1D,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACnC,OAAO,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;IAClC,CAAC;IAED,cAAc,CAAC,aAAsB;QACnC,OAAO,aAAa,IAAI,kBAAkB,CAAC;IAC7C,CAAC;CACF"}
@@ -0,0 +1,21 @@
1
+ import { Talk } from '../messages';
2
+ import { VoiceActor } from '../../../types/nijiVoice';
3
+ /**
4
+ * Common interface for voice engines
5
+ */
6
+ export interface VoiceEngine {
7
+ /**
8
+ * Get voice data
9
+ * @param input script
10
+ * @param speaker speaker ID
11
+ * @param apiKey API key (if needed)
12
+ * @param voiceActor voice actor information (for NijiVoice)
13
+ * @returns ArrayBuffer of voice data
14
+ */
15
+ fetchAudio(input: Talk, speaker: string, apiKey?: string, voiceActor?: VoiceActor): Promise<ArrayBuffer>;
16
+ /**
17
+ * Get a test message
18
+ * @returns test message
19
+ */
20
+ getTestMessage(textVoiceText?: string): string;
21
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=VoiceEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceEngine.js","sourceRoot":"","sources":["../../../../src/services/voice/engines/VoiceEngine.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ import { VoiceEngine } from './VoiceEngine';
2
+ /**
3
+ * Voice engine factory
4
+ * Generate appropriate voice engine instances based on voice engine type
5
+ */
6
+ export declare class VoiceEngineFactory {
7
+ /**
8
+ * Get the voice engine for the specified engine type
9
+ * @param engineType string of engine type ('voicevox', 'voicepeak', etc.)
10
+ * @returns voice engine instance
11
+ * @throws error if engine type is unknown
12
+ */
13
+ static getEngine(engineType: string): VoiceEngine;
14
+ }
@@ -0,0 +1,34 @@
1
+ import { VoiceVoxEngine } from './VoiceVoxEngine';
2
+ import { VoicePeakEngine } from './VoicePeakEngine';
3
+ import { AivisSpeechEngine } from './AivisSpeechEngine';
4
+ import { OpenAiEngine } from './OpenAiEngine';
5
+ import { NijiVoiceEngine } from './NijiVoiceEngine';
6
+ /**
7
+ * Voice engine factory
8
+ * Generate appropriate voice engine instances based on voice engine type
9
+ */
10
+ export class VoiceEngineFactory {
11
+ /**
12
+ * Get the voice engine for the specified engine type
13
+ * @param engineType string of engine type ('voicevox', 'voicepeak', etc.)
14
+ * @returns voice engine instance
15
+ * @throws error if engine type is unknown
16
+ */
17
+ static getEngine(engineType) {
18
+ switch (engineType) {
19
+ case 'voicevox':
20
+ return new VoiceVoxEngine();
21
+ case 'voicepeak':
22
+ return new VoicePeakEngine();
23
+ case 'aivisSpeech':
24
+ return new AivisSpeechEngine();
25
+ case 'openai':
26
+ return new OpenAiEngine();
27
+ case 'nijivoice':
28
+ return new NijiVoiceEngine();
29
+ default:
30
+ throw new Error(`Unsupported voice engine type: ${engineType}`);
31
+ }
32
+ }
33
+ }
34
+ //# sourceMappingURL=VoiceEngineFactory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceEngineFactory.js","sourceRoot":"","sources":["../../../../src/services/voice/engines/VoiceEngineFactory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAEpD;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IAC7B;;;;;OAKG;IACH,MAAM,CAAC,SAAS,CAAC,UAAkB;QACjC,QAAQ,UAAU,EAAE,CAAC;YACnB,KAAK,UAAU;gBACb,OAAO,IAAI,cAAc,EAAE,CAAC;YAC9B,KAAK,WAAW;gBACd,OAAO,IAAI,eAAe,EAAE,CAAC;YAC/B,KAAK,aAAa;gBAChB,OAAO,IAAI,iBAAiB,EAAE,CAAC;YACjC,KAAK,QAAQ;gBACX,OAAO,IAAI,YAAY,EAAE,CAAC;YAC5B,KAAK,WAAW;gBACd,OAAO,IAAI,eAAe,EAAE,CAAC;YAC/B;gBACE,MAAM,IAAI,KAAK,CAAC,kCAAkC,UAAU,EAAE,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ import { Talk } from '../messages';
2
+ import { VoiceEngine } from './VoiceEngine';
3
+ /**
4
+ * VoicePeak voice synthesis engine
5
+ */
6
+ export declare class VoicePeakEngine implements VoiceEngine {
7
+ fetchAudio(input: Talk, speaker: string): Promise<ArrayBuffer>;
8
+ /**
9
+ * Map emotion style to VoicePeak's emotion parameters
10
+ */
11
+ private mapEmotionStyle;
12
+ getTestMessage(textVoiceText?: string): string;
13
+ }
@@ -0,0 +1,46 @@
1
+ import { VOICEPEAK_API_URL } from '../../../constants';
2
+ /**
3
+ * VoicePeak voice synthesis engine
4
+ */
5
+ export class VoicePeakEngine {
6
+ async fetchAudio(input, speaker) {
7
+ const talk = input;
8
+ const ttsQueryResponse = await fetch(`${VOICEPEAK_API_URL}/audio_query?speaker=${speaker}&text=${encodeURIComponent(talk.message)}`, { method: 'POST' });
9
+ if (!ttsQueryResponse.ok) {
10
+ throw new Error('Failed to fetch TTS query.');
11
+ }
12
+ const ttsQueryJson = await ttsQueryResponse.json();
13
+ // set emotion from talk.style
14
+ ttsQueryJson['emotion'] = this.mapEmotionStyle(talk.style || 'neutral');
15
+ const synthesisResponse = await fetch(`${VOICEPEAK_API_URL}/synthesis?speaker=${speaker}`, {
16
+ method: 'POST',
17
+ headers: { 'Content-Type': 'application/json' },
18
+ body: JSON.stringify(ttsQueryJson),
19
+ });
20
+ if (!synthesisResponse.ok) {
21
+ throw new Error('Failed to fetch TTS synthesis result.');
22
+ }
23
+ const blob = await synthesisResponse.blob();
24
+ return await blob.arrayBuffer();
25
+ }
26
+ /**
27
+ * Map emotion style to VoicePeak's emotion parameters
28
+ */
29
+ mapEmotionStyle(style) {
30
+ switch (style.toLowerCase()) {
31
+ case 'happy':
32
+ case 'fun':
33
+ return 'happy';
34
+ case 'angry':
35
+ return 'angry';
36
+ case 'sad':
37
+ return 'sad';
38
+ default:
39
+ return 'neutral';
40
+ }
41
+ }
42
+ getTestMessage(textVoiceText) {
43
+ return textVoiceText || 'ボイスピークを使用します';
44
+ }
45
+ }
46
+ //# sourceMappingURL=VoicePeakEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoicePeakEngine.js","sourceRoot":"","sources":["../../../../src/services/voice/engines/VoicePeakEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAIvD;;GAEG;AACH,MAAM,OAAO,eAAe;IAC1B,KAAK,CAAC,UAAU,CAAC,KAAW,EAAE,OAAe;QAC3C,MAAM,IAAI,GAAG,KAAa,CAAC;QAE3B,MAAM,gBAAgB,GAAG,MAAM,KAAK,CAClC,GAAG,iBAAiB,wBAAwB,OAAO,SAAS,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,EAC9F,EAAE,MAAM,EAAE,MAAM,EAAE,CACnB,CAAC;QAEF,IAAI,CAAC,gBAAgB,CAAC,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,CAAC;QAEnD,8BAA8B;QAC9B,YAAY,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC,CAAC;QAExE,MAAM,iBAAiB,GAAG,MAAM,KAAK,CACnC,GAAG,iBAAiB,sBAAsB,OAAO,EAAE,EACnD;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;SACnC,CACF,CAAC;QAEF,IAAI,CAAC,iBAAiB,CAAC,EAAE,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,CAAC;QAC5C,OAAO,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;IAClC,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,KAAa;QACnC,QAAQ,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YAC5B,KAAK,OAAO,CAAC;YACb,KAAK,KAAK;gBACR,OAAO,OAAO,CAAC;YACjB,KAAK,OAAO;gBACV,OAAO,OAAO,CAAC;YACjB,KAAK,KAAK;gBACR,OAAO,KAAK,CAAC;YACf;gBACE,OAAO,SAAS,CAAC;QACrB,CAAC;IACH,CAAC;IAED,cAAc,CAAC,aAAsB;QACnC,OAAO,aAAa,IAAI,cAAc,CAAC;IACzC,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ import { Talk } from '../messages';
2
+ import { VoiceEngine } from './VoiceEngine';
3
+ /**
4
+ * VoiceVox voice synthesis engine
5
+ */
6
+ export declare class VoiceVoxEngine implements VoiceEngine {
7
+ fetchAudio(input: Talk, speaker: string): Promise<ArrayBuffer>;
8
+ /**
9
+ * Adjust parameters according to emotion
10
+ */
11
+ private adjustEmotionParameters;
12
+ getTestMessage(textVoiceText?: string): string;
13
+ }
@@ -0,0 +1,67 @@
1
+ import { VOICE_VOX_API_URL } from '../../../constants';
2
+ /**
3
+ * VoiceVox voice synthesis engine
4
+ */
5
+ export class VoiceVoxEngine {
6
+ async fetchAudio(input, speaker) {
7
+ const talk = input;
8
+ // get emotion from talk.style
9
+ const emotion = talk.style || 'neutral';
10
+ const ttsQueryResponse = await fetch(`${VOICE_VOX_API_URL}/audio_query?speaker=${speaker}&text=${encodeURIComponent(talk.message)}`, { method: 'POST' });
11
+ if (!ttsQueryResponse.ok) {
12
+ throw new Error('Failed to fetch TTS query.');
13
+ }
14
+ const ttsQueryJson = await ttsQueryResponse.json();
15
+ // adjust parameters according to emotion
16
+ this.adjustEmotionParameters(ttsQueryJson, emotion);
17
+ const synthesisResponse = await fetch(`${VOICE_VOX_API_URL}/synthesis?speaker=${speaker}`, {
18
+ method: 'POST',
19
+ headers: {
20
+ 'Content-Type': 'application/json',
21
+ 'Transfer-Encoding': 'chunked',
22
+ },
23
+ body: JSON.stringify(ttsQueryJson),
24
+ });
25
+ if (!synthesisResponse.ok) {
26
+ throw new Error('Failed to fetch TTS synthesis result.');
27
+ }
28
+ const blob = await synthesisResponse.blob();
29
+ return await blob.arrayBuffer();
30
+ }
31
+ /**
32
+ * Adjust parameters according to emotion
33
+ */
34
+ adjustEmotionParameters(ttsQueryJson, emotion) {
35
+ // default values
36
+ ttsQueryJson.speedScale = 1.16;
37
+ ttsQueryJson.pitchScale = -0.02;
38
+ ttsQueryJson.intonationScale = 1.26;
39
+ switch (emotion.toLowerCase()) {
40
+ case 'happy':
41
+ ttsQueryJson.speedScale = 1.25;
42
+ ttsQueryJson.pitchScale = 0.05;
43
+ ttsQueryJson.intonationScale = 1.4;
44
+ break;
45
+ case 'sad':
46
+ ttsQueryJson.speedScale = 1.0;
47
+ ttsQueryJson.pitchScale = -0.1;
48
+ ttsQueryJson.intonationScale = 1.0;
49
+ break;
50
+ case 'angry':
51
+ ttsQueryJson.speedScale = 1.2;
52
+ ttsQueryJson.pitchScale = -0.05;
53
+ ttsQueryJson.intonationScale = 1.5;
54
+ break;
55
+ case 'surprised':
56
+ ttsQueryJson.speedScale = 1.3;
57
+ ttsQueryJson.pitchScale = 0.1;
58
+ ttsQueryJson.intonationScale = 1.4;
59
+ break;
60
+ // default: "neutral" etc. other than default values
61
+ }
62
+ }
63
+ getTestMessage(textVoiceText) {
64
+ return textVoiceText || 'ボイスボックスを使用します';
65
+ }
66
+ }
67
+ //# sourceMappingURL=VoiceVoxEngine.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"VoiceVoxEngine.js","sourceRoot":"","sources":["../../../../src/services/voice/engines/VoiceVoxEngine.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAIvD;;GAEG;AACH,MAAM,OAAO,cAAc;IACzB,KAAK,CAAC,UAAU,CAAC,KAAW,EAAE,OAAe;QAC3C,MAAM,IAAI,GAAG,KAAa,CAAC;QAC3B,8BAA8B;QAC9B,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC;QAExC,MAAM,gBAAgB,GAAG,MAAM,KAAK,CAClC,GAAG,iBAAiB,wBAAwB,OAAO,SAAS,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,EAC9F,EAAE,MAAM,EAAE,MAAM,EAAE,CACnB,CAAC;QAEF,IAAI,CAAC,gBAAgB,CAAC,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;QAChD,CAAC;QAED,MAAM,YAAY,GAAG,MAAM,gBAAgB,CAAC,IAAI,EAAE,CAAC;QACnD,yCAAyC;QACzC,IAAI,CAAC,uBAAuB,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAEpD,MAAM,iBAAiB,GAAG,MAAM,KAAK,CACnC,GAAG,iBAAiB,sBAAsB,OAAO,EAAE,EACnD;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,mBAAmB,EAAE,SAAS;aAC/B;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC;SACnC,CACF,CAAC;QAEF,IAAI,CAAC,iBAAiB,CAAC,EAAE,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QAED,MAAM,IAAI,GAAG,MAAM,iBAAiB,CAAC,IAAI,EAAE,CAAC;QAC5C,OAAO,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;IAClC,CAAC;IAED;;OAEG;IACK,uBAAuB,CAAC,YAAiB,EAAE,OAAe;QAChE,iBAAiB;QACjB,YAAY,CAAC,UAAU,GAAG,IAAI,CAAC;QAC/B,YAAY,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC;QAChC,YAAY,CAAC,eAAe,GAAG,IAAI,CAAC;QAEpC,QAAQ,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC;YAC9B,KAAK,OAAO;gBACV,YAAY,CAAC,UAAU,GAAG,IAAI,CAAC;gBAC/B,YAAY,CAAC,UAAU,GAAG,IAAI,CAAC;gBAC/B,YAAY,CAAC,eAAe,GAAG,GAAG,CAAC;gBACnC,MAAM;YACR,KAAK,KAAK;gBACR,YAAY,CAAC,UAAU,GAAG,GAAG,CAAC;gBAC9B,YAAY,CAAC,UAAU,GAAG,CAAC,GAAG,CAAC;gBAC/B,YAAY,CAAC,eAAe,GAAG,GAAG,CAAC;gBACnC,MAAM;YACR,KAAK,OAAO;gBACV,YAAY,CAAC,UAAU,GAAG,GAAG,CAAC;gBAC9B,YAAY,CAAC,UAAU,GAAG,CAAC,IAAI,CAAC;gBAChC,YAAY,CAAC,eAAe,GAAG,GAAG,CAAC;gBACnC,MAAM;YACR,KAAK,WAAW;gBACd,YAAY,CAAC,UAAU,GAAG,GAAG,CAAC;gBAC9B,YAAY,CAAC,UAAU,GAAG,GAAG,CAAC;gBAC9B,YAAY,CAAC,eAAe,GAAG,GAAG,CAAC;gBACnC,MAAM;YACR,oDAAoD;QACtD,CAAC;IACH,CAAC;IAED,cAAc,CAAC,aAAsB;QACnC,OAAO,aAAa,IAAI,eAAe,CAAC;IAC1C,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ export type { VoiceEngine } from './VoiceEngine';
2
+ export { VoiceEngineFactory } from './VoiceEngineFactory';
3
+ export { VoiceVoxEngine } from './VoiceVoxEngine';
4
+ export { VoicePeakEngine } from './VoicePeakEngine';
5
+ export { AivisSpeechEngine } from './AivisSpeechEngine';
6
+ export { OpenAiEngine } from './OpenAiEngine';
7
+ export { NijiVoiceEngine } from './NijiVoiceEngine';
@@ -0,0 +1,7 @@
1
+ export { VoiceEngineFactory } from './VoiceEngineFactory';
2
+ export { VoiceVoxEngine } from './VoiceVoxEngine';
3
+ export { VoicePeakEngine } from './VoicePeakEngine';
4
+ export { AivisSpeechEngine } from './AivisSpeechEngine';
5
+ export { OpenAiEngine } from './OpenAiEngine';
6
+ export { NijiVoiceEngine } from './NijiVoiceEngine';
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/services/voice/engines/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,38 @@
1
+ import { VRMExpressionPresetName } from '@pixiv/three-vrm';
2
+ export type Message = {
3
+ role: 'assistant' | 'system' | 'user';
4
+ content: string;
5
+ timestamp?: number;
6
+ };
7
+ type VisionBlock = {
8
+ type: 'text';
9
+ text: string;
10
+ } | {
11
+ type: 'image_url';
12
+ image_url: {
13
+ url: string;
14
+ detail?: 'low' | 'high' | 'auto';
15
+ };
16
+ };
17
+ export type MessageWithVision = {
18
+ role: 'assistant' | 'system' | 'user';
19
+ content: string | VisionBlock[];
20
+ };
21
+ declare const talkStyles: readonly ["talk", "happy", "sad", "angry", "fear", "surprised"];
22
+ export type TalkStyle = (typeof talkStyles)[number];
23
+ export type Talk = {
24
+ style: TalkStyle;
25
+ message: string;
26
+ };
27
+ declare const emotions: readonly ["neutral", "happy", "angry", "sad", "relaxed"];
28
+ export type EmotionType = (typeof emotions)[number] & VRMExpressionPresetName;
29
+ /**
30
+ * Set of talk text and emotion, and model's emotion expression
31
+ */
32
+ export type Screenplay = {
33
+ expression: EmotionType;
34
+ talk: Talk;
35
+ };
36
+ export declare const splitSentence: (text: string) => string[];
37
+ export declare const textsToScreenplay: (texts: string[]) => Screenplay[];
38
+ export {};
@@ -0,0 +1,49 @@
1
+ const talkStyles = [
2
+ 'talk',
3
+ 'happy',
4
+ 'sad',
5
+ 'angry',
6
+ 'fear',
7
+ 'surprised',
8
+ ];
9
+ const emotions = ['neutral', 'happy', 'angry', 'sad', 'relaxed'];
10
+ export const splitSentence = (text) => {
11
+ const splitMessages = text.split(/(?<=[。.!?\n])/g);
12
+ return splitMessages.filter((msg) => msg !== '');
13
+ };
14
+ export const textsToScreenplay = (texts) => {
15
+ const screenplays = [];
16
+ let prevExpression = 'neutral';
17
+ for (let i = 0; i < texts.length; i++) {
18
+ const text = texts[i];
19
+ const match = text.match(/\[(.*?)\]/);
20
+ const tag = (match && match[1]) || prevExpression;
21
+ const message = text.replace(/\[(.*?)\]/g, '');
22
+ let expression = prevExpression;
23
+ if (emotions.includes(tag)) {
24
+ expression = tag;
25
+ prevExpression = tag;
26
+ }
27
+ screenplays.push({
28
+ expression: expression,
29
+ talk: {
30
+ style: emotionToTalkStyle(expression),
31
+ message: message,
32
+ },
33
+ });
34
+ }
35
+ return screenplays;
36
+ };
37
+ const emotionToTalkStyle = (emotion) => {
38
+ switch (emotion) {
39
+ case 'angry':
40
+ return 'angry';
41
+ case 'happy':
42
+ return 'happy';
43
+ case 'sad':
44
+ return 'sad';
45
+ default:
46
+ return 'talk';
47
+ }
48
+ };
49
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../../../src/services/voice/messages.ts"],"names":[],"mappings":"AAyBA,MAAM,UAAU,GAAG;IACjB,MAAM;IACN,OAAO;IACP,KAAK;IACL,OAAO;IACP,MAAM;IACN,WAAW;CACH,CAAC;AAQX,MAAM,QAAQ,GAAG,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,CAAU,CAAC;AAY1E,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,IAAY,EAAY,EAAE;IACtD,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC;IACnD,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC;AACnD,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,KAAe,EAAgB,EAAE;IACjE,MAAM,WAAW,GAAiB,EAAE,CAAC;IACrC,IAAI,cAAc,GAAG,SAAS,CAAC;IAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAEtB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAEtC,MAAM,GAAG,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,cAAc,CAAC;QAElD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;QAE/C,IAAI,UAAU,GAAG,cAAc,CAAC;QAChC,IAAI,QAAQ,CAAC,QAAQ,CAAC,GAAU,CAAC,EAAE,CAAC;YAClC,UAAU,GAAG,GAAG,CAAC;YACjB,cAAc,GAAG,GAAG,CAAC;QACvB,CAAC;QAED,WAAW,CAAC,IAAI,CAAC;YACf,UAAU,EAAE,UAAyB;YACrC,IAAI,EAAE;gBACJ,KAAK,EAAE,kBAAkB,CAAC,UAAyB,CAAC;gBACpD,OAAO,EAAE,OAAO;aACjB;SACF,CAAC,CAAC;IACL,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,OAAoB,EAAa,EAAE;IAC7D,QAAQ,OAAO,EAAE,CAAC;QAChB,KAAK,OAAO;YACV,OAAO,OAAO,CAAC;QACjB,KAAK,OAAO;YACV,OAAO,OAAO,CAAC;QACjB,KAAK,KAAK;YACR,OAAO,KAAK,CAAC;QACf;YACE,OAAO,MAAM,CAAC;IAClB,CAAC;AACH,CAAC,CAAC"}
@@ -0,0 +1,69 @@
1
+ import { EventEmitter } from '../../core/EventEmitter';
2
+ import { YouTubeService, YouTubeServiceOptions, YouTubeComment } from './YouTubeService';
3
+ /**
4
+ * YouTube Data API implementation using YouTube service
5
+ */
6
+ export declare class YouTubeDataApiService extends EventEmitter implements YouTubeService {
7
+ private options;
8
+ private isWatchingLive;
9
+ private watchingIntervalId;
10
+ private nextPageToken;
11
+ private currentLiveId;
12
+ /**
13
+ * Constructor
14
+ * @param options Service settings options
15
+ */
16
+ constructor(options: YouTubeServiceOptions);
17
+ /**
18
+ * Start watching live comments
19
+ * @param liveId Live ID
20
+ */
21
+ startWatching(liveId: string): Promise<void>;
22
+ /**
23
+ * Stop watching live comments
24
+ */
25
+ stopWatching(): void;
26
+ /**
27
+ * Return whether currently fetching
28
+ */
29
+ isWatching(): boolean;
30
+ /**
31
+ * Set comment fetch interval
32
+ * @param interval Interval in milliseconds
33
+ */
34
+ setFetchInterval(interval: number): void;
35
+ /**
36
+ * Set comment selection strategy
37
+ * @param strategy Selection strategy ('random' or 'latest')
38
+ */
39
+ setSelectionStrategy(strategy: 'random' | 'latest'): void;
40
+ /**
41
+ * Fetch latest comments (for manual retrieval)
42
+ * @param liveId Live ID
43
+ * @returns Comments array
44
+ */
45
+ fetchLatestComments(liveId: string): Promise<YouTubeComment[]>;
46
+ /**
47
+ * Subscribe to comment reception event
48
+ * @param callback Callback when comment is received
49
+ */
50
+ onComment(callback: (comment: YouTubeComment) => void): void;
51
+ /**
52
+ * Get live chat ID
53
+ * @param liveId Live ID
54
+ * @returns Live chat ID
55
+ */
56
+ private getLiveChatId;
57
+ /**
58
+ * Fetch live comments
59
+ * @param liveChatId Live chat ID
60
+ * @param usePageToken Whether to use page token
61
+ * @returns Comments array
62
+ */
63
+ private retrieveLiveComments;
64
+ /**
65
+ * Fetch and process comments
66
+ * @param liveChatId Live chat ID
67
+ */
68
+ private fetchAndProcessComments;
69
+ }