@@ -14,7 +14,7 @@ import * as fs from "fs";
14
14
import { Buffer } from "buffer" ;
15
15
import * as path from "path" ;
16
16
import * as process from "process" ;
17
- import { detect } from 'langdetect' ;
17
+ import { detect } from 'langdetect' ;
18
18
19
19
const generateTTS = async ( prompt : string , voice : string , runtime : IAgentRuntime ) => {
20
20
process . env [ "FAL_KEY" ] =
@@ -27,26 +27,24 @@ const generateTTS = async (prompt: string, voice: string, runtime: IAgentRuntime
27
27
input : {
28
28
input : prompt ,
29
29
voice : voice
30
- } ,
30
+ } ,
31
31
logs : true ,
32
32
onQueueUpdate : ( update ) => {
33
33
if ( update . status === "IN_PROGRESS" ) {
34
34
update . logs
35
35
. map ( ( log ) => log . message )
36
- . forEach ( elizaLogger . log ) ;
36
+ . forEach ( elizaLogger . debug ) ;
37
37
}
38
38
} ,
39
39
} ) ;
40
40
41
- elizaLogger . log (
41
+ elizaLogger . debug (
42
42
"Generation request successful, received response:" ,
43
43
response
44
44
) ;
45
45
46
- return { success : true ,
47
- data : response . data } ;
48
- }
49
- catch ( error ) {
46
+ return { success : true , data : response . data } ;
47
+ } catch ( error ) {
50
48
elizaLogger . error ( "TTS generation error:" , error ) ;
51
49
return {
52
50
success : false ,
@@ -67,9 +65,9 @@ const TTSGeneration: Action = {
67
65
] ,
68
66
description : "Generate a tts audio based on a text prompt" ,
69
67
validate : async ( runtime : IAgentRuntime , _message : Memory ) => {
70
- elizaLogger . log ( "Validating TTS action" ) ;
68
+ elizaLogger . debug ( "Validating TTS action" ) ;
71
69
const FalApiKey = runtime . getSetting ( "FAL_API_KEY" ) ;
72
- elizaLogger . log ( "FAL_API_KEY present:" , ! ! FalApiKey ) ;
70
+ elizaLogger . debug ( "FAL_API_KEY present:" , ! ! FalApiKey ) ;
73
71
return ! ! FalApiKey ;
74
72
} ,
75
73
handler : async (
@@ -79,120 +77,98 @@ const TTSGeneration: Action = {
79
77
_options : any ,
80
78
callback : HandlerCallback
81
79
) => {
82
- elizaLogger . log ( "TTS request:" , message ) ;
83
-
80
+ elizaLogger . debug ( "TTS request:" , message ) ;
84
81
// Clean up the prompt by removing mentions and commands
85
82
const TTSPrompt = message . content . text
86
83
. replace ( / < @ \d + > / g, "" ) // Remove mentions
87
- . replace ( / g e n e r a t e T T S | c r e a t e T T S | m a k e T T S | r e n d e r T T S / gi, "" ) // Remove commands
84
+ . replace ( / g e n e r a t e T T S | c r e a t e T T S | m a k e T T S | r e n d e r T T S / gi, "" )
88
85
. trim ( ) ;
89
86
90
87
if ( ! TTSPrompt || TTSPrompt . length < 3 ) {
91
- callback ( {
92
- text : "Please input a word at least of length 3" ,
93
- } ) ;
88
+ callback ( { text : "Please input a word at least of length 3" } ) ;
94
89
return ;
95
90
}
96
91
97
- elizaLogger . log ( "TTS prompt:" , TTSPrompt ) ;
92
+ elizaLogger . debug ( "TTS prompt:" , TTSPrompt ) ;
98
93
99
94
callback ( {
100
- text : `I'll generate a audio based on your prompt: "${ TTSPrompt } ". This might take a few seconds...` ,
95
+ text : `I'll generate an audio based on your prompt: "${ TTSPrompt } ". This might take a few seconds...` ,
101
96
} ) ;
102
97
103
- const language = detect ( TTSPrompt ) ;
104
- const voice_subject = VOICE_MAP [ language [ 0 ] . lang ] ;
105
- const target_voice = getRandomVoice ( voice_subject ) . fullName ;
98
+ let target_voice ;
99
+ try {
100
+ const language = detect ( TTSPrompt ) ;
101
+ if ( language && language . length > 0 ) {
102
+ const voice_subject = VOICE_MAP [ language [ 0 ] . lang ] ;
103
+ target_voice = getRandomVoice ( voice_subject ) . fullName ;
104
+ } else {
105
+ throw new Error ( "Language detection failed, no language detected." ) ;
106
+ }
107
+ } catch ( error ) {
108
+ elizaLogger . error ( "Language detection error:" , error ) ;
109
+ const defaultVoice = VOICE_MAP [ 'en' ] ;
110
+ target_voice = getRandomVoice ( defaultVoice ) . fullName ;
111
+ }
106
112
107
- elizaLogger . log ( "Starting TTS generation with prompt:" , prompt , "and voice:" , target_voice ) ;
113
+ elizaLogger . debug ( "Starting TTS generation with prompt:" , TTSPrompt , "and voice:" , target_voice ) ;
108
114
109
115
try {
110
116
const result = await generateTTS ( TTSPrompt , target_voice , runtime ) ;
111
117
112
118
if ( result . success && result . data . audio . url ) {
113
- // Download the Audio file
114
- const response = await fetch ( result . data . audio . url ) ;
115
- const arrayBuffer = await response . arrayBuffer ( ) ;
116
- const TTSFileName = `content_cache/tts_${ result . data . audio . file_name } ` ;
117
-
118
- // ensure the directory is existed
119
- const directoryPath = path . dirname ( TTSFileName ) ;
120
- if ( ! fs . existsSync ( directoryPath ) ) {
121
- fs . mkdirSync ( directoryPath , { recursive : true } ) ;
119
+ const cachedFile = `content_cache/tts_${ result . data . audio . file_name } ` ;
120
+ if ( fs . existsSync ( cachedFile ) ) {
121
+ elizaLogger . debug ( "Using cached audio:" , cachedFile ) ;
122
+ } else {
123
+ const response = await fetch ( result . data . audio . url ) ;
124
+ const arrayBuffer = await response . arrayBuffer ( ) ;
125
+
126
+ const directoryPath = path . dirname ( cachedFile ) ;
127
+ if ( ! fs . existsSync ( directoryPath ) ) {
128
+ fs . mkdirSync ( directoryPath , { recursive : true } ) ;
129
+ }
130
+
131
+ fs . writeFileSync ( cachedFile , Buffer . from ( arrayBuffer ) ) ;
132
+ elizaLogger . debug ( "Audio Duration:" , result . data . audio . duration ) ;
122
133
}
123
134
124
- // Save Audio file
125
- fs . writeFileSync ( TTSFileName , Buffer . from ( arrayBuffer ) ) ;
126
-
127
- elizaLogger . log ( "Audio Duration:" , result . data . audio . duration ) ;
128
- callback (
129
- {
130
- text : "TTS Success! Here's your generated audio!" ,
131
- attachments : [
132
- {
133
- id : crypto . randomUUID ( ) ,
134
- url : result . data . audio . url ,
135
- title : "TTS Generation" ,
136
- source : "TTSGeneration" ,
137
- description : TTSPrompt ,
138
- text : TTSPrompt ,
139
- } ,
140
- ] ,
141
- } ,
142
- [ TTSFileName ]
143
- ) ; // Add the audio file to the attachments
144
- } else {
145
135
callback ( {
146
- text : `TTS generation failed: ${ result . error } ` ,
147
- error : true ,
148
- } ) ;
136
+ text : "TTS Success! Here's your generated audio!" ,
137
+ attachments : [
138
+ {
139
+ id : crypto . randomUUID ( ) ,
140
+ url : result . data . audio . url ,
141
+ title : "TTS Generation" ,
142
+ source : "TTSGeneration" ,
143
+ description : TTSPrompt ,
144
+ text : TTSPrompt ,
145
+ } ,
146
+ ] ,
147
+ } , [ cachedFile ] ) ;
148
+ } else {
149
+ callback ( { text : `TTS generation failed: ${ result . error } ` , error : true } ) ;
149
150
}
150
151
} catch ( error ) {
151
152
elizaLogger . error ( `Failed to generate TTS. Error: ${ error } ` ) ;
152
- callback ( {
153
- text : `TTS generation failed: ${ error . message } ` ,
154
- error : true ,
155
- } ) ;
153
+ callback ( { text : `TTS generation failed: ${ error . message } ` , error : true } ) ;
156
154
}
157
155
} ,
158
156
examples : [
159
157
[
160
- {
161
- user : "{{user1}}" ,
162
- content : {
163
- text : "Generate a TTS of prompt: Hello world!" ,
164
- } ,
165
- } ,
166
- {
167
- user : "{{agentName}}" ,
168
- content : {
169
- text : "I'll call a TTS to generate an audio based on your input prompt" ,
170
- action : "CREATE_TTS" ,
171
- } ,
172
- } ,
158
+ { user : "{{user1}}" , content : { text : "Generate a TTS of prompt: Hello world!" } } ,
159
+ { user : "{{agentName}}" , content : { text : "I'll call a TTS to generate an audio based on your input prompt" , action : "CREATE_TTS" } } ,
173
160
] ,
174
161
[
175
- {
176
- user : "{{user1}}" ,
177
- content : {
178
- text : "Please do TTS to a prompt: Sam is busy now" ,
179
- } ,
180
- } ,
181
- {
182
- user : "{{agentName}}" ,
183
- content : {
184
- text : "Ok, please wait for the tts generation~" ,
185
- action : "AUDIO_CREATE" ,
186
- } ,
187
- } ,
162
+ { user : "{{user1}}" , content : { text : "Please do TTS to a prompt: Sam is busy now" } } ,
163
+ { user : "{{agentName}}" , content : { text : "Ok, please wait for the tts generation~" , action : "AUDIO_CREATE" } } ,
188
164
] ,
189
165
] ,
190
- } as Action ;
166
+ } ;
191
167
192
168
export const TTSGenerationPlugin : Plugin = {
193
169
name : "TTSGeneration" ,
194
170
description : "Generate TTS using PlayAI tts (v3)" ,
195
171
actions : [ TTSGeneration ] ,
196
172
evaluators : [ ] ,
197
173
providers : [ ] ,
198
- } ;
174
+ } ;
0 commit comments