華為HMS Core音頻編輯服務(Audio Editor Kit)依托自身AI技術的研發優勢,上線全新的歌聲合成音色及伴奏,給音視頻創作者提供更多的創作可能。在短視頻場景中,用戶自定義歌詞的歌聲結合視頻讓用戶感受到身臨其境,自由表達自己的情緒;在虛擬偶像場景中,歌聲合成功能賦予虛擬歌手們演唱風格各 ...
華為HMS Core音頻編輯服務(Audio Editor Kit)依托自身AI技術的研發優勢,上線全新的歌聲合成音色及伴奏,給音視頻創作者提供更多的創作可能。在短視頻場景中,用戶自定義歌詞的歌聲結合視頻讓用戶感受到身臨其境,自由表達自己的情緒;在虛擬偶像場景中,歌聲合成功能賦予虛擬歌手們演唱風格各異的歌曲,帶來創意無限。
HMS Core音頻編輯服務歌聲合成的AI Singer模型能力通過字級別輸入歌詞進行音素轉換,就可以為用戶創作音樂,也可預置曲目合成歌聲。通過自研音高模型,讓音高曲線在保持輸入曲譜的音高精準度的同時改善自然度,更接近人的真實演唱。使用最新的生成式模型,帶來更好的音色還原度、建模更多的演唱細節,同時高清聲碼器能夠真實還原48k高清音質。
另外,用戶通過自由調整顫音、滑音、呼吸音等功能,可根據情感需求調整歌聲演唱技巧。當前歌聲合成服務已開放了情流行女聲、國風女聲和民謠男聲音色,未來會持續更新更多音色。
華為HMS Core音頻編輯服務(Audio Editor Kit)讓機器“演唱”出真實度的歌聲,僅需簡單的集成獲得,以下是開發者應用集成音頻編輯服務歌聲合成能力的具體步驟。
開發步驟
1. 開發準備
1.1註冊成為開發者
在開發應用前需要在華為開發者聯盟網站上註冊成為開發者並完成實名認證,具體方法請參見帳號註冊認證。
1.2創建項目及應用
參見創建項目,然後在項目下創建應用完成應用的創建,特殊配置如下:
選擇平臺:選擇“Web”。
1.3打開相關服務
使用Audio Editor Kit服務需要您在AppGallery Connect上打開Audio Editor Kit服務開關,具體操作步驟請參見打開服務開關。
2.歌聲合成功能集成
2.1同步介面(流式)
2.1.1獲取access_token鑒權信息
使用開發者聯盟界面獲得的客戶端ID以及對應密鑰,發送HTTPS POST請求,獲取查詢access_token。獲取方式請參見客戶端模式(Client Credentials)。
2.1.2調用同步介面(流式)
通過以上步驟獲取的access_token信息,發送HTTPS POST調用同步介面(流式)。
示例代碼(Java)如下所示:
其中requestUrl = "https://audioeditor-api-drcn.cloud.huawei.com/v1/audioeditor/gateway/ai/ttsing/sync"。
請點擊下載MusicXML文件,並上傳:
/**
* 調用同步介面(流式)
* @throws Exception IO異常
*/
private static void syncTask() throws Exception {
// 設置請求header
PostMethod postMethod = new PostMethod(requestUrl);
// 設置文本類型(String),例:"application/json;charset=utf-8"
postMethod.setRequestHeader("Content-Type", contentType);
// 設置請求ID(String),例:"9af1aeda-531b-407a-80b4-65b40ef77bd6"
postMethod.setRequestHeader("X-Request-ID", requestId);
// 設置App包名(String),例:"com.huawei.demo"
postMethod.setRequestHeader("X-Package-Name", pacageName);
// 設置App所在國家(String),例:"cn"
postMethod.setRequestHeader("X-Country-Code", countryCode);
// 設置App標識(String),例:"9af1aeda-531b-407a-80b4-65b40ef77bd6"
postMethod.setRequestHeader("HMS-APPLICATION-ID", applicationId);
// 設置證書指紋(String),例:"xxxxxxxxxxxxxxx"
postMethod.setRequestHeader("certFingerprint", certFingerprint);
// 設置動態獲取的AccessToken(String)
postMethod.setRequestHeader("Authorization","Bearer " + accessToken);
// 設置請求body
Map<String, Object> bodyMap = new HashMap<>();
Map<String, Object> dataMap = new HashMap<>();
Map<String, Object> configMap = new HashMap<>();
// filePath是MusicXML文件路徑(含文件名、尾碼)
String lyricFilePath = "filePath";
dataMap.put("lyric", FileUtils.readFileToString(new File(lyricFilePath), "UTF-8"));
dataMap.put("language", "chinese");
configMap.put("type", 1);
configMap.put("outputEncoderFormat", 0);
configMap.put("wordDurationForceAlign", "false");
bodyMap.put("data", dataMap);
bodyMap.put("config", configMap);
RequestEntity requestEntity = new StringRequestEntity(JSONObject.toJSONString(bodyMap),"application/json" ,"UTF-8");
postMethod.setRequestEntity(requestEntity);
HttpClient httpClient = new HttpClient();
int ret = httpClient.executeMethod(postMethod);
if (ret == 200) {
Header responseHeader = postMethod.getResponseHeader("content-type");
if ("application/octet-stream".equals(responseHeader.getValue())) {
InputStream rpsContent = postMethod.getResponseBodyAsStream();
// filePath是要保存文件的路徑(含文件名、PCM文件尾碼)
String filePath = "filePath";
FileUtils.copyInputStreamToFile(rpsContent, new File(filePath));
} else {
String errorString = postMethod.getResponseBodyAsString();
System.out.println(errorString);
}
} else {
System.out.println("callApi failed: ret =" + ret + " rsp=" + postMethod.getResponseBodyAsString());
}
}
使用預置曲目輸入歌詞:
/**
* 調用同步介面(流式)
* @throws Exception IO異常
*/
private static void syncTask() throws Exception {
// 設置請求header
PostMethod postMethod = new PostMethod(requestUrl);
// 設置文本類型(String),例:"application/json;charset=utf-8"
postMethod.setRequestHeader("Content-Type", contentType);
// 設置請求ID(String),例:"9af1aeda-531b-407a-80b4-65b40ef77bd6"
postMethod.setRequestHeader("X-Request-ID", requestId);
// 設置App包名(String),例:"com.huawei.demo"
postMethod.setRequestHeader("X-Package-Name", pacageName);
// 設置App所在國家(String),例:"cn"
postMethod.setRequestHeader("X-Country-Code", countryCode);
// 設置App標識(String),例:"9af1aeda-531b-407a-80b4-65b40ef77bd6"
postMethod.setRequestHeader("HMS-APPLICATION-ID", applicationId);
// 設置證書指紋(String),例:"xxxxxxxxxxxxxxx"
postMethod.setRequestHeader("certFingerprint", certFingerprint);
// 設置動態獲取的AccessToken(String)
postMethod.setRequestHeader("Authorization","Bearer " + accessToken);
// 設置請求body
Map<String, Object> bodyMap = new HashMap<>();
Map<String, Object> dataMap = new HashMap<>();
Map<String, Object> configMap = new HashMap<>();
String[] lyrics = {"跟隨心跳的節拍", "感受自由的暢快", "把煩惱通通拋開", "我們一起嗨", "調整呼吸的節拍", "保持最好的狀態", "奔向耀眼的未來", "哦康忙北北"};
dataMap.put("lyrics", lyrics);
dataMap.put("accompanimentId", "1");
dataMap.put("isAutoFill", "false");
dataMap.put("language", "chinese");
configMap.put("type", 1);
configMap.put("outputEncoderFormat", 0);
configMap.put("wordDurationForceAlign", "false");
bodyMap.put("data", dataMap);
bodyMap.put("config", configMap);
RequestEntity requestEntity = new StringRequestEntity(JSONObject.toJSONString(bodyMap),"application/json" ,"UTF-8");
postMethod.setRequestEntity(requestEntity);
HttpClient httpClient = new HttpClient();
int ret = httpClient.executeMethod(postMethod);
if (ret == 200) {
Header responseHeader = postMethod.getResponseHeader("content-type");
if ("application/octet-stream".equals(responseHeader.getValue())) {
InputStream rpsContent = postMethod.getResponseBodyAsStream();
// filePath是要保存文件的路徑(含文件名、PCM文件尾碼)
String filePath = "filePath";
FileUtils.copyInputStreamToFile(rpsContent, new File(filePath));
} else {
String errorString = postMethod.getResponseBodyAsString();
System.out.println(errorString);
}
} else {
System.out.println("callApi failed: ret =" + ret + " rsp=" + postMethod.getResponseBodyAsString());
}
}
註意:
上述代碼中xxxxx對應的值請根據實際情況填寫,具體取值請參見同步介面(流式)。
2.2非同步介面
2.2.1創建非同步任務
通過access_token信息,發送HTTPS POST創建歌聲合成非同步任務。
示例代碼(Java)如下所示:
其中requestUrl = "https://audioeditor-api-drcn.cloud.huawei.com/v1/audioeditor/gateway/ai/ttsing/async/task/create"。
請點擊下載MusicXML文件,並上傳:
/**
* 調用創建非同步任務介面
* @throws Exception IO異常
*/
private static void creatAsyncTask() throws Exception {
// 設置請求header
PostMethod postMethod = new PostMethod(requestUrl);
// 設置文本類型(String),例:"application/json;charset=utf-8"
postMethod.setRequestHeader("Content-Type", contentType);
// 設置請求ID(String),例:"9af1aeda-531b-407a-80b4-65b40ef77bd6"
postMethod.setRequestHeader("X-Request-ID", requestId);
// 設置App包名(String),例:"com.huawei.demo"
postMethod.setRequestHeader("X-Package-Name", pacageName);
// 設置App所在國家(String),例:"cn"
postMethod.setRequestHeader("X-Country-Code", countryCode);
// 設置App標識(String),例:"9af1aeda-531b-407a-80b4-65b40ef77bd6"
postMethod.setRequestHeader("HMS-APPLICATION-ID", applicationId);
// 設置證書指紋(String),例:"xxxxxxxxxxxxxxx"
postMethod.setRequestHeader("certFingerprint", certFingerprint);
// 設置動態獲取的AccessToken(String)
postMethod.setRequestHeader("Authorization","Bearer " + accessToken);
// 設置請求body
Map<String, Object> bodyMap = new HashMap<>();
Map<String, Object> dataMap = new HashMap<>();
Map<String, Object> configMap = new HashMap<>();
// filePath是MusicXML文件路徑(含文件名、尾碼)
String lyricFilePath = "filePath";
dataMap.put("lyric", FileUtils.readFileToString(new File(lyricFilePath), "UTF-8"));
dataMap.put("language", "chinese");
configMap.put("type", 1);
configMap.put("outputEncoderFormat", 0);
configMap.put("wordDurationForceAlign", "false");
bodyMap.put("data", dataMap);
bodyMap.put("config", configMap);
RequestEntity requestEntity = new StringRequestEntity(JSONObject.toJSONString(bodyMap),"application/json" ,"UTF-8");
postMethod.setRequestEntity(requestEntity);
HttpClient httpClient = new HttpClient();
int ret = httpClient.executeMethod(postMethod);
String rpsContent = postMethod.getResponseBodyAsString();
if (ret == 200) {
System.out.println(rpsContent);
} else {
System.out.println("callApi failed: ret =" + ret + " rsp=" + rpsContent);
}
}
使用預置曲目輸入歌詞:
/**
* 調用創建非同步任務介面
* @throws Exception IO異常
*/
private static void creatAsyncTask() throws Exception {
// 設置請求header
PostMethod postMethod = new PostMethod(requestUrl);
// 設置文本類型(String),例:"application/json;charset=utf-8"
postMethod.setRequestHeader("Content-Type", contentType);
// 設置請求ID(String),例:"9af1aeda-531b-407a-80b4-65b40ef77bd6"
postMethod.setRequestHeader("X-Request-ID", requestId);
// 設置App包名(String),例:"com.huawei.demo"
postMethod.setRequestHeader("X-Package-Name", pacageName);
// 設置App所在國家(String),例:"cn"
postMethod.setRequestHeader("X-Country-Code", countryCode);
// 設置App標識(String),例:"9af1aeda-531b-407a-80b4-65b40ef77bd6"
postMethod.setRequestHeader("HMS-APPLICATION-ID", applicationId);
// 設置證書指紋(String),例:"xxxxxxxxxxxxxxx"
postMethod.setRequestHeader("certFingerprint", certFingerprint);
// 設置動態獲取的AccessToken(String)
postMethod.setRequestHeader("Authorization","Bearer " + accessToken);
// 設置請求body
Map<String, Object> bodyMap = new HashMap<>();
Map<String, Object> dataMap = new HashMap<>();
Map<String, Object> configMap = new HashMap<>();
String[] lyrics = {"跟隨心跳的節拍", "感受自由的暢快", "把煩惱通通拋開", "我們一起嗨", "調整呼吸的節拍", "保持最好的狀態", "奔向耀眼的未來", "哦康忙北北"};
dataMap.put("lyrics", lyrics);
dataMap.put("accompanimentId", "1");
dataMap.put("isAutoFill", "false");
dataMap.put("language", "chinese");
configMap.put("type", 1);
configMap.put("outputEncoderFormat", 0);
configMap.put("wordDurationForceAlign", "false");
bodyMap.put("data", dataMap);
bodyMap.put("config", configMap);
RequestEntity requestEntity = new StringRequestEntity(JSONObject.toJSONString(bodyMap),"application/json" ,"UTF-8");
postMethod.setRequestEntity(requestEntity);
HttpClient httpClient = new HttpClient();
int ret = httpClient.executeMethod(postMethod);
String rpsContent = postMethod.getResponseBodyAsString();
if (ret == 200) {
System.out.println(rpsContent);
} else {
System.out.println("callApi failed: ret =" + ret + " rsp=" + rpsContent);
}
}
註意:
上述代碼中xxxxx對應的值請根據實際情況填寫,具體取值請參見創建非同步任務。
2.2.2查詢非同步任務狀態
用戶創建非同步任務後,可以通過調用該介面,獲取任務處理狀態等信息。任務處理完成後,會返回任務的下載地址,直接訪問該地址即可下載文件。
通過access_token信息,和創建非同步任務獲取到的taskId發送HTTPS POST查詢歌聲合成非同步任務狀態。
示例代碼(Java)如下所示:
其中requestUrl = "https://audioeditor-api-drcn.cloud.huawei.com/v1/audioeditor/gateway/ai/ttsing/async/task/status"。
/**
* 調用查詢非同步任務狀態介面
* @param taskId 創建非同步任務獲取的taskId
* @throws Exception IO異常
*/
private static void queryAsyncTaskInfo(String taskId) throws Exception {
// 設置請求header
PostMethod postMethod = new PostMethod(requestUrl);
// 設置文本類型(String),例:"application/json;charset=utf-8"
postMethod.setRequestHeader("Content-Type", contentType);
// 設置請求ID(String),例:"9af1aeda-531b-407a-80b4-65b40ef77bd6"
postMethod.setRequestHeader("X-Request-ID", requestId);
// 設置App包名(String),例:"com.huawei.demo"
postMethod.setRequestHeader("X-Package-Name", pacageName);
// 設置App所在國家(String),例:"cn"
postMethod.setRequestHeader("X-Country-Code", countryCode);
// 設置App標識(String),例:"9af1aeda-531b-407a-80b4-65b40ef77bd6"
postMethod.setRequestHeader("HMS-APPLICATION-ID", applicationId);
// 設置證書指紋(String),例:"xxxxxxxxxxxxxxx"
postMethod.setRequestHeader("certFingerprint", certFingerprint);
// 設置動態獲取的AccessToken(String)
postMethod.setRequestHeader("Authorization","Bearer " + accessToken);
// 設置請求body
Map<String, Object> bodyMap = new HashMap<>();
// taskId對應的值是創建非同步任務時返回的任務ID(taskId)
bodyMap.put("taskId", taskId);
RequestEntity requestEntity = new StringRequestEntity(JSONObject.toJSONString(bodyMap),"application/json" ,"UTF-8");
postMethod.setRequestEntity(requestEntity);
HttpClient httpClient = new HttpClient();
int ret = httpClient.executeMethod(postMethod);
String rpsContent = postMethod.getResponseBodyAsString();
if (ret == 200) {
System.out.println(rpsContent);
} else {
System.out.println("callApi failed: ret =" + ret + " rsp=" + rpsContent);
}
}
註意:
上述代碼中xxxxx對應的值請根據實際情況填寫,具體取值請參見查詢非同步任務狀態。
2.2.3取消非同步任務
用戶創建歌聲合成非同步任務後,可以通過調用此介面,取消指定非同步任務並刪除相應任務數據。
通過access_token信息和創建非同步任務獲取到的taskId,發送HTTPS POST取消非同步任務。
示例代碼(Java)如下所示:
其中requestUrl = "https://audioeditor-api-drcn.cloud.huawei.com/v1/audioeditor/gateway/ai/ttsing/async/task/cancel"。
/**
* 調用取消非同步任務介面
* @param taskId 創建非同步任務獲取的taskId
* @throws Exception IO異常
*/
private static void cancelAsyncTask(String taskId) throws Exception {
// 設置請求header
PostMethod postMethod = new PostMethod(requestUrl);
// 設置文本類型(String),例:"application/json;charset=utf-8"
postMethod.setRequestHeader("Content-Type", contentType);
// 設置請求ID(String),例:"9af1aeda-531b-407a-80b4-65b40ef77bd6"
postMethod.setRequestHeader("X-Request-ID", requestId);
// 設置App包名(String),例:"com.huawei.demo"
postMethod.setRequestHeader("X-Package-Name", pacageName);
// 設置App所在國家(String),例:"cn"
postMethod.setRequestHeader("X-Country-Code", countryCode);
// 設置App標識(String),例:"9af1aeda-531b-407a-80b4-65b40ef77bd6"
postMethod.setRequestHeader("HMS-APPLICATION-ID", applicationId);
// 設置證書指紋(String),例:"xxxxxxxxxxxxxxx"
postMethod.setRequestHeader("certFingerprint", certFingerprint);
// 設置動態獲取的AccessToken(String)
postMethod.setRequestHeader("Authorization","Bearer " + accessToken);
// 設置請求body
Map<String, Object> bodyMap = new HashMap<>();
// taskId對應的值是創建非同步任務時返回的任務ID(taskId)
bodyMap.put("taskId", taskId);
RequestEntity requestEntity = new StringRequestEntity(JSONObject.toJSONString(bodyMap),"application/json" ,"UTF-8");
postMethod.setRequestEntity(requestEntity);
HttpClient httpClient = new HttpClient();
int ret = httpClient.executeMethod(postMethod);
String rpsContent = postMethod.getResponseBodyAsString();
if (ret == 200) {
System.out.println(rpsContent);
} else {
System.out.println("callApi failed: ret =" + ret + " rsp=" + rpsContent);
}
}
註意:
上述代碼中xxxxx對應的值請根據實際情況填寫,具體取值請參見取消非同步任務。
除了歌聲合成能力,音頻編輯服務還提供音頻基礎剪輯、AI配音、音源分離、空間渲染、變聲降噪等音頻處理能力,更多信息可以訪問官網獲得。
瞭解更多詳情>>
訪問華為開發者聯盟官網
獲取開髮指導文檔
華為移動服務開源倉庫地址:GitHub、Gitee
關註我們,第一時間瞭解 HMS Core 最新技術資訊~