AI 赋能音乐创作,人人都是音视频创作者
- 2022-11-23 贵州
本文字数:8890 字
阅读完需:约 29 分钟
华为 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 配音、音源分离、空间渲染、变声降噪等音频处理能力,更多信息可以访问官网获得。
了解更多详情>>
获取开发指导文档
关注我们,第一时间了解 HMS Core 最新技术资讯~
HMS Core
HMS Core技术团队。 2022-06-16 加入
分享最新的技术干货,带来最全的能力应用场景,更新热门开发者圈子活动。与开发者一起,同成长,共精彩。
评论