From 86111526b3a98c96f6ff30131dd23009f037ccf4 Mon Sep 17 00:00:00 2001 From: Lighthousexx <57421816+Lighthousexx@users.noreply.github.com> Date: Tue, 9 Sep 2025 10:12:00 +0800 Subject: [PATCH] feat: voice clone (#47) --- .../openapi/api/voiceclone/VoiceCloneApi.java | 14 ++++----- .../service/voiceclone/VoiceCloneRequest.java | 12 +++++--- .../service/voiceclone/VoiceCloneResult.java | 8 ++--- .../service/voiceclone/VoiceCloneService.java | 4 +-- .../voiceclone/VoiceCloneServiceImpl.java | 8 ++--- .../openapi/service/voiceclone/VoiceData.java | 6 ++-- .../voiceclone/VoiceDeleteRequest.java | 6 ++-- .../service/voiceclone/VoiceDeleteResult.java | 10 +++---- .../voiceclone/VoiceCloneServiceTest.java | 11 ++++--- .../VoiceCloneExample.java | 29 ++++++++++--------- 10 files changed, 56 insertions(+), 52 deletions(-) diff --git a/core/src/main/java/ai/z/openapi/api/voiceclone/VoiceCloneApi.java b/core/src/main/java/ai/z/openapi/api/voiceclone/VoiceCloneApi.java index 4a2d8d9..4a6c816 100644 --- a/core/src/main/java/ai/z/openapi/api/voiceclone/VoiceCloneApi.java +++ b/core/src/main/java/ai/z/openapi/api/voiceclone/VoiceCloneApi.java @@ -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 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 diff --git a/core/src/main/java/ai/z/openapi/service/voiceclone/VoiceCloneRequest.java b/core/src/main/java/ai/z/openapi/service/voiceclone/VoiceCloneRequest.java index 05dc421..f64ecd1 100644 --- a/core/src/main/java/ai/z/openapi/service/voiceclone/VoiceCloneRequest.java +++ b/core/src/main/java/ai/z/openapi/service/voiceclone/VoiceCloneRequest.java @@ -20,15 +20,19 @@ public class VoiceCloneRequest extends CommonRequest implements ClientRequest { - @JsonProperty("voice_id") - private String voiceId; + @JsonProperty("voice") + private String voice; } diff --git a/core/src/main/java/ai/z/openapi/service/voiceclone/VoiceDeleteResult.java b/core/src/main/java/ai/z/openapi/service/voiceclone/VoiceDeleteResult.java index bb5a276..55cddc0 100644 --- a/core/src/main/java/ai/z/openapi/service/voiceclone/VoiceDeleteResult.java +++ b/core/src/main/java/ai/z/openapi/service/voiceclone/VoiceDeleteResult.java @@ -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; } diff --git a/core/src/test/java/ai/z/openapi/service/voiceclone/VoiceCloneServiceTest.java b/core/src/test/java/ai/z/openapi/service/voiceclone/VoiceCloneServiceTest.java index 647a503..d741541 100644 --- a/core/src/test/java/ai/z/openapi/service/voiceclone/VoiceCloneServiceTest.java +++ b/core/src/test/java/ai/z/openapi/service/voiceclone/VoiceCloneServiceTest.java @@ -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); diff --git a/samples/src/main/ai.z.openapi.samples/VoiceCloneExample.java b/samples/src/main/ai.z.openapi.samples/VoiceCloneExample.java index bdd51c2..a706a35 100644 --- a/samples/src/main/ai.z.openapi.samples/VoiceCloneExample.java +++ b/samples/src/main/ai.z.openapi.samples/VoiceCloneExample.java @@ -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."); } } } \ No newline at end of file