feat: voice clone (#47)
This commit is contained in:
parent
cd4e1f1b11
commit
86111526b3
10 changed files with 56 additions and 52 deletions
|
|
@ -25,15 +25,15 @@ public interface VoiceCloneApi {
|
|||
* synthesize speech matching the characteristics of the provided sample.
|
||||
* @param request voice clone creation parameters including voice name, sample text,
|
||||
* target text, and audio file reference
|
||||
* @return voice clone creation result with voice ID and preview file information
|
||||
* @return voice clone creation result with voice and preview file information
|
||||
*/
|
||||
@POST("voice/clone")
|
||||
Single<VoiceCloneResult> cloneVoice(@Body VoiceCloneRequest request);
|
||||
|
||||
/**
|
||||
* Deletes an existing voice clone by voice ID. Permanently removes the voice model
|
||||
* and associated data from the system. This operation cannot be undone.
|
||||
* @param request voice deletion parameters containing the voice ID to delete
|
||||
* Deletes an existing voice clone by voice. Permanently removes the voice model and
|
||||
* associated data from the system. This operation cannot be undone.
|
||||
* @param request voice deletion parameters containing the voice to delete
|
||||
* @return voice deletion result with confirmation and deletion timestamp
|
||||
*/
|
||||
@POST("voice/delete")
|
||||
|
|
@ -41,8 +41,8 @@ public interface VoiceCloneApi {
|
|||
|
||||
/**
|
||||
* Retrieves a list of available voice clones with optional filtering. Returns
|
||||
* metadata and details for voice clones including voice IDs, names, types, download
|
||||
* URLs, and creation timestamps.
|
||||
* metadata and details for voice clones including voice, names, types, download URLs,
|
||||
* and creation timestamps.
|
||||
* @param voiceType optional voice type filter
|
||||
* @param voiceName optional voice name filter
|
||||
* @return list of voice clone data with comprehensive metadata
|
||||
|
|
@ -52,7 +52,7 @@ public interface VoiceCloneApi {
|
|||
|
||||
/**
|
||||
* Retrieves a list of available voice clones with optional filtering and Request-Id
|
||||
* header. Returns metadata and details for voice clones including voice IDs, names,
|
||||
* header. Returns metadata and details for voice clones including voice, names,
|
||||
* types, download URLs, and creation timestamps.
|
||||
* @param voiceType optional voice type filter
|
||||
* @param voiceName optional voice name filter
|
||||
|
|
|
|||
|
|
@ -20,15 +20,19 @@ public class VoiceCloneRequest extends CommonRequest implements ClientRequest<Vo
|
|||
private String voiceName;
|
||||
|
||||
/** Text content corresponding to the sample audio */
|
||||
@JsonProperty("voice_text_input")
|
||||
private String voiceTextInput;
|
||||
@JsonProperty("text")
|
||||
private String text;
|
||||
|
||||
/** Target text for preview audio */
|
||||
@JsonProperty("voice_text_output")
|
||||
private String voiceTextOutput;
|
||||
@JsonProperty("input")
|
||||
private String input;
|
||||
|
||||
/** File ID of the audio file */
|
||||
@JsonProperty("file_id")
|
||||
private String fileId;
|
||||
|
||||
/** Model */
|
||||
@JsonProperty("model")
|
||||
private String model;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import lombok.NoArgsConstructor;
|
|||
|
||||
/**
|
||||
* Result data for voice cloning operations. This class contains the voice cloning result
|
||||
* information including voice ID, audio file ID, and file purpose.
|
||||
* information including voice, audio file ID, and file purpose.
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
|
|
@ -16,9 +16,9 @@ import lombok.NoArgsConstructor;
|
|||
@NoArgsConstructor
|
||||
public class VoiceCloneResult {
|
||||
|
||||
/** Voice ID */
|
||||
@JsonProperty("voice_id")
|
||||
private String voiceId;
|
||||
/** Voice */
|
||||
@JsonProperty("voice")
|
||||
private String voice;
|
||||
|
||||
/** Audio preview file ID */
|
||||
@JsonProperty("file_id")
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ public interface VoiceCloneService {
|
|||
VoiceCloneResponse cloneVoice(VoiceCloneRequest request);
|
||||
|
||||
/**
|
||||
* Deletes an existing voice clone by voice ID.
|
||||
* @param request the voice deletion request containing the voice ID to delete
|
||||
* Deletes an existing voice clone by voice.
|
||||
* @param request the voice deletion request containing the voice to delete
|
||||
* @return VoiceDeleteResponse containing the deletion result and timestamp
|
||||
*/
|
||||
VoiceDeleteResponse deleteVoice(VoiceDeleteRequest request);
|
||||
|
|
|
|||
|
|
@ -58,8 +58,8 @@ public class VoiceCloneServiceImpl implements VoiceCloneService {
|
|||
if (request.getVoiceName() == null || request.getVoiceName().trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("voice name cannot be null or empty");
|
||||
}
|
||||
if (request.getVoiceTextInput() == null || request.getVoiceTextInput().trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("voice text input cannot be null or empty");
|
||||
if (request.getInput() == null || request.getInput().trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("input cannot be null or empty");
|
||||
}
|
||||
if (request.getFileId() == null || request.getFileId().trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("file ID cannot be null or empty");
|
||||
|
|
@ -70,8 +70,8 @@ public class VoiceCloneServiceImpl implements VoiceCloneService {
|
|||
if (request == null) {
|
||||
throw new IllegalArgumentException("request cannot be null");
|
||||
}
|
||||
if (request.getVoiceId() == null || request.getVoiceId().trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("voice ID cannot be null or empty");
|
||||
if (request.getVoice() == null || request.getVoice().trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("voice cannot be null or empty");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ import java.util.Date;
|
|||
|
||||
/**
|
||||
* Voice data entity containing voice information. This class contains voice details
|
||||
* including voice ID, name, type, download URL, and creation time.
|
||||
* including voice, name, type, download URL, and creation time.
|
||||
*/
|
||||
@Data
|
||||
public class VoiceData {
|
||||
|
||||
@JsonProperty("voice_id")
|
||||
private String voiceId;
|
||||
@JsonProperty("voice")
|
||||
private String voice;
|
||||
|
||||
@JsonProperty("voice_name")
|
||||
private String voiceName;
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@ import lombok.EqualsAndHashCode;
|
|||
|
||||
/**
|
||||
* Request parameters for voice deletion API. This class contains the necessary parameters
|
||||
* for deleting a voice, specifically the voice ID.
|
||||
* for deleting a voice, specifically the voice.
|
||||
*/
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@Data
|
||||
public class VoiceDeleteRequest extends CommonRequest implements ClientRequest<VoiceDeleteRequest> {
|
||||
|
||||
@JsonProperty("voice_id")
|
||||
private String voiceId;
|
||||
@JsonProperty("voice")
|
||||
private String voice;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ import java.util.Date;
|
|||
|
||||
/**
|
||||
* Result data for voice deletion operations. This class contains the deletion result
|
||||
* information including voice ID and deletion timestamp.
|
||||
* information including voice and deletion timestamp.
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
|
|
@ -20,11 +20,11 @@ import java.util.Date;
|
|||
@NoArgsConstructor
|
||||
public class VoiceDeleteResult {
|
||||
|
||||
@JsonProperty("voice_id")
|
||||
private String voiceId;
|
||||
@JsonProperty("voice")
|
||||
private String voice;
|
||||
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@JsonProperty("delete_time")
|
||||
private Date deleteTime;
|
||||
@JsonProperty("update_time")
|
||||
private Date updateTime;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,8 +15,6 @@ import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;
|
|||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
/**
|
||||
|
|
@ -73,9 +71,10 @@ public class VoiceCloneServiceTest {
|
|||
// Now we can use the uploaded file ID to create a voice clone
|
||||
VoiceCloneRequest request = new VoiceCloneRequest();
|
||||
request.setVoiceName("Test");
|
||||
request.setVoiceTextInput("This is sample text for voice cloning training");
|
||||
request.setVoiceTextOutput("This is target text for voice preview generation");
|
||||
request.setText("This is sample text for voice cloning training");
|
||||
request.setInput("This is target text for voice preview generation");
|
||||
request.setFileId(fileId); // Use the actual file ID from upload
|
||||
request.setModel("CogTTS-clone");
|
||||
|
||||
// Execute voice cloning
|
||||
VoiceCloneResponse response = voiceCloneService.cloneVoice(request);
|
||||
|
|
@ -112,10 +111,10 @@ public class VoiceCloneServiceTest {
|
|||
@DisplayName("Test voice deletion")
|
||||
@EnabledIfEnvironmentVariable(named = "ZAI_API_KEY", matches = "^[^.]+\\.[^.]+$")
|
||||
void testDeleteVoice() throws JsonProcessingException {
|
||||
// Create a voice deletion request with a test voice ID
|
||||
// Create a voice deletion request with a test voice
|
||||
// In a real scenario, this would be an ID from a previously created voice clone
|
||||
VoiceDeleteRequest request = new VoiceDeleteRequest();
|
||||
request.setVoiceId("Test voice Id");
|
||||
request.setVoice("Test voice");
|
||||
|
||||
// Execute the voice deletion
|
||||
VoiceDeleteResponse response = voiceCloneService.deleteVoice(request);
|
||||
|
|
|
|||
|
|
@ -75,17 +75,18 @@ public class VoiceCloneExample {
|
|||
// Step 2: Create voice clone using the uploaded file
|
||||
VoiceCloneRequest request = new VoiceCloneRequest();
|
||||
request.setVoiceName("My Custom Voice");
|
||||
request.setVoiceTextInput("Hello, this is a sample text for voice cloning training");
|
||||
request.setVoiceTextOutput("Welcome to our voice synthesis system");
|
||||
request.setText("Hello, this is a sample text for voice cloning training");
|
||||
request.setInput("Welcome to our voice synthesis system");
|
||||
request.setFileId(fileId);
|
||||
request.setRequestId("clone-request-" + System.currentTimeMillis());
|
||||
request.setModel("CogTTS-clone");
|
||||
|
||||
System.out.println("Creating voice clone...");
|
||||
VoiceCloneResponse response = voiceCloneService.cloneVoice(request);
|
||||
|
||||
if (response.isSuccess()) {
|
||||
System.out.println("Voice clone created successfully!");
|
||||
System.out.println("Voice ID: " + response.getData().getVoiceId());
|
||||
System.out.println("Voice: " + response.getData().getVoice());
|
||||
} else {
|
||||
System.err.println("Voice clone creation failed: " + response.getMsg());
|
||||
if (response.getError() != null) {
|
||||
|
|
@ -118,7 +119,7 @@ public class VoiceCloneExample {
|
|||
if (response.getData().getVoiceList() != null && !response.getData().getVoiceList().isEmpty()) {
|
||||
System.out.println("Found " + response.getData().getVoiceList().size() + " voices:");
|
||||
for (VoiceData voice : response.getData().getVoiceList()) {
|
||||
System.out.println("- Voice ID: " + voice.getVoiceId());
|
||||
System.out.println("- Voice: " + voice.getVoice());
|
||||
System.out.println(" Name: " + voice.getVoiceName());
|
||||
System.out.println(" Type: " + voice.getVoiceType());
|
||||
if (voice.getDownloadUrl() != null) {
|
||||
|
|
@ -142,24 +143,24 @@ public class VoiceCloneExample {
|
|||
|
||||
/**
|
||||
* Example of deleting a voice clone
|
||||
* Note: Replace "your-voice-id" with an actual voice ID from your account
|
||||
* Note: Replace "your-voice" with an actual voice from your account
|
||||
*/
|
||||
private static void deleteVoiceExample(VoiceCloneService voiceCloneService) {
|
||||
try {
|
||||
// Note: This is just an example - replace with actual voice ID
|
||||
String voiceIdToDelete = "your-voice-id-here";
|
||||
// Note: This is just an example - replace with actual voice
|
||||
String voiceToDelete = "your-voice-here";
|
||||
|
||||
VoiceDeleteRequest request = new VoiceDeleteRequest();
|
||||
request.setVoiceId(voiceIdToDelete);
|
||||
request.setVoice(voiceToDelete);
|
||||
request.setRequestId("delete-request-" + System.currentTimeMillis());
|
||||
|
||||
System.out.println("Deleting voice clone with ID: " + voiceIdToDelete);
|
||||
System.out.println("Deleting voice: " + voiceToDelete);
|
||||
VoiceDeleteResponse response = voiceCloneService.deleteVoice(request);
|
||||
|
||||
if (response.isSuccess()) {
|
||||
System.out.println("Voice clone deleted successfully!");
|
||||
if (response.getData().getDeleteTime() != null) {
|
||||
System.out.println("Deletion time: " + response.getData().getDeleteTime());
|
||||
if (response.getData().getUpdateTime() != null) {
|
||||
System.out.println("Deletion time: " + response.getData().getUpdateTime());
|
||||
}
|
||||
} else {
|
||||
System.err.println("Voice deletion failed: " + response.getMsg());
|
||||
|
|
@ -168,9 +169,9 @@ public class VoiceCloneExample {
|
|||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// Expected to fail with example voice ID
|
||||
System.out.println("Note: This example uses a placeholder voice ID and is expected to fail.");
|
||||
System.out.println("Replace 'your-voice-id-here' with an actual voice ID to test deletion.");
|
||||
// Expected to fail with example voice
|
||||
System.out.println("Note: This example uses a placeholder voice and is expected to fail.");
|
||||
System.out.println("Replace 'your-voice-here' with an actual voice to test deletion.");
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue