1616import com .ibm .watson .developer_cloud .text_to_speech .v1 .model .DeleteUserDataOptions ;
1717import com .ibm .watson .developer_cloud .text_to_speech .v1 .model .GetPronunciationOptions ;
1818import com .ibm .watson .developer_cloud .text_to_speech .v1 .model .GetVoiceOptions ;
19+ import com .ibm .watson .developer_cloud .text_to_speech .v1 .model .MarkTiming ;
20+ import com .ibm .watson .developer_cloud .text_to_speech .v1 .model .Marks ;
1921import com .ibm .watson .developer_cloud .text_to_speech .v1 .model .Pronunciation ;
2022import com .ibm .watson .developer_cloud .text_to_speech .v1 .model .SynthesizeOptions ;
23+ import com .ibm .watson .developer_cloud .text_to_speech .v1 .model .Timings ;
2124import com .ibm .watson .developer_cloud .text_to_speech .v1 .model .Voice ;
2225import com .ibm .watson .developer_cloud .text_to_speech .v1 .model .Voices ;
26+ import com .ibm .watson .developer_cloud .text_to_speech .v1 .model .WordTiming ;
2327import com .ibm .watson .developer_cloud .text_to_speech .v1 .util .WaveUtils ;
28+ import com .ibm .watson .developer_cloud .text_to_speech .v1 .websocket .BaseSynthesizeCallback ;
2429import com .ibm .watson .developer_cloud .util .RetryRunner ;
2530import org .junit .Assume ;
2631import org .junit .Before ;
2934
3035import javax .sound .sampled .AudioSystem ;
3136import javax .sound .sampled .UnsupportedAudioFileException ;
37+ import java .io .ByteArrayOutputStream ;
3238import java .io .File ;
39+ import java .io .FileNotFoundException ;
40+ import java .io .FileOutputStream ;
3341import java .io .IOException ;
3442import java .io .InputStream ;
43+ import java .io .OutputStream ;
44+ import java .util .ArrayList ;
45+ import java .util .Collections ;
46+ import java .util .List ;
47+ import java .util .concurrent .CountDownLatch ;
48+ import java .util .concurrent .TimeUnit ;
3549
50+ import static org .junit .Assert .assertEquals ;
3651import static org .junit .Assert .assertNotNull ;
3752import static org .junit .Assert .assertTrue ;
3853import static org .junit .Assert .fail ;
4358@ RunWith (RetryRunner .class )
4459public class TextToSpeechIT extends WatsonServiceTest {
4560
61+ private CountDownLatch lock = new CountDownLatch (1 );
4662 private TextToSpeech service ;
4763 private String voiceName ;
64+ private ByteArrayOutputStream byteArrayOutputStream ;
65+ private String returnedContentType ;
66+ private List <Timings > returnedTimings ;
67+ private List <Marks > returnedMarks ;
4868
4969 /*
5070 * (non-Javadoc)
@@ -63,6 +83,10 @@ public void setUp() throws Exception {
6383 service .setEndPoint (getProperty ("text_to_speech.url" ));
6484 service .setDefaultHeaders (getDefaultHeaders ());
6585 voiceName = getProperty ("text_to_speech.voice_name" );
86+
87+ byteArrayOutputStream = new ByteArrayOutputStream ();
88+ returnedTimings = new ArrayList <>();
89+ returnedMarks = new ArrayList <>();
6690 }
6791
6892 /**
@@ -191,4 +215,99 @@ public void testDeleteUserData() {
191215 fail (ex .getMessage ());
192216 }
193217 }
218+
219+ @ Test
220+ public void testSynthesizeUsingWebSocket () throws InterruptedException , IOException {
221+ String basicText = "One taught me love. One taught me patience, and one taught me pain. Now, I'm so amazing. Say " +
222+ "I've loved and I've lost, but that's not what I see. So, look what I got. Look what you taught me. And for " +
223+ "that, I say... thank u, next." ;
224+
225+ SynthesizeOptions synthesizeOptions = new SynthesizeOptions .Builder ()
226+ .text (basicText )
227+ .voice (SynthesizeOptions .Voice .EN_US_ALLISONVOICE )
228+ .accept (SynthesizeOptions .Accept .AUDIO_OGG_CODECS_OPUS )
229+ .timings (Collections .singletonList ("words" ))
230+ .build ();
231+
232+ service .synthesizeUsingWebSocket (synthesizeOptions , new BaseSynthesizeCallback () {
233+ @ Override
234+ public void onContentType (String contentType ) {
235+ returnedContentType = contentType ;
236+ }
237+
238+ @ Override
239+ public void onAudioStream (byte [] bytes ) {
240+ // build byte array of synthesized text
241+ try {
242+ byteArrayOutputStream .write (bytes );
243+ } catch (IOException e ) {
244+ e .printStackTrace ();
245+ }
246+ }
247+
248+ @ Override
249+ public void onTimings (Timings timings ) {
250+ returnedTimings .add (timings );
251+ }
252+ });
253+
254+ // wait for synthesis to complete
255+ lock .await (5 , TimeUnit .SECONDS );
256+
257+ String filename = "synthesize_websocket_test.ogg" ;
258+ OutputStream fileOutputStream = new FileOutputStream (filename );
259+ byteArrayOutputStream .writeTo (fileOutputStream );
260+ File createdFile = new File (filename );
261+
262+ assertTrue (createdFile .exists ());
263+ assertEquals (SynthesizeOptions .Accept .AUDIO_OGG_CODECS_OPUS , returnedContentType );
264+ for (Timings t : returnedTimings ) {
265+ List <WordTiming > wordTimings = t .getWords ();
266+ for (WordTiming wordTiming : wordTimings ) {
267+ assertTrue (basicText .contains (wordTiming .getWord ()));
268+ }
269+ }
270+
271+ // clean up
272+ byteArrayOutputStream .close ();
273+ fileOutputStream .close ();
274+ if (createdFile .delete ()) {
275+ System .out .println ("File deleted successfully!" );
276+ } else {
277+ System .out .println ("File could not be deleted" );
278+ }
279+ }
280+
281+ @ Test
282+ public void testSynthesizeUsingWebSocketWithSsml () throws InterruptedException {
283+ List <String > ssmlMarks = new ArrayList <>();
284+ ssmlMarks .add ("sean" );
285+ ssmlMarks .add ("ricky" );
286+ String ssmlText = String .format ("Thought I'd end up with <mark name=\" %s\" />Sean, <express-as type=\" Apology\" > " +
287+ "but he wasn't a match. </express-as> Wrote some songs about <mark name=\" %s\" />Ricky, now I listen and " +
288+ "laugh" , ssmlMarks .get (0 ), ssmlMarks .get (1 ));
289+
290+ SynthesizeOptions synthesizeOptions = new SynthesizeOptions .Builder ()
291+ .text (ssmlText )
292+ .voice (SynthesizeOptions .Voice .EN_US_ALLISONVOICE )
293+ .accept (SynthesizeOptions .Accept .AUDIO_OGG_CODECS_OPUS )
294+ .build ();
295+
296+ service .synthesizeUsingWebSocket (synthesizeOptions , new BaseSynthesizeCallback () {
297+ @ Override
298+ public void onMarks (Marks marks ) {
299+ returnedMarks .add (marks );
300+ }
301+ });
302+
303+ // wait for synthesis to complete
304+ lock .await (5 , TimeUnit .SECONDS );
305+
306+ for (Marks m : returnedMarks ) {
307+ List <MarkTiming > markList = m .getMarks ();
308+ for (MarkTiming markTiming : markList ) {
309+ assertTrue (ssmlMarks .contains (markTiming .getMark ()));
310+ }
311+ }
312+ }
194313}
0 commit comments