虛擬偶像的歌聲原來是這樣生成的!

  • 2022 年 7 月 27 日
  • 筆記

HMS Core音頻編輯服務(Audio Editor Kit)6.6.0版本上線,新增歌聲合成能力。通過歌詞和曲調,結合不同的曲風讓機器也能生成真實度極高的歌聲。支援字級別輸入歌詞進行音素轉換,生成對應歌詞的歌聲,可靈活調整音高、滑音、呼吸音、顫音等細節參數,讓歌聲更真實。

歌聲合成服務可廣泛應用於音影片創意製作、影音娛樂、音樂教育、虛擬偶像等領域。例如,在音樂創作或短影片創意編輯時,歌聲合成服務可以助力用戶自由創作合成歌曲,使創作更加豐富多彩。在虛擬偶像領域,通過歌聲合成,可以讓虛擬人擁有特定音色歌唱能力,使其形象更生動。在音樂遊戲或者歌唱教育中,歌聲合成可以迅速生成標準參考聲音,提高音頻製作效率節省人力成本。

歌聲合成效果

聽到了歌聲合成媲美真人的歌唱效果,是否迫不及待想上手使用了呢,以下是歌聲合成的具體集成方法。快來親自集成試試吧!

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調用同步介面(流式)

通過以上步驟獲取的access_token資訊,發送HTTPS POST調用同步介面(流式)。

示例程式碼(Java)如下所示:

其中requestUrl = “//audioeditor-api-drcn.cloud.huawei.com/v1/audioeditor/gateway/ai/ttsing/sync“。

/**
     * 調用同步介面(流式)
     * @param accessToken 根據clientId和密鑰獲取的token
     * @throws Exception IO異常
     */
    private static void syncTask(String accessToken) throws Exception {
        // 設置請求header
        PostMethod postMethod = new PostMethod(requestUrl);
        postMethod.setRequestHeader("Content-Type","application/json;charset=utf-8");
        postMethod.setRequestHeader("X-Request-ID","9af1aeda-531b-407a-80b4-65b40ef77bd6");
        postMethod.setRequestHeader("X-Package-Name","com.huawei.demo");
        postMethod.setRequestHeader("X-Country-Code","cn");
        postMethod.setRequestHeader("HMS-APPLICATION-ID","123456");
        postMethod.setRequestHeader("certFingerprint","xxxxx");
        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);
        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是要保存文件的路徑(含文件名、後綴)
                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());
        }
    }

2.2非同步介面

2.2.1創建非同步任務

通過access_token資訊,發送HTTPS POST創建歌聲合成非同步任務。

  /**
     * 調用創建非同步任務介面
     * @param accessToken 根據clientId和密鑰獲取的token
     * @throws Exception IO異常
     */
    private static void creatAsyncTask(String accessToken) throws Exception {
        // 設置請求header
        PostMethod postMethod = new PostMethod(requestUrl);
        postMethod.setRequestHeader("Content-Type","application/json;charset=utf-8");
        postMethod.setRequestHeader("X-Request-ID","9af1aeda-531b-407a-80b4-65b40ef77bd6");
        postMethod.setRequestHeader("X-Package-Name","com.huawei.demo");
        postMethod.setRequestHeader("X-Country-Code","cn");
        postMethod.setRequestHeader("HMS-APPLICATION-ID","123456");
        postMethod.setRequestHeader("certFingerprint","xxxxx");
        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);
        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);
        }
    }

2.2.2查詢非同步任務狀態

通過access_token資訊,發送HTTPS POST查詢歌聲合成非同步任務狀態。

  /**
     * 調用查詢非同步任務狀態介面
     * @param accessToken 根據clientId和密鑰獲取的token
     * @throws Exception IO異常
     */
    private static void queryAsyncTaskInfo(String accessToken) throws Exception {
        // 設置請求header
        PostMethod postMethod = new PostMethod(requestUrl);
        postMethod.setRequestHeader("Content-Type","application/json;charset=utf-8");
        postMethod.setRequestHeader("X-Request-ID","9af1aeda-531b-407a-80b4-65b40ef77bd6");
        postMethod.setRequestHeader("X-Package-Name","com.huawei.demo");
        postMethod.setRequestHeader("X-Country-Code","cn");
        postMethod.setRequestHeader("HMS-APPLICATION-ID","123456");
        postMethod.setRequestHeader("certFingerprint","xxxxx");
        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);
        }
    }

2.2.3取消非同步任務

通過access_token資訊,發送HTTPS POST取消非同步任務。

  /**
     * 調用取消非同步任務介面
     * @param accessToken 根據clientId和密鑰獲取的token
     * @throws Exception IO異常
     */
    private static void cancelAsuncTask(String accessToken) throws Exception {
        // 設置請求header
        PostMethod postMethod = new PostMethod(requestUrl);
        postMethod.setRequestHeader("Content-Type","application/json;charset=utf-8");
        postMethod.setRequestHeader("X-Request-ID","9af1aeda-531b-407a-80b4-65b40ef77bd6");
        postMethod.setRequestHeader("X-Package-Name","com.huawei.demo");
        postMethod.setRequestHeader("X-Country-Code","cn");
        postMethod.setRequestHeader("HMS-APPLICATION-ID","123456");
        postMethod.setRequestHeader("certFingerprint","xxxxx");
        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);
        }
    }

除了歌聲合成能力,音頻編輯服務還提供音頻基礎編輯、AI配音伴奏提取、空間渲染、變聲降噪等豐富的音頻處理能力,為全球開發者提供性能優異、簡單易用、開放性強的介面,幫助開發者輕鬆高效構建應用音頻編輯能力。

了解更多詳情>>

訪問華為開發者聯盟官網
獲取開發指導文檔
華為移動服務開源倉庫地址:GitHubGitee

關注我們,第一時間了解 HMS Core 最新技術資訊~