feat: audio speech streaming (#56)
Co-authored-by: yuhongxiao <hongxiao.yu@aminer.cn>
This commit is contained in:
parent
0ec7aac35f
commit
3120753df3
5 changed files with 79 additions and 0 deletions
|
|
@ -39,6 +39,20 @@ public interface AudioApi {
|
||||||
@POST("audio/speech")
|
@POST("audio/speech")
|
||||||
Single<ResponseBody> audioSpeech(@Body AudioSpeechRequest request);
|
Single<ResponseBody> audioSpeech(@Body AudioSpeechRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Text-to-Speech (TTS) conversion using GLM-4-Voice Converts text input into
|
||||||
|
* natural-sounding speech audio with emotion and tone control Supports multiple
|
||||||
|
* voices, languages, speed adjustment, and various audio formats Features advanced
|
||||||
|
* voice synthesis with customizable emotional expressions and dialects
|
||||||
|
* @param request TTS parameters including text, voice selection, emotion, speed,
|
||||||
|
* tone, and output format
|
||||||
|
* @return Generated high-quality audio streaming in specified format with natural
|
||||||
|
* prosody
|
||||||
|
*/
|
||||||
|
@Streaming
|
||||||
|
@POST("audio/speech")
|
||||||
|
Call<ResponseBody> audioSpeechStreaming(@Body AudioSpeechRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Voice cloning and customization using advanced neural models Creates custom voice
|
* Voice cloning and customization using advanced neural models Creates custom voice
|
||||||
* models from provided audio samples with high fidelity Enables personalized speech
|
* models from provided audio samples with high fidelity Enables personalized speech
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,13 @@ public interface AudioService {
|
||||||
*/
|
*/
|
||||||
AudioSpeechResponse createSpeech(AudioSpeechRequest request);
|
AudioSpeechResponse createSpeech(AudioSpeechRequest request);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates speech from text using text-to-speech.
|
||||||
|
* @param request the speech generation request
|
||||||
|
* @return AudioSpeechStreamingResponse containing the generated speech streaming
|
||||||
|
*/
|
||||||
|
AudioSpeechStreamingResponse createStreamingSpeechStreaming(AudioSpeechRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates customized speech with specific voice characteristics.
|
* Creates customized speech with specific voice characteristics.
|
||||||
* @param request the speech customization request
|
* @param request the speech customization request
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import ai.z.openapi.service.deserialize.MessageDeserializeFactory;
|
||||||
import ai.z.openapi.utils.FlowableRequestSupplier;
|
import ai.z.openapi.utils.FlowableRequestSupplier;
|
||||||
import ai.z.openapi.utils.RequestSupplier;
|
import ai.z.openapi.utils.RequestSupplier;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
import io.reactivex.rxjava3.core.Single;
|
import io.reactivex.rxjava3.core.Single;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import okhttp3.MediaType;
|
import okhttp3.MediaType;
|
||||||
|
|
@ -57,6 +58,13 @@ public class AudioServiceImpl implements AudioService {
|
||||||
return this.zAiClient.executeRequest(request, supplier, AudioSpeechResponse.class);
|
return this.zAiClient.executeRequest(request, supplier, AudioSpeechResponse.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AudioSpeechStreamingResponse createStreamingSpeechStreaming(AudioSpeechRequest request) {
|
||||||
|
validateSpeechParams(request);
|
||||||
|
FlowableRequestSupplier<AudioSpeechRequest, retrofit2.Call<ResponseBody>> supplier = audioApi::audioSpeechStreaming;
|
||||||
|
return this.zAiClient.streamRequest(request, supplier, AudioSpeechStreamingResponse.class, ObjectNode.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AudioCustomizationResponse createCustomSpeech(AudioCustomizationRequest request) {
|
public AudioCustomizationResponse createCustomSpeech(AudioCustomizationRequest request) {
|
||||||
validateCustomSpeechParams(request);
|
validateCustomSpeechParams(request);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package ai.z.openapi.service.audio;
|
||||||
|
|
||||||
|
import ai.z.openapi.core.model.ClientResponse;
|
||||||
|
import ai.z.openapi.core.model.FlowableClientResponse;
|
||||||
|
import ai.z.openapi.service.model.ChatError;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||||
|
import io.reactivex.rxjava3.core.Flowable;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class AudioSpeechStreamingResponse implements FlowableClientResponse<ObjectNode> {
|
||||||
|
|
||||||
|
private int code;
|
||||||
|
|
||||||
|
private String msg;
|
||||||
|
|
||||||
|
private boolean success;
|
||||||
|
|
||||||
|
private ObjectNode data;
|
||||||
|
|
||||||
|
private ChatError error;
|
||||||
|
|
||||||
|
private Flowable<ObjectNode> flowable;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -82,6 +82,29 @@ public class AudioServiceTest {
|
||||||
logger.info("Text-to-speech response: {}", mapper.writeValueAsString(response));
|
logger.info("Text-to-speech response: {}", mapper.writeValueAsString(response));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@DisplayName("Should generate speech streaming from text successfully")
|
||||||
|
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
|
||||||
|
void testAudioSpeechStreaming() {
|
||||||
|
String requestId = String.format(REQUEST_ID_TEMPLATE, System.currentTimeMillis());
|
||||||
|
AudioSpeechRequest audioSpeechRequest = AudioSpeechRequest.builder()
|
||||||
|
.model(Constants.ModelTTS)
|
||||||
|
.encodeFormat("base64")
|
||||||
|
.input("Hello, this is a test for text-to-speech functionality.")
|
||||||
|
.voice("female")
|
||||||
|
.speed(1.0f)
|
||||||
|
.volume(1.0f)
|
||||||
|
.stream(Boolean.TRUE)
|
||||||
|
.responseFormat("wav")
|
||||||
|
.requestId(requestId)
|
||||||
|
.build();
|
||||||
|
AudioSpeechStreamingResponse audioSpeechStreamingApiResponse = audioService
|
||||||
|
.createStreamingSpeechStreaming(audioSpeechRequest);
|
||||||
|
audioSpeechStreamingApiResponse.getFlowable()
|
||||||
|
.doOnNext(speechPro -> logger.info("speechPro: {}", speechPro.toString()))
|
||||||
|
.blockingSubscribe();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@DisplayName("Should generate custom speech with voice cloning successfully")
|
@DisplayName("Should generate custom speech with voice cloning successfully")
|
||||||
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
|
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue